Android Service

来源:互联网 发布:6寸windows平板 编辑:程序博客网 时间:2024/06/11 01:59

 在Android组件中,service一是用于在后台处理一些不需要user看到的事件,比如有一些只有在AP启动的时候才听的action,可以动态的在service里来监听,动态注册receiver,还有一些需要receiver来驱动的事件,由于receiver不适合处理复杂耗时的逻辑,可以start service来做UI显示前的处理,在需要和适合显示的时候才发消息给UI 来显示。再一个就是返回bind接口供AP 来调用需要的API 。那么首先第一个问题,怎么启动一个service呢?

        启动一个service有两种方式,context.startService() and context.bindService(),下面就分别介绍一下。

        1.  Start service.

[java] view plain copy
  1. <span style="font-size:18px;">  private void startSimpleService() {  
  2.         Log.d(TAG, "startSimpleService ****");  
  3.         Intent service = new Intent(this, MySimpleService.class);  
  4.         this.startService(service);  
  5.     }</span>  
        调用startService后会做些什么呢?首先如果service还没有create,系统会调用service的onCreate(),然后onStartCommand(),这个时候service处于foreground状态,具有比较高的优先级,不会被系统kill掉。在2.0之前的版本里会用到onStart()这个api,但是之后的版本里这个api就被弃用了,因为android是系统来管理内存的,在系统内存紧张的时候会根据优先级kill掉一些优先级比较低的进程,而service在start后就不再是foreground状态,优先级就会降低,这个时候就容易被系统kill掉,而在2.0之前的版本,service在被系统kill掉之后,在系统内存不紧张的时候被restart,这个时候service的onCreate被调用,但是onStart并不会被调用,因为没有startService,这个时候就会比较尴尬,service create了,但是却没事做,也不知道什么时候stop。因此在2.0之后的版本里使用了onStartCommand()

[java] view plain copy
  1. <span style="font-size:18px;">  @Override  
  2.     public int onStartCommand(Intent intent, int flags, int startId) {  
  3.         // TODO Auto-generated method stub  
  4.         Log.d(TAG, "onStartCommand =====");  
  5.         return Service.START_STICKY;  
  6.     }</span>  
不同的地方是,它可以return一个int值,START_STICKY,START_NOT_STICKY,START_REDELIVER_INTENT.

START_STICKY: 和原来的onStart类似,在被系统kill掉后会restart,但是不同的是onStartCommand会被调用并传入一个null值作为intent,这个时候service就可以对这种case做出处理。

START_NOT_STICKY: 被kill掉后就不会自动restart了。

START_REDELIVER_INTENT: 如果service被kill掉了,系统会把之前的intent再次发送给service,直到service处里完成。

    还有一点就是setforeground()这样的api也被弃用了,foreground状态是具有比较高的优先级的,有些开发者为了避免自己的service由于优先级太低被系统kill掉,就一直让自己的service跑在foreground状态,这显然是不合适的,这样系统的自动回收机制就被废掉了,大量的service占用了资源却不能被kill掉。在后来的版本里foreground的要有一个notification通知User,有一个service在foreground状态。

    最后,start的service必需在不需要的时候主动stop掉,避免占用太多资源。

    2. bind service

可以得到从service返回的bind接口,从而可以调用接口中的api。如果service没有create,在第一个process bind上来的时候会create,在最后一个process unbind后会destroy掉,因此,在使用完后要及时的unbind,避免占用资源。和start不同,bind的时候会调用service的onBind接口。

//MySimpleService

[java] view plain copy
  1. public class MyBinder extends Binder {  
  2.       
  3.     public String getString() {  
  4.         return "simple test";  
  5.     }  
  6. }  
  7.   
  8. private final MyBinder myBinder = new MyBinder();  
  9. @Override  
  10. public IBinder onBind(Intent arg0) {  
  11.     // TODO Auto-generated method stub  
  12.     Log.d(TAG, "onBind =====");  
  13.     return myBinder;  
  14. }  

//MainActivity

[java] view plain copy
  1. MyBinder mBinder = null;  
  2. private ServiceConnection simpleConn = new ServiceConnection() {  
  3.   
  4.     @Override  
  5.     public void onServiceConnected(ComponentName name, IBinder service) {  
  6.         // TODO Auto-generated method stub  
  7.         Log.d(TAG, "onServiceConnected ***");  
  8.         mBinder = (MyBinder)service;  
  9.         Log.d(TAG, mBinder.getString() + "****");  
  10.     }  
  11.   
  12.     @Override  
  13.     public void onServiceDisconnected(ComponentName name) {  
  14.         // TODO Auto-generated method stub  
  15.         Log.d(TAG, "onServiceDisconnected ***");  
  16.     }  
  17.       
  18. };  
  19.   
  20. private void bindSimpleService() {  
  21.     Intent service = new Intent(this, MySimpleService.class);  
  22.     this.bindService(service, simpleConn, Service.BIND_AUTO_CREATE);  
  23. }  
  24.   
  25. private void unbindSimpleService() {  
  26.     this.unbindService(simpleConn);  
  27. }  


    最后需要说明一点,service不是一个子线程,如果有耗时的操作应该放到子线程里处理,如果service长时间被block,会有ANR的情况。
0 0