赞
踩
前面写了一个脚本 来执行自动打卡 效果还不错
又学习了一些android的体系知识点
其中就用到了前台服务 利用播放器的模式 来消除被杀的可能
提高Service的优先级
1. 提高Service的优先级:
为防止Service被系统回收,可以尝试通过提高服务的优先级解决,
1000是最高优先级,数字越小,优先级越低
android:priority=“1000”
2.把service写成系统服务
在Manifest.xml文件中设置persistent属性为true,则可使该服务免受out-of-memory killer的影响。
但是这种做法一定要谨慎,系统服务太多将严重影响系统的整体运行效率。
3.将服务改成前台服务foreground service:
重写onStartCommand方法,使用StartForeground(int,Notification)方法来启动service。
注:一般前台服务会在状态栏显示一个通知,最典型的应用就是音乐播放器,只要在播放状态下,
就算休眠也不会被杀,如果不想显示通知,只要把参数里的int设为0即可。
同时,对于通过startForeground启动的service,
onDestory方法中需要通过stopForeground(true)来取消前台运行状态。
4.利用Android的系统广播
利用ANDROID的系统广播检查Service的运行状态,如果被杀掉,就再起来,系统广播是Intent.ACTION_TIME_TICK,这个广播每分钟发送一次,我们可以每分钟检查一次Service的运行状态,如果已经被结束了,就重新启动Service。
当后台服务被回收的时候,我们查看Logcat里面的日志的时候,我们可能会看到如下的日志
Killing ProcessRecord{43a96570 6437:com.example.helloandroid/u0a187}: background ANR
Process com.example.helloandroid (pid 6437) (adj 0) has died.
看日志说明是ANR导致的,如何避免ANR呢?
1.主线程 (“事件处理线程” / “UI线程”) 在5秒内没有响应输入事件
2.BroadcastReceiver 没有在10秒内完成返回
3.在主线程内进行网络操作
4.在主线程内进行一些缓慢的磁盘操作(I/O操作或数据库操作)
至于如何避免ANR的发生,各位尽量避免上面这几种情况出现,基本上就能避开大部分ANR了。
前台服务是那些被认为用户知道(用户所认可的)且在系统内存不足的时候不允许系统杀死的服务。前台服务必须给状态栏提供一个通知,它被放到正在运行(Ongoing)标题之下——这就意味着通知只有在这个服务被终止或从前台主动移除通知后才能被解除。
在一般情况下,Service几乎都是在后台运行,一直默默地做着辛苦的工作。但这种情况下,后台运行的Service系统优先级相对较低,当系统内存不足时,在后台运行的Service就有可能被回收。
那么,如果我们希望Service可以一直保持运行状态且不会在内存不足的情况下被回收时,可以选择将需要保持运行的Service设置为前台服务。
照做音乐播放器的思路,做一下相关的说明,如何使用前台服务
public class MusicPlayerService extends Service { private static final String TAG = MusicPlayerService.class.getSimpleName(); @Override public void onCreate() { super.onCreate(); Log.d(TAG, "onCreate()"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "onStartCommand()"); } @Override public IBinder onBind(Intent intent) { Log.d(TAG, "onBind()"); // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } }
然后创建Notification:
在Service的onStartCommand中添加如下代码:
@Override public int onStartCommand(Intent intent, int flags, int startId) { Log.e(TAG, "-------------onStartCommand"); Context context = this; NotificationCompat.Builder builder = new NotificationCompat.Builder(context); builder.setSmallIcon(R.mipmap.timer_task); builder.setContentTitle("新消息").setContentText("这是一条定时任务"); builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.timer_task)); // 8.0设置Notification的Channel_ID,否则不能正常显示 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { builder.setChannelId("notification_id"); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); NotificationChannel channel = new NotificationChannel("notification_id", "notification_name", NotificationManager.IMPORTANCE_LOW); assert notificationManager != null; notificationManager.createNotificationChannel(channel); } //启用前台服务 其目的是为了保活 提高Service的优先级 startForeground(0, builder.build()); }
在完成Notification通知消息的构建后,
在Service的onStartCommand中可以使用startForeground方法来让Android服务运行在前台。
如果需要停止前台服务,可以使用stopForeground来停止正在运行的前台服务。
@Override
public void onDestroy() {
//停止服务
stopForeground(true);
super.onDestroy();
Log.e(TAG, "-------------onDestroy");
}
前台服务与普通服务的区别?
1.前台Service的系统优先级更高、不易被回收;
2.前台Service会一直有一个正在运行的图标在系统的状态栏显示,下拉状态栏后可以看到更加详细的信息,非常类似于通知的效果。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。