AIDL
2.service的种类,
由于adroid的独特的线程模型,service被同一个apk调用和不同apk调用原理是不同的,因此分成以下两种:
(1). 本地服务(Local Service):说白了就是在同一个apk内被调用。
(2). 远程服务(Remote Sercie):被另外一个apk调用。 AIDL来实现
AIDL: Android Interface definition language的,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口
---------------------------------------------------------------------------
服务端:
//ICat.aidl
package org.crazyit.service; interface ICat { String getColor(); double getWeight(); }
//ICat.java 这个文件是依据ICat.aidl自动生成的,不需要进行任何修改 package org.crazyit.service; public interface ICat extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements org.crazyit.service.ICat { private static final java.lang.String DESCRIPTOR = "org.crazyit.service.ICat"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an org.crazyit.service.ICat interface, * generating a proxy if needed. */ public static org.crazyit.service.ICat asInterface( android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof org.crazyit.service.ICat))) { return ((org.crazyit.service.ICat) iin); } return new org.crazyit.service.ICat.Stub.Proxy(obj); } @Override public android.os.IBinder asBinder() { return this; } @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_getColor: { data.enforceInterface(DESCRIPTOR); java.lang.String _result = this.getColor(); reply.writeNoException(); reply.writeString(_result); return true; } case TRANSACTION_getWeight: { data.enforceInterface(DESCRIPTOR); double _result = this.getWeight(); reply.writeNoException(); reply.writeDouble(_result); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements org.crazyit.service.ICat { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } @Override public java.lang.String getColor() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); java.lang.String _result; try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_getColor, _data, _reply, 0); _reply.readException(); _result = _reply.readString(); } finally { _reply.recycle(); _data.recycle(); } return _result; } @Override public double getWeight() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); double _result; try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_getWeight, _data, _reply, 0); _reply.readException(); _result = _reply.readDouble(); } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int TRANSACTION_getColor = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_getWeight = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); } public java.lang.String getColor() throws android.os.RemoteException; public double getWeight() throws android.os.RemoteException; }
package org.crazyit.service; import java.util.Timer; import java.util.TimerTask; import org.crazyit.service.ICat.Stub; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; public class AidlService extends Service { private CatBinder catBinder; Timer timer = new Timer(); String[] colors = new String[] { "红色", "黄色", "黑色" }; double[] weights = new double[] { 2.3, 3.1, 1.58 }; private String color; private double weight; public class CatBinder extends Stub { @Override public String getColor() throws RemoteException { return color; } @Override public double getWeight() throws RemoteException { return weight; } } @Override public void onCreate() { super.onCreate(); catBinder = new CatBinder(); timer.schedule(new TimerTask() { @Override public void run() { int rand = (int) (Math.random() * 3); color = colors[rand]; weight = weights[rand]; } }, 0, 800); } @Override public IBinder onBind(Intent arg0) { return catBinder; } @Override public void onDestroy() { timer.cancel(); } }
AidlService这个类不会被显示实例化,而是通过org.crazyit.aidl.action.AIDL_SERVICE来标识它的。绑定服务的时候依据含有这个action的Intent来识别AidlService
//AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.crazyit.service" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <!-- 定义一个Service组件 --> <service android:name=".AidlService" > <intent-filter> <action android:name="org.crazyit.aidl.action.AIDL_SERVICE" /> </intent-filter> </service> </application> </manifest>
-----------------------------------------------
客户端:
//ICat.aidl package org.crazyit.service; interface ICat { String getColor(); double getWeight(); }
public class AidlClient extends Activity { private ICat catService; private Button get; EditText color, weight; private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { catService = ICat.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { catService = null; } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); get = (Button) findViewById(R.id.get); color = (EditText) findViewById(R.id.color); weight = (EditText) findViewById(R.id.weight); Intent intent = new Intent(); intent.setAction("org.crazyit.aidl.action.AIDL_SERVICE"); bindService(intent, conn, Service.BIND_AUTO_CREATE); get.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { try { color.setText(catService.getColor()); weight.setText(catService.getWeight() + ""); } catch (RemoteException e) { e.printStackTrace(); } } }); } @Override public void onDestroy() { super.onDestroy(); this.unbindService(conn); } }
运行的时候,先将服务端(这个是没有界面的)安装起来,然后再运行客户端。