创建前台Service
Service几乎都是在后台运行的,一直以来它都是默默地做着辛苦的工作。但是Service的系统优先级还是比较低的,当系统出现内存不足情况时,就有可能会回收掉正在后台运行的Service。如果你希望Service可以一直保持运行状态,而不会由于系统内存不足的原因导致被回收,就可以考虑使用前台Service。前台Service和普通Service最大的区别就在于,它会一直有一个正在运行的图标在系统的状态栏显示,下拉状态栏后可以看到更加详细的信息,非常类似于通知的效果。当然有时候你也可能不仅仅是为了防止Service被回收才使用前台Service,有些项目由于特殊的需求会要求必须使用前台Service,比如说墨迹天气,它的Service在后台更新天气数据的同时,还会在系统状态栏一直显示当前天气的信息,如下图所示:
那么我们就来看一下如何才能创建一个前台Service吧,其实并不复杂,修改MyService中的代码,如下所示:
- public
class MyService extends Service { -
-
public static final String TAG = "MyService"; -
-
private MyBinder mBinder = new MyBinder(); -
-
@Override -
public void onCreate() { -
super.onCreate(); -
Notification notification = new Notification(R.drawable.ic_launcher, -
"有通知到来", System.currentTimeMillis()); -
Intent notificationIntent = new Intent(this, MainActivity.class); -
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, -
notificationIntent, 0); -
notification.setLatestEventInfo(this, "这是通知的标题", "这是通知的内容", -
pendingIntent); -
startForeground(1, notification); -
Log.d(TAG, "onCreate() executed"); -
} -
-
......... -
- }
现在重新运行一下程序,并点击Start Service或BindService按钮,MyService就会以前台Service的模式启动了,并且在系统状态栏会弹出一个通栏图标,下拉状态栏后可以看到通知的详细内容,如下图所示。
在上篇文章中我们知道了,Service其实是运行在主线程里的,如果直接在Service中处理一些耗时的逻辑,就会导致程序ANR。
让我们来做个实验验证一下吧,修改上一篇文章中创建的ServiceTest项目,在MyService的onCreate()方法中让线程睡眠60秒,如下所示:
- public
class MyService extends Service { -
-
...... -
-
@Override -
public void onCreate() { -
super.onCreate(); -
Log.d(TAG, "onCreate() executed"); -
try { -
Thread.sleep(60000); -
} catch (InterruptedException e) { -
e.printStackTrace(); -
} -
} -
-
...... -
- }
重新运行后,点击一下Start Service按钮或BindService按钮,程序就会阻塞住并无法进行任何其它操作,过一段时间后就会弹出ANR的提示框,如下图所示。
之前我们提到过,应该在Service中开启线程去执行耗时任务,这样就可以有效地避免ANR的出现。
那么本篇文章的主题是介绍远程Service的用法,如果将MyService转换成一个远程Service,还会不会有ANR的情况呢?让我们来动手尝试一下吧。
将一个普通的Service转换成远程Service其实非常简单,只需要在注册Service的时候将它的android:process属性指定成:remote就可以了,代码如下所示: