最近项目要求,需要一个写一个服务一直跑在后台,不被杀死,就算被杀死也要被重启,参考了网上各种资料,最后做个总结。
一、自定义BroadcastReceiver
这个receiver用于监听各种广播,代码如下:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!--开机广播-->
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
<!--屏幕开解锁-->
<intent-filter>
<action android:name="android.intent.action.SCREEN_ON" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SCREEN_OFF" />
</intent-filter>
<!--网络变化-->
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
在自定义的Application里面注册这个广播接收器,因为ACTION_TIME_TICK只能动态注册。
//这个广播动作是以每分钟一次的形式发送。但你不能通过在manifest注册,只能在代码里通过registerReceiver()方法注册.
IntentFilter timeFilter = new IntentFilter(Intent.ACTION_TIME_TICK);
//监听网络变化
IntentFilter connFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); MyReceiver receiver = new MyReceiver();
registerReceiver(receiver, timeFilter);
registerReceiver(receiver, connFilter);
在这个广播接收器中每次接到广播,都要判断service的进程是否还在后台运行,如果没运行,就通过startService方法启动这个服务。
二、保证Service杀不死
以startService()启动service,系统将通过传入的Intent在底层搜索相关符合Intent里面信息的service。
1.在service 的onStartCommand方法里面手动返回TART_STICKY,当service因内存不足被kill,当内存又有的时候,service又被重新创建。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
2.提升service进程优先级
在AndroidManifest.xml文件中对于intent-filter可以通过android:priority = "1000"这个属性设置最高优先级,1000是最高值,如果数字越小则优先级越低。
<service android:name=".service.CommandService"
android:process="com.wyf.service">
<intent-filter android:priority="1000">
<action android:name="com.wyf.service" />
</intent-filter>
</service>
Android中的进程是托管的,当系统进程空间紧张的时候,会依照优先级自动进行进程的回收。Android将进程分为6个等级,它们按优先级顺序由高到低依次是:
前台进程( FOREGROUND_APP)
可视进程(VISIBLE_APP )
次要服务进程(SECONDARY_SERVER )
后台进程 (HIDDEN_APP)
内容供应节点(CONTENT_PROVIDER)
空进程(EMPTY_APP)
当service运行在低内存的环境时,系统将会kill掉一些存在的进程。因此进程的优先级将会很重要,可以使用startForeground API将service放到前台状态。这样在低内存时被kill的几率更低,但是如果在极度极度低内存的压力下,该service还是会被kill掉。
在onStartCommand方法内加入以下代码
startForeground(2, new Notification());
3.在application上添加属性android:persistent="true"
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:persistent="true"
android:sharedUserId="android.uid.system"
android:supportsRtl="true">
这个属性不能乱设置,添加之后就相当于系统级的进程。
4.添加当服务被系统回收之后给发送广播
实现service的onTrimMemory方法
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
Log.d(TAG, "onTrimMemory");
Intent intent = new Intent("com.wyf.service.onTrimMemory");
sendBroadcast(intent);
}
在前面的广播接受器里面添加action
<receiver android:name=".MyReceiver">
<intent-filter >
<action android:name="com.wyf.service.onTrimMemory" />
</intent-filter>
</receiver>
三、总结
这样基本实现了服务的杀死重启,但是杀死之后会过一段时间重启不能马上重启。在网上查找资料据说可以通过守护进程实现,正在研究,以后补充。