先来一点基础知识:
Service 是android的四大组件之一,与Activity同属于一个级别,它是运行在后台进行服务的组件(例如在后台播放的音乐,播放音乐的同时并不影响其他操作)。Service与Activity不同,Service没有界面。
Service虽然在后台运行,但是却与Activity一样运行在主程序中,因此不可在Service中进行耗时的操作。如果需要耗时操作的时候,可以开启子线程来操作。
Service的两种用法及其生命周期:
1.startService 开启服务
2.bindService 绑定服务
上图是这两种用法的生命周期图:
1、启动方式:onCreate()->onStartCommand()->onStop()->onDestroy()
2、绑定方式:onCreate()->onBind()->onUnBind()->onDestroy()
启动服务:一般从活动中调用 startService() ==> 服务调用 onCreate()(创建时只调用一次)==>onStartCommand() (可调用多次)
停止服务:一般从活动中调用 stopService() ==> 服务调用 onDestroy() (只调用一次) 或 直接在服务中调用stopSelf()来停止,如果有绑定服务,得先解绑,才能停止服务
使用方法一:启动服务
例子:服务与Activity的交互
1.在MainActivity中设置两个Button,分别启动服务和停止服务。
1 import android.content.Intent;
2 import android.os.Bundle;
3 import android.support.v7.app.ActionBarActivity;
4 import android.view.Menu;
5 import android.view.MenuItem;
6 import android.view.View;
7
8 public class MainActivity extends ActionBarActivity {
9 int number=38;
10 @Override
11 protected void onCreate(Bundle savedInstanceState) {
12 super.onCreate(savedInstanceState);
13 setContentView(R.layout.activity_main);
14 }
15
16 public void doButton(View v) {
17 Intent intent=new Intent();
18 switch (v.getId()) {
19 case R.id.button1:
20 intent.setAction("com.robin.testservice2.action");
21 intent.putExtra("number", number);
22 startService(intent);//启动服务
23 number++;
24 break;
25
26 case R.id.button2:
27 intent.setAction("com.robin.testservice2.action");
28 stopService(intent);//停止服务
29 break;
30 default:
31 break;
32 }
33 }
34 }
2.建一个Service的子类----这是在执行每两秒cnt自动减1的操作,其代码如下:
1 import android.app.Service;
2 import android.content.Intent;
3 import android.media.MediaPlayer;
4 import android.os.IBinder;
5 import android.util.Log;
6
7 public class MyService extends Service{
8 protected static final String TAG = "robin debug";
9 MediaPlayer mp;
10 Thread printThread;
11 int cnt=-1;
12 boolean active=false;
13 @Override
14 public IBinder onBind(Intent intent) {
15 return null;
16 }
17
18 @Override
19 public void onCreate() {
20 Log.e(TAG,"service create");
21 super.onCreate();
22 }
23
24 @Override
25 public int onStartCommand(Intent intent, int flags, int startId) {
26 Log.e(TAG,"service start command");
27 cnt=intent.getIntExtra("number", -1);
28 active=true;
29 printThread=new Thread(){
30 @Override
31 public void run() {
32 while(active){
33 cnt--;
34 try {
35 Thread.sleep(2000);
36 } catch (InterruptedException e) {
37 e.printStackTrace();
38 }
39 Log.e(TAG,"progress value--------->"+cnt);
40 }
41 }
42 };
43 printThread.start();
44 return super.onStartCommand(intent, flags, startId);
45 }
46
47 @Override
48 public void onDestroy() {
49 active=false;
50 super.onDestroy();
51 Log.e(TAG,"service destroy");
52 }
53 }
布局文件
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
2 xmlns:tools="http://schemas.android.com/tools"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent" >
5
6 <TextView
7 android:id="@+id/textView1"
8 android:layout_width="wrap_content"
9 android:layout_height="wrap_content"
10 android:text="@string/hello_world" />
11
12 <Button
13 android:id="@+id/button1"
14 android:layout_width="wrap_content"
15 android:layout_height="wrap_content"
16 android:layout_alignLeft="@+id/textView1"
17 android:layout_below="@+id/textView1"
18 android:layout_marginLeft="47dp"
19 android:layout_marginTop="24dp"
20 android:text="启动服务"
21 android:onClick="doButton"/>
22
23 <Button
24 android:id="@+id/button2"
25 android:layout_width="wrap_content"
26 android:layout_height="wrap_content"
27 android:layout_alignLeft="@+id/button1"
28 android:layout_below="@+id/button1"
29 android:layout_marginTop="60dp"
30 android:text="停止服务"
31 android:onClick="doButton"/>
32
33 </RelativeLayout>
以上的操作过程为,在Activity界面点击启动服务(startService(intent);)--->在MyService 中会执行
使用方法二:绑定服务
例子:Service与Activity之间进行通信
先来看看方法之间的调用顺序/过程:
上图中的代码:
ICount.java 类:
1 package com.robin.testservice3;
2
3
4 public interface ICount { //描述需要的行为(功能)
5 public int getCount();
6 public void setCount(int cnt);
7 }
MainActivity.java
1 package com.robin.testservice3;
2
3 import android.content.ComponentName;
4 import android.content.Intent;
5 import android.content.ServiceConnection;
6 import android.os.Bundle;
7 import android.os.IBinder;
8 import android.support.v7.app.ActionBarActivity;
9 import android.view.Menu;
10 import android.view.MenuItem;
11 import android.view.View;
12 import android.widget.TextView;
13
14 public class MainActivity extends ActionBarActivity {
15 private ICount count;
16 private class MyConn implements ServiceConnection{
17
18 @Override
19 public void onServiceConnected(ComponentName name, IBinder binder) {
20 count=(ICount) binder;
21 }
22
23 @Override
24 public void onServiceDisconnected(ComponentName name) {
25 count=null;
26 }
27 }
28 MyConn conn=new MyConn();
29 TextView txt;
30 @Override
31 protected void onCreate(Bundle savedInstanceState) {
32 super.onCreate(savedInstanceState);
33 setContentView(R.layout.activity_main);
34 Intent service=new Intent("com.robin.testservice3.action");
35 bindService(service, conn, BIND_AUTO_CREATE);
36 txt=(TextView)findViewById(R.id.result);
37 }
38
39 @Override
40 public boolean onCreateOptionsMenu(Menu menu) {
41 getMenuInflater().inflate(R.menu.main, menu);
42 return true;
43 }
44
45 @Override
46 public boolean onOptionsItemSelected(MenuItem item) {
47 int id = item.getItemId();
48 if (id == R.id.action_settings) {
49 return true;
50 }
51 return super.onOptionsItemSelected(item);
52 }
53
54 public void doButton(View view ){
55 switch (view.getId()) {
56 case R.id.button1:
57 txt.setText("来自service子线程的计数值:"+count.getCount());
58 break;
59 case R.id.button2:
60 count.setCount(1000);
61 break;
62 default:
63 break;
64 }
65 }
66 @Override
67 protected void onDestroy() {
68 unbindService(conn);
69 super.onDestroy();
70 }
71 }
MyService.java
1 package com.robin.testservice3;
2
3 import android.app.Service;
4 import android.content.Intent;
5 import android.os.Binder;
6 import android.os.IBinder;
7 import android.util.Log;
8
9 public class MyService extends Service{
10 protected static final String TAG = "robin debug";
11 private boolean active=false;
12 private int cnt=0;
13 private class MyBinder extends Binder implements ICount{
14
15 @Override
16 public int getCount() {
17 return cnt;
18 }
19 @Override
20 public void setCount(int cnt) {
21 MyService.this.cnt=cnt;
22 }
23 }
24 MyBinder binder=new MyBinder();
25
26 @Override
27 public IBinder onBind(Intent intent) {
28 return binder;
29 }
30
31 @Override
32 public void onCreate() {
33 new Thread(new Runnable() {
34
35 @Override
36 public void run() {
37 active=true;
38 while(active){
39 cnt++;
40 try {
41 Thread.sleep(2000);
42 } catch (InterruptedException e) {
43 e.printStackTrace();
44 }
45 Log.e(TAG,"service thread :cnt----->"+cnt);
46
47 }
48 }
49 }).start();
50 super.onCreate();
51 }
52 @Override
53 public void onDestroy() {
54 Log.e(TAG,"service call onDestroy");
55 active=false;
56 super.onDestroy();
57 }
58 }
布局文件:
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
2 xmlns:tools="http://schemas.android.com/tools"
3 android:id="@+id/LinearLayout1"
4 android:layout_width="match_parent"
5 android:layout_height="match_parent"
6 android:orientation="vertical">
7
8 <TextView
9 android:layout_width="wrap_content"
10 android:layout_height="wrap_content"
11 android:text="测试绑定使用service" />
12
13 <Button
14 android:id="@+id/button1"
15 android:layout_width="wrap_content"
16 android:layout_height="wrap_content"
17 android:text="读service端子线程的计数值"
18 android:onClick="doButton"/>
19
20 <Button
21 android:id="@+id/button2"
22 android:layout_width="wrap_content"
23 android:layout_height="wrap_content"
24 android:text="修改service端子线程的计数值"
25 android:onClick="doButton"/>
26
27 <TextView
28 android:id="@+id/result"
29 android:layout_width="wrap_content"
30 android:layout_height="wrap_content"
31 android:text="TextView" />
32
33 </LinearLayout>