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 }

在自己的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 /*
  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 }

  点击按钮之后,启动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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值