Android Service

来源:互联网 发布:阿里云视频直播服务器 编辑:程序博客网 时间:2024/06/03 17:53

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         @Override20         public void register() throws RemoteException {21             // TODO Auto-generated method stub22             Log.d(TAG, "register from com.example.servicelearning");23         }24         25         @Override26         public int get() throws RemoteException {27             // TODO Auto-generated method stub28             return 10086;29         }30     };31     32     @Override33     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: onClick2 01-06 08:07:30.450 30442 30442 D BindServiceTestLog.TAG: onBind3 01-06 08:07:30.452 30401 30401 D MainActivityLog.TAG: ServiceTestHelp  onServiceConnected4 01-06 08:07:30.453 30442 30462 D BindServiceTestLog.TAG: register from com.example.servicelearning5 01-06 08:07:30.454 30401 30401 D MainActivityLog.TAG:  get = 10086

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

0 0
原创粉丝点击