什么是Service
Service提供了两个主要的功能:
- 可以让程序在后台一直做它想要做的事情,即使当前没有与用户进行交互。(对应context.startService()的启动方式)。
- 实现了某些功能已供其他程序调用的工具,并可保持长期连接进行交互。(对应context.bindService()的启动方式)。
Service的生命周期(对应两种启动方式)
- onCreate () 首次创建服务时,系统将调用此方法来执行一次性设置程序(在调用 onStartCommand() 或onBind() 之前)。如果服务已在运行,则不会调用此方法,该方法只调用一次。
- onBind(Intent intent) 当整个系统的内存不足,并且正在运行的进程应减少其内存使用量时,将调用此方法。尽管没有定义确切的调用点,但是通常会在杀死所有后台进程时发生。也就是说,在达到终止进程的目的之前,我们要避免终止承载服务和前台UI的进程。 您应该实现此方法以释放可能要保留的所有缓存或其他不必要的资源。从此方法返回后,系统将为您执行垃圾回收。
- onStartCommand (Intent intent, int flags, int startId)
- intent :启动时,启动组件传递过来的Intent,如Activity可利用Intent封装所需要的参数并传递给Service
- flags:表示启动请求时是否有额外数据,可选值有 0,START_FLAG_REDELIVERY,START_FLAG_RETRY,0代表没有,它们具体含义如下: START_FLAG_REDELIVERY 这个值代表了onStartCommand方法的返回值为 START_REDELIVER_INTENT,而且在上一次服务被杀死前会去调用stopSelf方法停止服务。其中START_REDELIVER_INTENT意味着当Service因内存不足而被系统kill后,则会重建服务,并通过传递给服务的最后一个 Intent 调用 onStartCommand(),此时Intent时有值的。 START_FLAG_RETRY 该flag代表当onStartCommand调用后一直没有返回值时,会尝试重新去调用onStartCommand()。
- startId : 指明当前服务的唯一ID,与stopSelfResult (int startId)配合使用,stopSelfResult 可以更安全地根据ID停止服务。
4.onRebind(Intent intent) 仅当onUnbind(Intent)的实现被重写以返回true时,才调用此方法。
5.onUnbind(Intent intent) 当所有客户端都与服务发布的特定接口断开连接时调用。 默认实现不执行任何操作,并返回false。
6.onDestroy () 当运行的设备配置发生更改时,系统调用此方法。与Activity等其他组件不同,当这个回调发生时Service不会重走生命周期。
Service的使用
1.首先我们需要创建一个继承了android.app.Service的类。
2.AS通常会在我们创建service类后自动在清单文件内加入service的声明,若没有的话就需要我们手动添加。
<service android:name=".TestService"/> android:exported:代表是否能被其他应用隐式调用,其默认值是由service中有无intent-filter决定的,如果有intent-filter,默认值为true,否则为false。为false的情况下,即使有intent-filter匹配,也无法打开,即无法被其他应用隐式调用。
android:name:对应Service类名
android:permission:是权限声明
android:process:是否需要在单独的进程中运行,当设置为android:process=”:remote”时,代表Service在单独的进程中运行。注意“:”很重要,它的意思是指要在当前进程名称前面附加上当前的包名,所以“remote”和”:remote”不是同一个意思,前者的进程名称为:remote,而后者的进程名称为:App-packageName:remote。 android:isolatedProcess :设置 true 意味着,服务会在一个特殊的进程下运行,这个进程与系统其他进程分开且没有自己的权限。与其通信的唯一途径是通过服务的API(bind and start)。
android:enabled:是否可以被系统实例化,默认为 true因为父标签 也有 enable 属性,所以必须两个都为默认值 true 的情况下服务才会被激活,否则不会激活。
3.在activity或其他上下文中启动service。
启动服务
startService(new Intent(this, TestService.class));
绑定服务
//创建一个ServiceConnection,可以在回调方法中进行逻辑处理
private Myconnection mConnection;
class Myconnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected ComponentName : " + name + " IBinder : " + service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected ComponentName : " + name);
}
}
//绑定服务
bindService(new Intent(this, TestService.class), mConnection, Context.BIND_AUTO_CREATE);
解绑服务
unbindService(mConnection);
停止服务
stopService(new Intent(this, TestService.class));
开启前台服务
前台服务是那些被认为用户知道且在系统内存不足的时候不允许系统杀死的服务。前台服务必须给状态栏提供一个通知。 最常见的表现形式就是音乐播放服务,应用程序后台进行时,用户可以通过通知栏,知道当前播放内容,并进行暂停,继续,切歌等相关操作。 startForegroundService(new Intent(this, TestService.class)); 启动前台服务后必须在service中创建并其他一个前台的通知。否则程序会出现错误。
startForeground(NOTIFICATION_ID,notification);
停止前台服务
在服务停止时需要移除通知。可以写在service的ondestroy当中。
stopForeground(true);
什么是IntentService
android.app.IntentService 的本质就是一个 android.app.Service。 它需要在 AndroidManifest.xml 中注册 <service /> 节点,并可以 startService() 的形式启动。它是Android官方引入的用于执行“耗时任务”的服务抽象类。 传统的 Service 里的代码都是运行在主线程里的,而对于服务这种天生就被设计成更适合“在后台默默工作”的机制来说,我们又常常需要它执行一些耗时型的操作,主线程是不建议做耗时操作的。因此,我们常常会在服务中创建子线程来做耗时操作。而IntentService就是Android官方提供的在普通Service里搭建好了用于执行耗时任务的子线程的特殊Service。
IntentService的原理
IntentService的本质就是一个普通Service里面加装了一套运行在子线程的Handler机制。
IntentService的使用
IntentService的启动和普通的service一致,onHandleIntent(Intent intent)是执行在子线程中的,所以我们可以把耗时操作放在这个回调中。 其他的生命周期都是在主线程当中,我们连续调用了五次startService(intent)之后,onStartCommand依次被调用了五次,然后依次执行了onHandleIntent五次,这样就依次完成了job,当最后一个job完成,也就是在最后一次onHandleIntent调用完成之后,整个IntentService的工作都完成,执行onDestroy回调方法,IntentService销毁。 所以IntentService在onHandleIntent执行完成后是会自动销毁的。