Android Service

Android 有四大组件: Activity , Service , BroadcastReceiver , ContentProvider, 这篇主要讲Service

 

启动Service有两种方式: startService 和 bindService

startService:

  Service也有自己的生命周期, startService是会依次调用service的 onCreate(), onStartCommand(),onStart()方法(实际在父类的onStartCommand()方法中主动调用的onStart()),如果Service已经启动了,则只会调用onStartCommand()和onStart().

  stopService,停止已经开始的Service,会动用Service的onDestroy();

  从log中可以看到,Service是运行与主线程,所以不应做繁重的任务,防止ANR.

bindService:

  bindService 需要传三个参数 Intent ,ServiceConnection , flag

    Intent 指明需要启动的Service ; ServiceConnection Service连接成功之后的回调; flag bind的方式,一般是1;

  bindService 会依次调用Service的onCreate(),onBind()方法, 如果Service已经启动,再次bindService会连接,但不会再调用生命周期的方法

  unbindService 会调用Service的onDestroy()。

  通过bindService的方式启动Service,可以获取到一个IBinder对象,通过IBinder对象可以调用Service里的方法。

  binderService的第二个参数: 通过onServiceConnected()回调 可以获取到IBinder对象。

 1     ServiceConnection sc = new ServiceConnection() {
 2         @Override
 3         public void onServiceDisconnected(ComponentName name) {
 4             
 5         }
 6         @Override
 7         public void onServiceConnected(ComponentName name, IBinder service) {
 8             // TODO Auto-generated method stub
 9 
10     };

 

AIDL: android 接口定义语言,通过他可以实现进程间的通信。

要和远端的Service进行交互,可以使用aidl实现进程间的通信:

myService.aidl

1 package com.example.servicelearning.aidl;
2 
3 interface myService {
4     void register();
5     int get();
6 }

编译之后,会在gen目录对应包名下自动生成一个myService.java的接口,里面有一个内部静态抽象类Stub,实现了myService的接口。

编译之后的myService.java

  1 /*
  2  * This file is auto-generated.  DO NOT MODIFY.
  3  * Original file: E:\\vivoCamera\\ServiceLearning\\src\\com\\example\\servicelearning\\aidl\\myService.aidl
  4  */
  5 package com.example.servicelearning.aidl;
  6 public interface myService extends android.os.IInterface
  7 {
  8 /** Local-side IPC implementation stub class. */
  9 public static abstract class Stub extends android.os.Binder implements com.example.servicelearning.aidl.myService
 10 {
 11 private static final java.lang.String DESCRIPTOR = "com.example.servicelearning.aidl.myService";
 12 /** Construct the stub at attach it to the interface. */
 13 public Stub()
 14 {
 15 this.attachInterface(this, DESCRIPTOR);
 16 }
 17 /**
 18  * Cast an IBinder object into an com.example.servicelearning.aidl.myService interface,
 19  * generating a proxy if needed.
 20  */
 21 public static com.example.servicelearning.aidl.myService asInterface(android.os.IBinder obj)
 22 {
 23 if ((obj==null)) {
 24 return null;
 25 }
 26 android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
 27 if (((iin!=null)&&(iin instanceof com.example.servicelearning.aidl.myService))) {
 28 return ((com.example.servicelearning.aidl.myService)iin);
 29 }
 30 return new com.example.servicelearning.aidl.myService.Stub.Proxy(obj);
 31 }
 32 @Override public android.os.IBinder asBinder()
 33 {
 34 return this;
 35 }
 36 @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
 37 {
 38 switch (code)
 39 {
 40 case INTERFACE_TRANSACTION:
 41 {
 42 reply.writeString(DESCRIPTOR);
 43 return true;
 44 }
 45 case TRANSACTION_register:
 46 {
 47 data.enforceInterface(DESCRIPTOR);
 48 this.register();
 49 reply.writeNoException();
 50 return true;
 51 }
 52 case TRANSACTION_get:
 53 {
 54 data.enforceInterface(DESCRIPTOR);
 55 int _result = this.get();
 56 reply.writeNoException();
 57 reply.writeInt(_result);
 58 return true;
 59 }
 60 }
 61 return super.onTransact(code, data, reply, flags);
 62 }
 63 private static class Proxy implements com.example.servicelearning.aidl.myService
 64 {
 65 private android.os.IBinder mRemote;
 66 Proxy(android.os.IBinder remote)
 67 {
 68 mRemote = remote;
 69 }
 70 @Override public android.os.IBinder asBinder()
 71 {
 72 return mRemote;
 73 }
 74 public java.lang.String getInterfaceDescriptor()
 75 {
 76 return DESCRIPTOR;
 77 }
 78 @Override public void register() throws android.os.RemoteException
 79 {
 80 android.os.Parcel _data = android.os.Parcel.obtain();
 81 android.os.Parcel _reply = android.os.Parcel.obtain();
 82 try {
 83 _data.writeInterfaceToken(DESCRIPTOR);
 84 mRemote.transact(Stub.TRANSACTION_register, _data, _reply, 0);
 85 _reply.readException();
 86 }
 87 finally {
 88 _reply.recycle();
 89 _data.recycle();
 90 }
 91 }
 92 @Override public int get() throws android.os.RemoteException
 93 {
 94 android.os.Parcel _data = android.os.Parcel.obtain();
 95 android.os.Parcel _reply = android.os.Parcel.obtain();
 96 int _result;
 97 try {
 98 _data.writeInterfaceToken(DESCRIPTOR);
 99 mRemote.transact(Stub.TRANSACTION_get, _data, _reply, 0);
100 _reply.readException();
101 _result = _reply.readInt();
102 }
103 finally {
104 _reply.recycle();
105 _data.recycle();
106 }
107 return _result;
108 }
109 }
110 static final int TRANSACTION_register = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
111 static final int TRANSACTION_get = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
112 }
113 public void register() throws android.os.RemoteException;
114 public int get() throws android.os.RemoteException;
115 }
View Code

在自己的Service 实现此类里面的抽象方法。在bindService的时候,onBind()方法可以return此对象,通过此对象实现通信。

BindServiceTest.java  (记得在Manifest文件里声明Service)

 1 package com.example.servicelearning.service;
 2 
 3 import com.example.servicelearning.aidl.myService;
 4 
 5 import android.app.Service;
 6 import android.content.Intent;
 7 import android.os.IBinder;
 8 import android.os.RemoteException;
 9 import android.util.Log;
10 
11 public class BindServiceTest extends Service {
12     
13     
14     private static final String TAG = "BindServiceTestLog.TAG";
15 
16     
17     myService.Stub mStub = new myService.Stub() {
18         
19         @Override
20         public void register() throws RemoteException {
21             // TODO Auto-generated method stub
22             Log.d(TAG, "register from com.example.servicelearning");
23         }
24         
25         @Override
26         public int get() throws RemoteException {
27             // TODO Auto-generated method stub
28             return 10086;
29         }
30     };
31     
32     @Override
33     public IBinder onBind(Intent intent) {
34         Log.d(TAG, "onBind");
35         return mStub;
36     }
37 
38  }

 

  为了验证通过AIDL实现的进程通信,我们可以再编写一个apk,通过这个apk启动之前那个apk里面的Service,并实现通信。

  在这个apk里面我们必须写一个同样的aidl文件,包名必须和之前那个一致。

MainActivity.java   (布局文件和Manifest文件都比较简单就不贴出来了)

 1 package com.example.servicetesthelp;
 2 
 3 import com.example.servicelearning.aidl.myService;
 4 import android.app.Activity;
 5 import android.content.ComponentName;
 6 import android.content.Context;
 7 import android.content.Intent;
 8 import android.content.ServiceConnection;
 9 import android.os.Bundle;
10 import android.os.IBinder;
11 import android.os.RemoteException;
12 import android.util.Log;
13 import android.view.View;
14 import android.view.View.OnClickListener;
15 import android.widget.Button;
16 
17 public class MainActivity extends Activity {
18 
19     private static final String TAG = "MainActivityLog.TAG";
20     Button mButton;
21     @Override
22     protected void onCreate(Bundle savedInstanceState) {
23         super.onCreate(savedInstanceState);
24         setContentView(R.layout.activity_main);
25         mButton = (Button) findViewById(R.id.mButton);
26         mButton.setOnClickListener(new OnClickListener() {
27             
28             @Override
29             public void onClick(View v) {
30                 // TODO Auto-generated method stub
31                 Log.d(TAG, "onClick ");
32                 Intent mIntent = new Intent("android.service.bindservicetest");
33                 mIntent.setPackage("com.example.servicelearning");
34                 bindService(mIntent, new ServiceConnection() {
35                     
36                     @Override
37                     public void onServiceDisconnected(ComponentName name) {
38                         // TODO Auto-generated method stub                        
39                     }
40                     
41                     @Override
42                     public void onServiceConnected(ComponentName name, IBinder service) {
43                         // TODO Auto-generated method stub
44                         Log.d(TAG , "ServiceTestHelp  onServiceConnected");
45                         myService binder = myService.Stub.asInterface(service);
46                         try {
47                             binder.register();
48                             Log.d(TAG," get = " + binder.get());
49                         } catch (RemoteException e) {
50                             // TODO Auto-generated catch block
51                             e.printStackTrace();
52                         }
53                     }
54                 }, Context.BIND_AUTO_CREATE);
55             }
56         });
57     }
58 
59 }
View Code

  点击按钮之后,启动Service,(启动Service时,Intent必须是显性的),onServiceConnected()方法的回调的Ibinder方法,通过myService.Stub.asInterface()方法获取到myService对象,通过此对象可以调用对端Service的方法,具体可以通过Log看到。

1 01-06 08:07:30.385 30401 30401 D MainActivityLog.TAG: onClick
2 01-06 08:07:30.450 30442 30442 D BindServiceTestLog.TAG: onBind 3 01-06 08:07:30.452 30401 30401 D MainActivityLog.TAG: ServiceTestHelp onServiceConnected 4 01-06 08:07:30.453 30442 30462 D BindServiceTestLog.TAG: register from com.example.servicelearning 5 01-06 08:07:30.454 30401 30401 D MainActivityLog.TAG: get = 10086

   可以看到是在两个进程里面,也可以正常通信。

posted on 2016-07-09 11:18  梦想,就在不远方  阅读(570)  评论(0编辑  收藏  举报

导航