Android总结篇系列:Android Service

Service作为Android中四大基本组件之一,也是App中经常要用到的。其实,Service这块的知识点还是有些多的,下面要分别一一总结下。

Service通常总是称之为“后台服务”,其中“后台”一词是相对于前台而言的,具体是指其本身的运行并不依赖于用户可视的UI界面,因此,从实际业务需求上来理解,Service的适用场景应该具备以下条件:

1.并不依赖于用户可视的UI界面(当然,这一条其实也不是绝对的,如前台Service就是与Notification界面结合使用的);

2.具有较长时间的运行特性。

1.Service AndroidManifest.xml 声明

一般而言,从Service的启动方式上,可以将Service分为Started Service和Bound Service。无论哪种具体的Service启动类型,都是通过继承Service基类自定义而来。在使用Service时,要想系统能够找到此自定义Service,无论哪种类型,都需要在AndroidManifest.xml中声明,语法格式如下:

 1 <service android:enabled=["true" | "false"]
 2     android:exported=["true" | "false"]
 3     android:icon="drawable resource"
 4     android:isolatedProcess=["true" | "false"]
 5     android:label="string resource"
 6     android:name="string"
 7     android:permission="string"
 8     android:process="string" >
 9     . . .
10 </service>

其中,android:exported属性上一篇博文中对此已进行详尽描述,android:name对应Service类名,android:permission是权限声明,android:process设置具体的进程名称。需要注意的是Service能否单独使用一个进程与其启动方式有关,本后下面会给出具体说明。其他的属性此处与其他组件基本相同,不再过多描述。

注:如果自定义Service没有在AndroidManifest.xml中声明,当具体使用时,不会像Activity那样直接崩溃报错,但是Service没法启动,这反而使得有时候不容易发现忘了声明而一时定位不到问题。

 

2.Started Service

 Started Service相对比较简单,通过context.startService(Intent serviceIntent)启动Service,context.stopService(Intent serviceIntent)停止此Service。当然,在Service内部,也可以通过stopSelf(...)方式停止其本身。

1)Started Service自定义

下面代码片段显示的是一个最基本的Started Service的自定义方式:

 1 public class MyService extends Service {
 2 
 3     public static final String TAG = "MyService";
 4 
 5     @Override
 6     public IBinder onBind(Intent intent) {
 7         return null;
 8     }
 9 
10     @Override
11     public void onCreate() {
12         super.onCreate();
13         Log.w(TAG, "in onCreate");
14     }
15 
16     @Override
17     public int onStartCommand(Intent intent, int flags, int startId) {
18         Log.w(TAG, "in onStartCommand");
19         Log.w(TAG, "MyService:" + this);
20         String name = intent.getStringExtra("name");
21         Log.w(TAG, "name:" + name);
22         return START_STICKY;
23     }
24 
25     @Override
26     public void onDestroy() {
27         super.onDestroy();
28         Log.w(TAG, "in onDestroy");
29     }
30 }

其中,onBind(...)函数是Service基类中的唯一抽象方法,子类都必须重写实现,此函数的返回值是针对Bound Service类型的Service才有用的,在Started Service类型中,此函数直接返回 null 即可。onCreate(...)、onStartCommand(...)和onDestroy()都是Started Service相应生命周期阶段的回调函数。

2) Started Service使用

 1 public class MainActivity extends Activity {
 2 
 3     public static final String TAG = "MainActivity";
 4 
 5     private Button startServiceBtn;
 6     private Button stopServideBtn;
 7     private Button goBtn;
 8 
 9     private Intent serviceIntent;
10 
11     @Override
12     protected void onCreate(Bundle savedInstanceState) {
13         super.onCreate(savedInstanceState);
14         setContentView(R.layout.activity_main);
15 
16         startServiceBtn = (Button) findViewById(R.id.start_service);
17         stopServideBtn = (Button) findViewById(R.id.stop_service);
18         goBtn = (Button) findViewById(R.id.go);
19 
20         startServiceBtn.setOnClickListener(new View.OnClickListener() {
21             @Override
22             public void onClick(View v) {
23                 serviceIntent = new Intent(MainActivity.this, MyService.class);
24                 startService(serviceIntent);
25             }
26         });
27 
28         stopServideBtn.setOnClickListener(new View.OnClickListener() {
29             @Override
30             public void onClick(View v) {
31                 stopService(serviceIntent);
32             }
33         });
34 
35         goBtn.setOnClickListener(new View.OnClickListener() {
36             @Override
37             public void onClick(View v) {
38                 Intent intent = new Intent(MainActivity.this, BActivity.class);
39                 startActivity(intent);
40             }
41         });
42 
43     }
44 
45     @Override
46     protected void onDestroy() {
47         super.onDestroy();
48         Log.w(TAG, "in onDestroy");
49     }
50 }

如上代码片段,

当Client调用startService(Intent serviceIntent)后,如果MyService是第一次启动,首先会执行 onCreate()回调,然后再执行onStartCommand(Intent intent, int flags, int startId),当Client再次调用startService(Intent serviceIntent),将只执行onStartCommand(Intent intent, int flags, int startId),因为此时Service已经创建了,无需执行onCreate()回调。无论多少次的startService,只需要一次stopService()即可将此Service终止,执行onDestroy()函数(其实很好理解,因为onDestroy()与onCreate()回调是相对的)。

下面重点关注下onStartCommand(Intent intent, int flags, int startId)方法。

其中参数flags默认情况下是0,对应的常量名为START_STICKY_COMPATIBILITY。startId是一个唯一的整型,用于表示此次Client执行startService(...)的请求请求标识,在多次startService(...)的情况下,呈现0,1,2....递增。另外,此函数具有一个int型的返回值,具体的可选值及含义如下:

START_NOT_STICKY:当Service因为内存不足而被系统kill后,接下来未来的某个时间内,即使系统内存足够可用,系统也不会尝试重新创建此Service。除非程序中Client明确再次调用startService(...)启动此Service。

START_STICKY:当Service因为内存不足而被系统kill后,接下来未来的某个时间内,当系统内存足够可用的情况下,系统将会尝试重新创建此Service,一旦创建成功后将回调onStartCommand(...)方法,但其中的Intent将是null,pendingintent除外。

START_REDELIVER_INTENT:与START_STICKY唯一不同的是,回调onStartCommand(...)方法时,其中的Intent将是非空,将是最后一次调用startService(...)中的intent。

START_STICKY_COMPATIBILITY:compatibility version of {@link #START_STICKY} that does not guarantee that {@link #onStartCommand} will be called again after being killed。此值一般不会使用,所以注意前面三种情形就好。

以上的描述中,”当Service因为内存不足而被系统kill后“一定要非常注意,因为此函数的返回值设定只是针对此种情况才有意义的,换言之,当认为的kill掉Service进程,此函数返回值无论怎么设定,接下来未来的某个时间内,即使系统内存足够可用,Service也不会重启。

 

 

 

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。