简介
Android系统的后台服务组件,适用于无界面、长时间运行的场景
特点
后台运行,没有用户界面,不可交互;
比非活动的Activity优先级高,被系统回收可能性小;
被回收后可以自动恢复;
进程间通讯
生命周期
void onCreate()
Service第一次创建时调用,只会被调用一次
int onStartCommand(Intent intent, int flags, int startId)
每次客户端调用startService时调用,可以被调用多次,startId表示被调用的次数,0开始
START_STICKY:kill后,重启,intent值为null
START_NOT_STICKY:kill后,不重启
START_REDELIVER_INTENT: kill后,重启,intent值保留
START_STICKY_COMPATIBILITY: START_STICKY的兼容版本,不一定保证能重启
IBinder onBind(Intent intent)
客户端绑定时调用,返回Ibinder对象用于通讯
boolean onUnbind(Intent intent)
解绑
void onDestroy()
Service销毁时调用
示例
public class MyService extends Service {
private final String TAG = MyService.class.getSimpleName();
private MyBinder mMyBinder = new MyBinder();
public MyService() {
}
@Override
public void onCreate() {
Log.d(TAG, "onCreate");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand intent:" + intent + " startId:" + startId);
return super.onStartCommand(intent, flags, startId);
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind");
return mMyBinder;
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy");
super.onDestroy();
}
public class MyBinder extends Binder {
public void test(String test){
Log.d(TAG,"test - :" + test.length());
}
}
}
Mainfest配置
android:name: service名称,必须
android:process:进程名,默认在创建进程,可选
android:enabled:能否被系统实例化,必须
android:exported:能否被其他应用调用,必须
android:permission:权限,可选
intent-filter:意图过滤,可选
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"
android:permission="cfyushi.wzs.123">
<intent-filter>
<action android:name="com.cfyushi.MyService" />
</intent-filter>
</service>
启动和停止
startService(Intent service)
启动服务,可多次调用
stopService(Intent name)
停止服务
Intent的创建
Intent intent = new Intent(); intent.setClassName(this,“类名");
Intent intent = new Intent();intent.setAction(“intent-filter”);intent.setPackage(“应用包名");
Intent intent = new Intent(context, xx.class)
绑定和解绑
boolean bindService(Intent service, ServiceConnection conn, int flags)
客户端调用此接口进行绑定,然后通讯交互
BIND_AUTO_CREATE:当收到绑定请求时,如果服务尚未创建,则即刻创建
BIND_DEBUG_UNBIND:调试解绑接口,仅Debug
BIND_NOT_FOREGROUND系统将阻止驻留该服务的进程具有前台优先级,仅在后台运行
ServiceConnection
private ServiceConnection mSC = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected name:" + name);
mBinder = (MyService.MyBinder)service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected");
mMyService = null;
}
};
void unbindService(ServiceConnection conn)
解绑
IntentService
Service是在UI线程运行,不能处理耗时任务
IntentService会单独创建线程顺序执行Intent请求、执行完毕会自动停止、只需要执行onHandleIntent,其他方法(onBind、onStartCommand)默认实现
public class MyIntentService extends IntentService {
private final String TAG =MyIntentService.class.getSimpleName();
public MyIntentService() {
super("MyIntentService");
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
//获取action和参数
final String action = intent.getAction();
Log.d(TAG, "onHandleIntent action:" + action);
Log.d(TAG, "Thread:" + Thread.currentThread());
final String param1 = intent.getStringExtra("EXTRA_PARAM1");
final String param2 = intent.getStringExtra("EXTRA_PARAM2");
}
}
}
Aidl
支持基本类型、String、List、Map和序列化对象
创建aidl文件
以IMyAidlInterface.aidl为例
interface IMyAidlInterface {
int test(String test);
}
配置Mainfest
<service
android:name=".MyAidlService"
android:enabled="true"
android:exported="true"
android:process=":aidl">
<intent-filter>
<action android:name="com.cfyushi.MyAidlService" />
</intent-filter>
</service>
创建Aidl service
public class MyAidlService extends Service {
private final String TAG = MyAidlService.class.getSimpleName();
public MyAidlService() {
}
@Override
public void onCreate() {
Log.d(TAG, "onCreate");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand intent:" + intent + " startId:" + startId);
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy");
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public IBinder onBind(Intent intent) {
return mStub;
}
IMyAidlInterface.Stub mStub = new IMyAidlInterface.Stub() {
/**
*
* @param test
* @return
* @throws RemoteException
*/
@Override
public int test(String test) throws RemoteException {
String s = null;
Log.d(TAG, "test:" + test);
Log.d(TAG, "s:" + s.length());
return 0;
}
};
}
Binder
Binder是android系统中常用的IPC通讯机制,以内核层Binder驱动为主,Client和Server以此基础进行通讯。
Service保活
程序异常报错、系统回收等原因会导致Service停止工作,因此保活至关重要,以下措施在系统强杀和root流氓软件强杀下无效,也没必要有效,我们不做流氓。
设置为前台进程
Notification.Builder nb = new Notification.Builder(getApplication());
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
nb.setWhen(System.currentTimeMillis());
nb.setTicker("1111");
nb.setContentTitle("sevrice 在前台");
nb.setContentIntent(pendingIntent);
startForeground(1, nb.build());
onStartCommand返回START_STICK
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand intent:" + intent + " startId:" + startId);
return START_STICKY;
//return super.onStartCommand(intent, flags, startId);
}
native层保活
在native层创建守护线程,github地址
还有一些不推荐使用的方法,配置android:persistent=“true”、重写Service的onDestroy方法、服务互绑和监听闹钟及广播