Android之Service详解(二)
2016-10-25 16:42
381 查看
上一篇Android之Service详解(一)讲解了Service的定义、开启和关闭以及生命周期,接下来讲解Service与Activity间的通信,以及IntentService等内容。
一、Service与Activity间的通信
在上一篇中我们学习了启动和停止服务的方法,不知道你有没有发现,虽然服务是在活动里启动的,但在启动了服务之后,活动与服务基本就没有什么关系了。确实如此,我们在活动里调用了startService()方法来启动MyService 这个服务,然后MyService 的onCreate()和onStartCommand()方法就会得到执行。之后服务会一直处于运行状态,但具体运行的是什么逻辑,活动就控制不了了。这就类似于活动通知了服务一下:“你可以启动了!”然后服务就去忙自己的事情了,但活动并不知道服务到底去做了什么事情,以及完成的如何。
那么有没有什么办法能让活动和服务的关系更紧密一些呢?例如在活动中指挥服务去干什么,服务就去干什么。当然可以,这就需要借助我们刚刚忽略的onBind()方法了。
比如说目前我们希望在MyService 里提供一个下载功能,然后在活动中可以决定何时开始下载,以及随时查看下载进度。实现这个功能的思路是创建一个专门的Binder 对象来对下载功能进行管理,修改MyService 中的代码,如下所示:
可以看到,这里我们新建了一个DownloadBinder 类,并让它继承自Binder,然后在它的内部提供了开始下载以及查看下载进度的方法。当然这只是两个模拟方法,并没有实现真正的功能,我们在这两个方法中分别打印了一行日志。
接着,在MyService 中创建了DownloadBinder 的实例,然后在onBind()方法里返回了这个实例,这样MyService 中的工作就全部完成了。
可以看到,这里我们首先创建了一个ServiceConnection 的匿名类,在里面重写了onServiceConnected()方法和onServiceDisconnected()方法,这两个方法分别会在活动与服务成功绑定以及解除绑定的时候调用。在onServiceConnected()方法中,我们又通过向下转型得到了DownloadBinder 的实例,有了这个实例,活动和服务之间的关系就变得非常紧密了。
现在我们可以在活动中根据具体的场景来调用DownloadBinder 中的任何public 方法,即实现了指挥服务干什么,服务就去干什么的功能。这里仍然只是做了个简单的测试,在onServiceConnected()方法中调用了DownloadBinder 的startDownload()和getProgress()方法。
当然,现在活动和服务其实还没进行绑定呢,这个功能是在Bind Service 按钮的点击事件里完成的。可以看到,这里我们仍然是构建出了一个Intent 对象,然后调用bindService()方法将MainActivity 和MyService 进行绑定。bindService()方法接收三个参数,第一个参数就是刚刚构建出的Intent 对象,第二个参数是前面创建出的ServiceConnection 的实例,第三个参数则是一个标志位,这里传入BIND_AUTO_CREATE 表示在活动和服务进行绑定后自动创建服务。这会使得MyService 中的onCreate()方法得到执行,但onStartCommand()方法不会执行。
然后如果我们想解除活动和服务之间的绑定该怎么办呢?调用一下unbindService()方法就可以了,这也是Unbind Service 按钮的点击事件里实现的功能。
二、Service生命周期(二)
上一篇讲解了基本的Service(Bound Service)生命周期,这里讲结合Unbound Service一起讲解。
这两条路径并不是毫不相干的:当调用startService()start一个Service后,您仍可以bind该Service。比如,当播放音乐时,需调用startService()启动指定播放的音乐,当需要获取该音乐的播放进度时,有需要调用bindService(),在这种情况下,直到Service被unbind ,调用stopService() 或stopSelf()都不能停止该Service。
实现Service的生命周期回调:
这些生命周期方法在使用时无需调用各自的父类方法。
在两条生命周期路径中,都包含了两个嵌套的生命周期:
1、完整生命周期( entire lifetime ):从onCreate()被调用到onDestroy()返回。与Activity类似,一般在onCreate()中做一些初始化工作,而在onDestroy()做一些资源释放工作。如,若Service在后台播放一个音乐,就需要在onCreate()方法中开启一个线程启动音乐,并在onDestroy()中结束线程。
无论是startService() 还是 bindService()启动Service,onCreate() 和 onDestroy()均会被回调。
2、活动生命周期(active lifetime):从onStartCommand() 或 onBind()回调开始。由相应的startService() 或 bindService()调用。
若是Start Service,那么Service的活动生命周期结束就意味着其完整生命周期结束 (the active lifetime ends the same time that the entire lifetime ends),即便onStartCommand()返回后,Service仍处于活动状态;若是bound Service,那么当onUnbind()返回时,Service的活动生命周期结束。
注意:针对Start Service,由于Service中没有类似onStop()的回调,所以在调用stopSelf() 或 stopService()后,只有onDestroy()被回调标志着Service已停止。
三、Service更多技巧
1、向用户发送通知
运行中的Service可以通过Toast Notifications 或 Status Bar Notifications 向用户发送通知。Toast是一个可以短时间弹出的提醒框。二Status Bar是顶部状态栏中出现的太有图标的信息,用户可以通过下拉状态栏获得具体信息并执行某些操作(如启动Activity)。
通常,Status Bar用于通知某些操作已经完成,如下载文件完成。当用户下拉状态栏后,点击该通知,可获取详细内容,如查看该下载的文件。
2、运行前台Service
前台Service用于动态通知消息,如天气预报。该Service不易被kill。前台Service必须提供status bar,只有前台Service被destroy后,status bar才能消失。
举例来说,一个播放音乐的Service必须是前台Service,只有这样用户才能确知其运行状态。为前台Service提供的status bar可以显示当前音乐的播放状态,并可以启动播放音乐的Activity。
调用startForeground()可以启动前台Service。该方法接收两个参数,参数一是一个int型变量,用户指定该通知的唯一性标识,而参数而是一个Notification用于配置status bar,示例如下:
调用stopForeground()来移除(remove)前台Service。该方法需传入一个boolean型变量,表示是否也一并清除status bar上的notification。该方法并不停止Service,如果停止正在前台运行的Service,那么notification 也一并被清除。
参考:
http://www.cnblogs.com/lwbqqyumidi/p/4181185.html
http://blog.csdn.net/vanpersie_9987/article/details/51360245
一、Service与Activity间的通信
在上一篇中我们学习了启动和停止服务的方法,不知道你有没有发现,虽然服务是在活动里启动的,但在启动了服务之后,活动与服务基本就没有什么关系了。确实如此,我们在活动里调用了startService()方法来启动MyService 这个服务,然后MyService 的onCreate()和onStartCommand()方法就会得到执行。之后服务会一直处于运行状态,但具体运行的是什么逻辑,活动就控制不了了。这就类似于活动通知了服务一下:“你可以启动了!”然后服务就去忙自己的事情了,但活动并不知道服务到底去做了什么事情,以及完成的如何。
那么有没有什么办法能让活动和服务的关系更紧密一些呢?例如在活动中指挥服务去干什么,服务就去干什么。当然可以,这就需要借助我们刚刚忽略的onBind()方法了。
比如说目前我们希望在MyService 里提供一个下载功能,然后在活动中可以决定何时开始下载,以及随时查看下载进度。实现这个功能的思路是创建一个专门的Binder 对象来对下载功能进行管理,修改MyService 中的代码,如下所示:
public class MyService extends Service { private DownloadBinder mBinder = new DownloadBinder(); class DownloadBinder extends Binder { public void startDownload() { Log.d("MyService", "startDownload executed"); } public int getProgress() { Log.d("MyService", "getProgress executed"); return 0; } } @Override public IBinder onBind(Intent intent) { return mBinder; } …… }
可以看到,这里我们新建了一个DownloadBinder 类,并让它继承自Binder,然后在它的内部提供了开始下载以及查看下载进度的方法。当然这只是两个模拟方法,并没有实现真正的功能,我们在这两个方法中分别打印了一行日志。
接着,在MyService 中创建了DownloadBinder 的实例,然后在onBind()方法里返回了这个实例,这样MyService 中的工作就全部完成了。
public class MainActivity extends Activity implements OnClickListener { private Button bindService; private Button unbindService; private MyService.DownloadBinder downloadBinder; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { } @Override public void onServiceConnected(ComponentName name, IBinder service) { downloadBinder = (MyService.DownloadBinder) service; downloadBinder.startDownload(); downloadBinder.getProgress(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bindService = (Button) findViewById(R.id.bind_service); unbindService = (Button) findViewById(R.id.unbind_service); bindService.setOnClickListener(this); unbindService.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.bind_service: Intent bindIntent = new Intent(this, MyService.class); bindService(bindIntent, connection, BIND_AUTO_CREATE); break; case R.id.unbind_service: unbindService(connection); break; default: break; } } }
可以看到,这里我们首先创建了一个ServiceConnection 的匿名类,在里面重写了onServiceConnected()方法和onServiceDisconnected()方法,这两个方法分别会在活动与服务成功绑定以及解除绑定的时候调用。在onServiceConnected()方法中,我们又通过向下转型得到了DownloadBinder 的实例,有了这个实例,活动和服务之间的关系就变得非常紧密了。
现在我们可以在活动中根据具体的场景来调用DownloadBinder 中的任何public 方法,即实现了指挥服务干什么,服务就去干什么的功能。这里仍然只是做了个简单的测试,在onServiceConnected()方法中调用了DownloadBinder 的startDownload()和getProgress()方法。
当然,现在活动和服务其实还没进行绑定呢,这个功能是在Bind Service 按钮的点击事件里完成的。可以看到,这里我们仍然是构建出了一个Intent 对象,然后调用bindService()方法将MainActivity 和MyService 进行绑定。bindService()方法接收三个参数,第一个参数就是刚刚构建出的Intent 对象,第二个参数是前面创建出的ServiceConnection 的实例,第三个参数则是一个标志位,这里传入BIND_AUTO_CREATE 表示在活动和服务进行绑定后自动创建服务。这会使得MyService 中的onCreate()方法得到执行,但onStartCommand()方法不会执行。
然后如果我们想解除活动和服务之间的绑定该怎么办呢?调用一下unbindService()方法就可以了,这也是Unbind Service 按钮的点击事件里实现的功能。
二、Service生命周期(二)
上一篇讲解了基本的Service(Bound Service)生命周期,这里讲结合Unbound Service一起讲解。
这两条路径并不是毫不相干的:当调用startService()start一个Service后,您仍可以bind该Service。比如,当播放音乐时,需调用startService()启动指定播放的音乐,当需要获取该音乐的播放进度时,有需要调用bindService(),在这种情况下,直到Service被unbind ,调用stopService() 或stopSelf()都不能停止该Service。
实现Service的生命周期回调:
int mStartMode; // indicates how to behave if the service is killed IBinder mBinder; // interface for clients that bind boolean mAllowRebind; // indicates whether onRebind should be used @Override public void onCreate() { // The service is being created } @Override public int onStartCommand(Intent intent, int flags, int startId) { // The service is starting, due to a call to startService() return mStartMode; } @Override public IBinder onBind(Intent intent) { // A client is binding to the service with bindService() return mBinder; } @Override public boolean onUnbind(Intent intent) { // All clients have unbound with unbindService() return mAllowRebind; } @Override public void onRebind(Intent intent) { // A client is binding to the service with bindService(), // after onUnbind() has already been called } @Override public void onDestroy() { // The service is no longer used and is being destroyed } }
这些生命周期方法在使用时无需调用各自的父类方法。
在两条生命周期路径中,都包含了两个嵌套的生命周期:
1、完整生命周期( entire lifetime ):从onCreate()被调用到onDestroy()返回。与Activity类似,一般在onCreate()中做一些初始化工作,而在onDestroy()做一些资源释放工作。如,若Service在后台播放一个音乐,就需要在onCreate()方法中开启一个线程启动音乐,并在onDestroy()中结束线程。
无论是startService() 还是 bindService()启动Service,onCreate() 和 onDestroy()均会被回调。
2、活动生命周期(active lifetime):从onStartCommand() 或 onBind()回调开始。由相应的startService() 或 bindService()调用。
若是Start Service,那么Service的活动生命周期结束就意味着其完整生命周期结束 (the active lifetime ends the same time that the entire lifetime ends),即便onStartCommand()返回后,Service仍处于活动状态;若是bound Service,那么当onUnbind()返回时,Service的活动生命周期结束。
注意:针对Start Service,由于Service中没有类似onStop()的回调,所以在调用stopSelf() 或 stopService()后,只有onDestroy()被回调标志着Service已停止。
三、Service更多技巧
1、向用户发送通知
运行中的Service可以通过Toast Notifications 或 Status Bar Notifications 向用户发送通知。Toast是一个可以短时间弹出的提醒框。二Status Bar是顶部状态栏中出现的太有图标的信息,用户可以通过下拉状态栏获得具体信息并执行某些操作(如启动Activity)。
通常,Status Bar用于通知某些操作已经完成,如下载文件完成。当用户下拉状态栏后,点击该通知,可获取详细内容,如查看该下载的文件。
2、运行前台Service
前台Service用于动态通知消息,如天气预报。该Service不易被kill。前台Service必须提供status bar,只有前台Service被destroy后,status bar才能消失。
举例来说,一个播放音乐的Service必须是前台Service,只有这样用户才能确知其运行状态。为前台Service提供的status bar可以显示当前音乐的播放状态,并可以启动播放音乐的Activity。
调用startForeground()可以启动前台Service。该方法接收两个参数,参数一是一个int型变量,用户指定该通知的唯一性标识,而参数而是一个Notification用于配置status bar,示例如下:
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text), System.currentTimeMillis()); Intent notificationIntent = new Intent(this, ExampleActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); notification.setLatestEventInfo(this, getText(R.string.notification_title), getText(R.string.notification_message), pendingIntent); startForeground(ONGOING_NOTIFICATION_ID, notification);
调用stopForeground()来移除(remove)前台Service。该方法需传入一个boolean型变量,表示是否也一并清除status bar上的notification。该方法并不停止Service,如果停止正在前台运行的Service,那么notification 也一并被清除。
参考:
http://www.cnblogs.com/lwbqqyumidi/p/4181185.html
http://blog.csdn.net/vanpersie_9987/article/details/51360245
相关文章推荐
- android中自定义service的详解(例子)
- Android中Service的使用详解和注意点(LocalService)
- Android Service 详解四:开始停止service
- Android Service 详解一:概述
- Android Service 详解三:从类Service派生service
- Android Bind Service机制详解
- Android Service 详解五:前台运行与生命期
- Android Service 详解四:开始停止service
- Android Service 详解
- Android Service 详解五:前台运行与生命期
- Android中RemoteService的使用详解(Aidl、IPC机制)
- Android Service 详解一:概述
- Android Service 详解一:概述
- Android Service 详解四:开始停止service
- Android Service 详解三:从类Service派生service
- Android 四大组件之(2)Service实现原理以及AIDL语言的使用详解
- android service 详解
- Android Service 详解二:创建一个service
- Android Service 详解四:开始停止service
- Android Service 详解五:前台运行与生命期