Android Service的两种启动方式

参考连接html

1. 概念java

开始,先稍稍讲一点android中Service的概念和用途吧~android

Service分为本地服务(LocalService)和远程服务(RemoteService)服务器

一、本地服务依附在主进程上而不是独立的进程,这样在必定程度上节约了资源,另外Local服务由于是在同一进程所以不须要IPC,网络

也不须要AIDL。相应bindService会方便不少。主进程被Kill后,服务便会终止。app

二、远程服务为独立的进程,对应进程名格式为所在包名加上你指定的android:process字符串。因为是独立的进程,所以在Activity所在进程被Kill的时候,该服务依然在运行,dom

不受其余进程影响,有利于为多个进程提供服务具备较高的灵活性。该服务是独立的进程,会占用必定资源,而且使用AIDL进行IPC稍微麻烦一点。异步

按使用方式能够分为如下三种:ide

一、startService 启动的服务:主要用于启动一个服务执行后台任务,不进行通讯。中止服务使用stopService;函数

二、bindService 启动的服务:该方法启动的服务能够进行通讯。中止服务使用unbindService;

三、startService 同时也 bindService 启动的服务:中止服务应同时使用stepService与unbindService

2. Service 与 Thread 的区别

不少时候,你可能会问,为何要用 Service,而不用 Thread 呢,由于用 Thread 是很方便的,比起 Service 也方便多了,下面我详细的来解释一下。

1). Thread:Thread 是程序执行的最小单元,它是分配CPU的基本单位。能够用 Thread 来执行一些异步的操做。

2). Service:Service 是android的一种机制,当它运行的时候若是是Local Service,那么对应的 Service 是运行在主进程的 main 线程上的。如:onCreate,onStart 这些函数在被系统调用的时候都是在主进程的 main 线程上运行的。若是是RemoteService,那么对应的 Service 则是运行在独立进程的 main 线程上。所以请不要把 Service 理解成线程,它跟线程半毛钱的关系都没有!

既然这样,那么咱们为何要用 Service 呢?其实这跟 android 的系统机制有关,咱们先拿 Thread 来讲。Thread 的运行是独立于 Activity 的,也就是说当一个 Activity 被 finish 以后,若是你没有主动中止 Thread 或者 Thread 里的 run 方法没有执行完毕的话,Thread 也会一直执行。所以这里会出现一个问题:当 Activity 被 finish 以后,你再也不持有该 Thread 的引用。另外一方面,你没有办法在不一样的 Activity 中对同一 Thread 进行控制。

举个例子:若是你的 Thread 须要不停地隔一段时间就要链接服务器作某种同步的话,该 Thread 须要在 Activity 没有start的时候也在运行。这个时候当你 start 一个 Activity 就没有办法在该 Activity 里面控制以前建立的 Thread。所以你便须要建立并启动一个 Service ,在 Service 里面建立、运行并控制该 Thread,这样便解决了该问题(由于任何 Activity 均可以控制同一 Service,而系统也只会建立一个对应 Service 的实例)。

所以你能够把 Service 想象成一种消息服务,而你能够在任何有 Context 的地方调用 Context.startService、Context.stopService、Context.bindService,Context.unbindService,来控制它,你也能够在 Service 里注册 BroadcastReceiver,在其余地方经过发送 broadcast 来控制它,固然这些都是 Thread 作不到的。

3.  Service和Activity通讯

       须要用到bindService,经过onBind()方法来实现,看下面bindService的例子

4. Service的生命周期


第一种方式:经过StartService启动Service

经过startService启动后,service会一直无限期运行下去,只有外部调用了stopService()或stopSelf()方法时,该Service才会中止运行并销毁。

要建立一个这样的Service,你须要让该类继承Service类,而后重写如下方法:

  • onCreate()
    1.若是service没被建立过,调用startService()后会执行onCreate()回调;
    2.若是service已处于运行中,调用startService()不会执行onCreate()方法。
    也就是说,onCreate()只会在第一次建立service时候调用,屡次执行startService()不会重复调用onCreate(),此方法适合完成一些初始化工做。

  • onStartCommand()
    若是屡次执行了Context的startService()方法,那么Service的onStartCommand()方法也会相应的屡次调用。onStartCommand()方法很重要,咱们在该方法中根据传入的Intent参数进行实际的操做,好比会在此处建立一个线程用于下载数据或播放音乐等。

  • onBind()
    Service中的onBind()方法是抽象方法,Service类自己就是抽象类,因此onBind()方法是必须重写的,即便咱们用不到。

  • onDestory()
    在销毁的时候会执行Service该方法。

这几个方法都是回调方法,且在主线程中执行,由android操做系统在合适的时机调用。

startService代码实例

建立TestOneService,并在manifest里注册。

须要注意,项目中的每个Service都必须在AndroidManifest.xml中注册才行,因此还须要编辑AndroidManifest.xml文件,代码以下所示:

 1 <?xml version="1.0" encoding="utf-8"?>  
 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
 3  package="com.example.servicetest"  
 4  android:versionCode="1"  
 5  android:versionName="1.0" >  
 6   
 7     <uses-sdk  8         android:minSdkVersion="14"  
 9  android:targetSdkVersion="17" />  
10   
11     <application 12         android:allowBackup="true"  
13  android:icon="@drawable/ic_launcher"  
14  android:label="@string/app_name"  
15  android:theme="@style/AppTheme" >  
16           
17  …… 18   
19         <service android:name="com.example.servicetest.TestOneService" >  
20         </service>  
21     </application>  
22   
23 </manifest>

在MainActivty中操做TestOneService,code以下:

 1 /**  2  * Created by Kathy on 17-2-6.  3  */  4  
 5 public class TestOneService extends Service{  6  
 7  @Override  8  public void onCreate() {  9  Log.i("Kathy","onCreate - Thread ID = " + Thread.currentThread().getId()); 10  super.onCreate(); 11  } 12  
13  @Override 14  public int onStartCommand(Intent intent, int flags, int startId) { 15  Log.i("Kathy", "onStartCommand - startId = " + startId + ", Thread ID = " + Thread.currentThread().getId()); 16  return super.onStartCommand(intent, flags, startId); 17  } 18  
19  @Nullable 20  @Override 21  public IBinder onBind(Intent intent) { 22  Log.i("Kathy", "onBind - Thread ID = " + Thread.currentThread().getId()); 23  return null; 24  } 25  
26  @Override 27  public void onDestroy() { 28  Log.i("Kathy", "onDestroy - Thread ID = " + Thread.currentThread().getId()); 29  super.onDestroy(); 30  } 31 }

在MainActivity中三次startService,以后stopService。

 1 /**  2  * Created by Kathy on 17-2-6.  3  */  4  
 5 public class MainActivity extends AppCompatActivity {  6  
 7  @Override  8  protected void onCreate(Bundle savedInstanceState) {  9  super.onCreate(savedInstanceState); 10  setContentView(R.layout.activity_main); 11  Log.i("Kathy", "Thread ID = " + Thread.currentThread().getId()); 12  Log.i("Kathy", "before StartService"); 13  
14  //连续启动Service 15  Intent intentOne = new Intent(this, TestOneService.class); 16  startService(intentOne); 17  Intent intentTwo = new Intent(this, TestOneService.class); 18  startService(intentTwo); 19  Intent intentThree = new Intent(this, TestOneService.class); 20  startService(intentThree); 21  
22  //中止Service 23  Intent intentFour = new Intent(this, TestOneService.class); 24  stopService(intentFour); 25  
26  //再次启动Service 27  Intent intentFive = new Intent(this, TestOneService.class); 28  startService(intentFive); 29  
30  Log.i("Kathy", "after StartService"); 31  } 32 }

打印出的Log以下:

02-06 15:19:45.090 8938-8938/? I/Kathy: Thread ID = 1
        02-06 15:19:45.090 8938-8938/? I/Kathy: before StartService
        02-06 15:19:45.233 8938-8938/? I/Kathy: onCreate - Thread ID = 1
        02-06 15:19:45.234 8938-8938/? I/Kathy: onStartCommand - startId = 1, Thread ID = 1
        02-06 15:19:45.234 8938-8938/? I/Kathy: onStartCommand - startId = 2, Thread ID = 1
        02-06 15:19:45.235 8938-8938/? I/Kathy: onStartCommand - startId = 3, Thread ID = 1
        02-06 15:19:45.236 8938-8938/? I/Kathy: onDestroy - Thread ID = 1
        02-06 15:19:45.237 8938-8938/? I/Kathy: onCreate - Thread ID = 1
        02-06 15:19:45.237 8938-8938/? I/Kathy: onStartCommand - startId = 1, Thread ID = 1
        02-06 15:19:45.238 8938-8938/? I/Kathy: after StartService

 分析:
1.主线程打印出是1,全部回调方法中打印出的执行线程ID都是1,证实回调方法都是在主线程中执行的
2.三次调用startService,只触发一次onCreate回调,触发了三次onStartCommand回调,且startId分别为1,2,3。证实 屡次startService不会重复执行onCreate回调,但每次都会执行onStartCommand回调

第二种方式:经过bindService启动Service

bindService启动服务特色:
1.bindService启动的服务和调用者之间是典型的client-server模式。调用者是client,service则是server端。service只有一个,但绑定到service上面的client能够有一个或不少个。这里所提到的client指的是组件,好比某个Activity。
2.client能够经过IBinder接口获取Service实例,从而实如今client端直接调用Service中的方法以实现灵活交互,这在经过startService方法启动中是没法实现的。
3.bindService启动服务的生命周期与其绑定的client息息相关。当client销毁时,client会自动与Service解除绑定。固然,client也能够明确调用Context的unbindService()方法与Service解除绑定。当没有任何client与Service绑定时,Service会自行销毁

bindService代码实例

交互界面设计以下:


ActivityA界面布局.png

ActivityB界面布局.png

1.建立一个TestTwoService继承Service(Server)
2.建立ActivityA,能够经过bindService绑定服务(client)
3.建立ActivityB,能够经过bindService绑定服务(client)
4.ActivityA能够跳转到ActivityB

TestTwoService建立以下:
要想让Service支持bindService调用方式,须要作如下事情:
1.在Service的onBind()方法中返回IBinder类型的实例。
2.onBInd()方法返回的IBinder的实例须要可以返回Service实例自己。一般,最简单的方法就是在service中建立binder的内部类,加入相似getService()的方法返回Service,这样绑定的client就能够经过getService()方法得到Service实例了。

 1 /**
 2  * Created by Kathy on 17-2-6.  3  */
 4  
 5 public class TestTwoService extends Service{  6  
 7     //client 能够经过Binder获取Service实例
 8     public class MyBinder extends Binder {  9         public TestTwoService getService() { 10             return TestTwoService.this; 11  } 12  } 13  
14     //经过binder实现调用者client与Service之间的通讯
15     private MyBinder binder = new MyBinder(); 16  
17     private final Random generator = new Random(); 18  
19  @Override 20     public void onCreate() { 21         Log.i("Kathy","TestTwoService - onCreate - Thread = " + Thread.currentThread().getName()); 22         super.onCreate(); 23  } 24  
25  @Override 26     public int onStartCommand(Intent intent, int flags, int startId) { 27         Log.i("Kathy", "TestTwoService - onStartCommand - startId = " + startId + ", Thread = " + Thread.currentThread().getName()); 28         return START_NOT_STICKY; 29  } 30  
31  @Nullable 32  @Override 33     public IBinder onBind(Intent intent) { 34         Log.i("Kathy", "TestTwoService - onBind - Thread = " + Thread.currentThread().getName()); 35         return binder; 36  } 37  
38  @Override 39     public boolean onUnbind(Intent intent) { 40         Log.i("Kathy", "TestTwoService - onUnbind - from = " + intent.getStringExtra("from")); 41         return false; 42  } 43  
44  @Override 45     public void onDestroy() { 46         Log.i("Kathy", "TestTwoService - onDestroy - Thread = " + Thread.currentThread().getName()); 47         super.onDestroy(); 48  } 49  
50     //getRandomNumber是Service暴露出去供client调用的公共方法
51     public int getRandomNumber() { 52         return generator.nextInt(); 53  } 54 }

client端要作的事情:
1.建立ServiceConnection类型实例,并重写onServiceConnected()方法和onServiceDisconnected()方法。
2.当执行到onServiceConnected回调时,可经过IBinder实例获得Service实例对象,这样可实现client与Service的链接。
3.onServiceDisconnected回调被执行时,表示client与Service断开链接,在此能够写一些断开链接后须要作的处理。

建立ActivityA,代码以下:

 1 /**
 2  * Created by Kathy on 17-2-6.  3  */
 4 public class ActivityA extends Activity implements Button.OnClickListener {  5     private TestTwoService service = null;  6     private boolean isBind = false;  7  
 8     private ServiceConnection conn = new ServiceConnection() {  9  @Override 10         public void onServiceConnected(ComponentName name, IBinder binder) { 11             isBind = true; 12             TestTwoService.MyBinder myBinder = (TestTwoService.MyBinder) binder; 13             service = myBinder.getService(); 14             Log.i("Kathy", "ActivityA - onServiceConnected"); 15             int num = service.getRandomNumber(); 16             Log.i("Kathy", "ActivityA - getRandomNumber = " + num); 17  } 18  
19  @Override 20         public void onServiceDisconnected(ComponentName name) { 21             isBind = false; 22             Log.i("Kathy", "ActivityA - onServiceDisconnected"); 23  } 24  }; 25  
26     protected void onCreate(Bundle savedInstanceState) { 27         super.onCreate(savedInstanceState); 28  setContentView(R.layout.activity_a); 29         Log.i("Kathy", "ActivityA - onCreate - Thread = " + Thread.currentThread().getName()); 30  
31         findViewById(R.id.btnBindService).setOnClickListener(this); 32         findViewById(R.id.btnUnbindService).setOnClickListener(this); 33         findViewById(R.id.btnStartActivityB).setOnClickListener(this); 34         findViewById(R.id.btnFinish).setOnClickListener(this); 35  } 36  
37  @Override 38     public void onClick(View v) { 39         if (v.getId() == R.id.btnBindService) { 40             //单击了“bindService”按钮
41             Intent intent = new Intent(this, TestTwoService.class); 42             intent.putExtra("from", "ActivityA"); 43             Log.i("Kathy", "----------------------------------------------------------------------"); 44             Log.i("Kathy", "ActivityA 执行 bindService"); 45  bindService(intent, conn, BIND_AUTO_CREATE); 46         } else if (v.getId() == R.id.btnUnbindService) { 47             //单击了“unbindService”按钮
48             if (isBind) { 49                 Log.i("Kathy", 50                         "----------------------------------------------------------------------"); 51                 Log.i("Kathy", "ActivityA 执行 unbindService"); 52  unbindService(conn); 53  } 54         } else if (v.getId() == R.id.btnStartActivityB) { 55             //单击了“start ActivityB”按钮
56             Intent intent = new Intent(this, ActivityB.class); 57             Log.i("Kathy", 58                     "----------------------------------------------------------------------"); 59             Log.i("Kathy", "ActivityA 启动 ActivityB"); 60  startActivity(intent); 61         } else if (v.getId() == R.id.btnFinish) { 62             //单击了“Finish”按钮
63             Log.i("Kathy", 64                     "----------------------------------------------------------------------"); 65             Log.i("Kathy", "ActivityA 执行 finish"); 66             this.finish(); 67  } 68  } 69  
70  @Override 71     protected void onDestroy() { 72         super.onDestroy(); 73         Log.i("Kathy", "ActivityA - onDestroy"); 74  } 75 }

建立ActivityB,代码以下:

 1 /**
 2  * Created by Kathy on 17-2-6.  3  */
 4 public class ActivityB extends Activity implements Button.OnClickListener {  5  
 6     private TestTwoService service = null;  7  
 8     private boolean isBind = false;  9  
10     private ServiceConnection conn = new ServiceConnection() { 11  @Override 12         public void onServiceConnected(ComponentName name, IBinder binder) { 13             isBind = true; 14             TestTwoService.MyBinder myBinder = (TestTwoService.MyBinder)binder; 15             service = myBinder.getService(); 16             Log.i("Kathy", "ActivityB - onServiceConnected"); 17             int num = service.getRandomNumber(); 18             Log.i("Kathy", "ActivityB - getRandomNumber = " + num); 19  } 20  
21  @Override 22         public void onServiceDisconnected(ComponentName name) { 23             isBind = false; 24             Log.i("Kathy", "ActivityB - onServiceDisconnected"); 25  } 26  }; 27  
28  @Override 29     protected void onCreate(Bundle savedInstanceState) { 30         super.onCreate(savedInstanceState); 31  setContentView(R.layout.activity_b); 32  
33         findViewById(R.id.btnBindService).setOnClickListener(this); 34         findViewById(R.id.btnUnbindService).setOnClickListener(this); 35         findViewById(R.id.btnFinish).setOnClickListener(this); 36  } 37  
38  @Override 39     public void onClick(View v) { 40         if(v.getId() == R.id.btnBindService){ 41             //单击了“bindService”按钮
42             Intent intent = new Intent(this, TestTwoService.class); 43             intent.putExtra("from", "ActivityB"); 44             Log.i("Kathy", "----------------------------------------------------------------------"); 45             Log.i("Kathy", "ActivityB 执行 bindService"); 46  bindService(intent, conn, BIND_AUTO_CREATE); 47         }else if(v.getId() == R.id.btnUnbindService){ 48             //单击了“unbindService”按钮
49             if(isBind){ 50                 Log.i("Kathy", "----------------------------------------------------------------------"); 51                 Log.i("Kathy", "ActivityB 执行 unbindService"); 52  unbindService(conn); 53  } 54         }else if(v.getId() == R.id.btnFinish){ 55             //单击了“Finish”按钮
56             Log.i("Kathy", "----------------------------------------------------------------------"); 57             Log.i("Kathy", "ActivityB 执行 finish"); 58             this.finish(); 59  } 60  } 61  @Override 62     public void onDestroy(){ 63         super.onDestroy(); 64         Log.i("Kathy", "ActivityB - onDestroy"); 65  } 66 }

测试步骤1

step1: 点击ActivityA的bindService按钮
step2: 再点击ActivityA的unbindService按钮
Log输出:

 1 02-07 14:09:38.031 1738-1738/com.demo.kathy.demo I/Kathy: ActivityA - onCreate - Thread = main  2 02-07 14:09:39.488 1738-1738/com.demo.kathy.demo I/Kathy: ----------------------------------------------------------------------
 3 02-07 14:09:39.488 1738-1738/com.demo.kathy.demo I/Kathy: ActivityA 执行 bindService  4 02-07 14:09:39.496 1738-1738/com.demo.kathy.demo I/Kathy: TestTwoService - onCreate - Thread = main  5 02-07 14:09:39.497 1738-1738/com.demo.kathy.demo I/Kathy: TestTwoService - onBind - Thread = main  6 02-07 14:09:39.500 1738-1738/com.demo.kathy.demo I/Kathy: ActivityA - onServiceConnected  7 02-07 14:09:39.500 1738-1738/com.demo.kathy.demo I/Kathy: ActivityA - getRandomNumber = -1046987376
 8 02-07 14:09:50.866 1738-1738/com.demo.kathy.demo I/Kathy: ----------------------------------------------------------------------
 9 02-07 14:09:50.866 1738-1738/com.demo.kathy.demo I/Kathy: ActivityA 执行 unbindService 10 02-07 14:09:50.870 1738-1738/com.demo.kathy.demo I/Kathy: TestTwoService - onUnbind - from = ActivityA 11 02-07 14:09:50.871 1738-1738/com.demo.kathy.demo I/Kathy: TestTwoService - onDestroy - Thread = main

总结调用bindService以后发生的事情:
1.client执行bindService()
2.若是Service不存在,则Service执行onCreate(),onBind()
3.client实例ServiceConnection执行onServiceConnected()方法

总结调用unbindService以后发生的事情:
1.client执行unbindService()
2.client与Service解除绑定链接状态
3.Service检测是否还有其余client与其链接,若是没有Service执行onUnbind()和onDestroy()

测试步骤2

step1: 点击ActivityA的bindService按钮
step2: 再点击ActivityA的Finish按钮
Log 输出:

02-07 14:49:16.626 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA - onCreate - Thread = main
02-07 14:49:18.102 12566-12566/com.demo.kathy.demo I/Kathy: ----------------------------------------------------------------------
02-07 14:49:18.102 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA 执行 bindService
02-07 14:49:18.105 12566-12566/com.demo.kathy.demo I/Kathy: TestTwoService - onCreate - Thread = main
02-07 14:49:18.110 12566-12566/com.demo.kathy.demo I/Kathy: TestTwoService - onBind - Thread = main
02-07 14:49:18.112 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA - onServiceConnected
02-07 14:49:18.112 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA - getRandomNumber = -318399886
02-07 14:49:19.540 12566-12566/com.demo.kathy.demo I/Kathy: ----------------------------------------------------------------------
02-07 14:49:19.540 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA 执行 finish
02-07 14:49:19.789 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA - onDestroy
02-07 14:49:19.798 12566-12566/com.demo.kathy.demo I/Kathy: TestTwoService - onUnbind - from = ActivityA
02-07 14:49:19.798 12566-12566/com.demo.kathy.demo I/Kathy: TestTwoService - onDestroy - Thread = main

 

总结:若是client销毁,那么client会自动与Service解除绑定。

测试步骤3

step1: 点击ActivityA的bindService按钮
step2: 点击ActivityA的startActivity B按钮,切换到ActivityB
step3: 点击ActivityB中的bindService按钮
step4: 点击ActivityB中的unbindService按钮
step5: 点击ActivityB中的Finish按钮
step6: 点击ActivityA中的unbindService按钮
获得Log:

02-07 14:55:04.390 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA - onCreate - Thread = main
02-07 14:55:08.191 12566-12566/com.demo.kathy.demo I/Kathy: ----------------------------------------------------------------------
02-07 14:55:08.191 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA 执行 bindService
02-07 14:55:08.197 12566-12566/com.demo.kathy.demo I/Kathy: TestTwoService - onCreate - Thread = main
02-07 14:55:08.198 12566-12566/com.demo.kathy.demo I/Kathy: TestTwoService - onBind - Thread = main
02-07 14:55:08.205 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA - onServiceConnected
02-07 14:55:08.205 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA - getRandomNumber = -706215542
02-07 14:55:23.261 12566-12566/com.demo.kathy.demo I/Kathy: ----------------------------------------------------------------------
02-07 14:55:23.261 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA 启动 ActivityB
02-07 14:55:29.239 12566-12566/com.demo.kathy.demo I/Kathy: ----------------------------------------------------------------------
02-07 14:55:29.239 12566-12566/com.demo.kathy.demo I/Kathy: ActivityB 执行 bindService
02-07 14:55:29.241 12566-12566/com.demo.kathy.demo I/Kathy: ActivityB - onServiceConnected
02-07 14:55:29.241 12566-12566/com.demo.kathy.demo I/Kathy: ActivityB - getRandomNumber = 1827572726
02-07 14:55:33.951 12566-12566/com.demo.kathy.demo I/Kathy: ----------------------------------------------------------------------
02-07 14:55:33.951 12566-12566/com.demo.kathy.demo I/Kathy: ActivityB 执行 unbindService
02-07 14:55:36.645 12566-12566/com.demo.kathy.demo I/Kathy: ----------------------------------------------------------------------
02-07 14:55:36.645 12566-12566/com.demo.kathy.demo I/Kathy: ActivityB 执行 finish
02-07 14:55:36.852 12566-12566/com.demo.kathy.demo I/Kathy: ActivityB - onDestroy
02-07 14:55:43.137 12566-12566/com.demo.kathy.demo I/Kathy: ----------------------------------------------------------------------
02-07 14:55:43.137 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA 执行 unbindService
02-07 14:55:43.143 12566-12566/com.demo.kathy.demo I/Kathy: TestTwoService - onUnbind - from = ActivityA
02-07 14:55:43.143 12566-12566/com.demo.kathy.demo I/Kathy: TestTwoService - onDestroy - Thread = main

 

总结bindService的生命周期:
1.点击ActivityA的bindService按钮
第一次调用bindService会实例化TestTwoService,而后执行其onBind()方法,获得IBinder类型的实例,将其做为参数传入ActivityA的ServiceConnection的onServiceConnected方法中,标志着ActivityA与TestTwoService创建了绑定

2.点击ActivityB中的bindService按钮
因为TestTwoService已处于运行状态,因此再次调用bindService不会从新建立它的实例,因此也不会执行TestTwoService的onCreate()方法和onBind()方法。ActivityB与ActivityA共享IBinder实例。此时有两个client与TestTwoService绑定

3.点击ActivityB中的unbindService按钮
ActivityB与TestTwoService解除了绑定,当没有任何client与Service绑定时,才会执行Service的onUnbind()方法。此时,ActivityA还在绑定链接中,因此不会执行Service的解绑方法

4.点击ActivityA中的unbindService按钮
ActivityA执行unbindService以后,ActivityA与TestTwoService就解除绑定了,这样就没有client与TestTwoService绑定,这时候Android会销毁TestTwoService,在销毁前会先执行TestTwoService的onUnbind()方法,而后才会执行其onDestroy()方法,这样TestService就销毁了。

如何保证Service不被杀死?

1. onStartCommand方式中,返回START_STICKY

首先咱们来看看onStartCommand均可以返回哪些值:

调用Context.startService方式启动Service时,若是Android面临内存匮乏,可能会销毁当前运行的Service,待内存充足时能够重建Service。而Service被Android系统强制销毁并再次重建的行为依赖于Service的onStartCommand()方法的返回值。

  • START_NOT_STICKY
    若是返回START_NOT_STICKY,表示当Service运行的进程被Android系统强制杀掉以后,不会从新建立该Service
    。固然若是在其被杀掉以后一段时间又调用了startService,那么该Service又将被实例化。那什么情境下返回该值比较恰当呢?
    若是咱们某个Service执行的工做被中断几回可有可无或者对Android内存紧张的状况下须要被杀掉且不会当即从新建立这种行为也可接受,那么咱们即可将 onStartCommand的返回值设置为START_NOT_STICKY。
    举个例子,某个Service须要定时从服务器获取最新数据:经过一个定时器每隔指定的N分钟让定时器启动Service去获取服务端的最新数据。当执行到Service的onStartCommand时,在该方法内再规划一个N分钟后的定时器用于再次启动该Service并开辟一个新的线程去执行网络操做。假设Service在从服务器获取最新数据的过程当中被Android系统强制杀掉,Service不会再从新建立,这也不要紧,由于再过N分钟定时器就会再次启动该Service并从新获取数据。

  • START_STICKY
    若是返回START_STICKY,表示Service运行的进程被Android系统强制杀掉以后,Android系统会将该Service依然设置为started状态(即运行状态),可是再也不保存onStartCommand方法传入的intent对象,而后Android系统会尝试再次从新建立该Service,并执行onStartCommand回调方法,可是onStartCommand回调方法的Intent参数为null,也就是onStartCommand方法虽然会执行可是获取不到intent信息。若是你的Service能够在任意时刻运行或结束都没什么问题,并且不须要intent信息,那么就能够在onStartCommand方法中返回START_STICKY,好比一个用来播放背景音乐功能的Service就适合返回该值。

  • START_REDELIVER_INTENT
    若是返回START_REDELIVER_INTENT,表示Service运行的进程被Android系统强制杀掉以后,与返回START_STICKY的状况相似,Android系统会将再次从新建立该Service,并执行onStartCommand回调方法,可是不一样的是,Android系统会再次将Service在被杀掉以前最后一次传入onStartCommand方法中的Intent再次保留下来并再次传入到从新建立后的Service的onStartCommand方法中,这样咱们就能读取到intent参数。只要返回START_REDELIVER_INTENT,那么onStartCommand重的intent必定不是null。若是咱们的Service须要依赖具体的Intent才能运行(须要从Intent中读取相关数据信息等),而且在强制销毁后有必要从新建立运行,那么这样的Service就适合返回START_REDELIVER_INTENT。

2.提升Service的优先级
在AndroidManifest.xml文件中对于intent-filter能够经过android:priority = "1000"这个属性设置最高优先级,1000是最高值,若是数字越小则优先级越低,同时适用于广播。

3.提高Service进程的优先级

当系统进程空间紧张时,会依照优先级自动进行进程的回收。
Android将进程分为6个等级,按照优先级由高到低依次为:

  • 前台进程foreground_app
  • 可视进程visible_app
  • 次要服务进程secondary_server
  • 后台进程hiddena_app
  • 内容供应节点content_provider
  • 空进程empty_app
    可使用startForeground将service放到前台状态,这样低内存时,被杀死的几率会低一些。

4.在onDestroy方法里重启Service
当service走到onDestroy()时,发送一个自定义广播,当收到广播时,从新启动service。

5.系统广播监听Service状态
6.将APK安装到/system/app,变身为系统级应用




FROM: 

Android Service两种启动方式详解(总结版)

http://www.jianshu.com/p/4c798c91a613

 

Android Service彻底解析,关于服务你所需知道的一切(上)

http://blog.csdn.net/guolin_blog/article/details/11952435/

 

Android中Service的使用详解和注意点(LocalService)

http://www.cnblogs.com/linlf03/p/3296323.html

 

Android四大组件:Service服务史上最全面解析

http://www.jianshu.com/p/d963c55c3ab9

相关文章
相关标签/搜索