android AIDL服务
来源:互联网 发布:双程2网络剧百度云盘 编辑:程序博客网 时间:2024/06/06 05:53
原文链接:http://www.cnblogs.com/trinea/archive/2012/11/08/2701390.html。
(1) 服务器端新建AIDL文件定义接口
在服务器端的src目录下新建以.aidl为后缀的文件,在这个文件中定义一个接口,声明服务器端和客户端交互的api,语法跟普通java接口声明一样,可以添加中英文注释。不同的是
a. 除了Java基本数据类型 (int, long, char, boolean等)、String、CharSequence、List、Map外,其他复杂类型都需要显式import(包括其他AIDL定义的接口),即便复杂类型在同一个包内定义。
b. 支持泛型实例化的List,如List<String>;不支持泛型实例化的Map,如Map<String, String>。对于List为参数接收者接收到的始终是ArrayList;对于Map为参数接收者接收到的始终是HashMap。
c. interface和函数都不能带访问权限修饰符。
d. 接口内只允许定义方法,不允许定义静态属性。
我们定义MyAIDLInterface.aidl文件如下:
package com.trinea.android.demo;interface MyAIDLInterface { int getCount(); void setCount(int count);}
声明两个接口在后面供客户端调用。保存文件,编译后,Sdk工具在gen目录下相同子目录中自动生成同名的以.java为后缀的文件,这里文件名为MyAIDLInterface.java。
(2) 自动生成的同名java文件解析
MyAIDLInterface.java为Sdk工具自动生成,内容如下:
根据AIDL文件自动生成的Java文件 /* * This file is auto-generated. DO NOT MODIFY. * Original file: D:\\Eclipse\\AndroidDemo\\MapDemo\\src\\com\\trinea\\android\\demo\\MyAIDLInterface.aidl */package com.trinea.android.demo;public interface MyAIDLInterface extends android.os.IInterface{/** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implements com.trinea.android.demo.MyAIDLInterface{private static final java.lang.String DESCRIPTOR = "com.trinea.android.demo.MyAIDLInterface";/** Construct the stub at attach it to the interface. */public Stub(){this.attachInterface(this, DESCRIPTOR);}/** * Cast an IBinder object into an com.trinea.android.demo.MyAIDLInterface interface, * generating a proxy if needed. */public static com.trinea.android.demo.MyAIDLInterface asInterface(android.os.IBinder obj){if ((obj==null)) {return null;}android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);if (((iin!=null)&&(iin instanceof com.trinea.android.demo.MyAIDLInterface))) {return ((com.trinea.android.demo.MyAIDLInterface)iin);}return new com.trinea.android.demo.MyAIDLInterface.Stub.Proxy(obj);}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_getCount:{data.enforceInterface(DESCRIPTOR);int _result = this.getCount();reply.writeNoException();reply.writeInt(_result);return true;}case TRANSACTION_setCount:{data.enforceInterface(DESCRIPTOR);int _arg0;_arg0 = data.readInt();this.setCount(_arg0);reply.writeNoException();return true;}}return super.onTransact(code, data, reply, flags);}private static class Proxy implements com.trinea.android.demo.MyAIDLInterface{private android.os.IBinder mRemote;Proxy(android.os.IBinder remote){mRemote = remote;}public android.os.IBinder asBinder(){return mRemote;}public java.lang.String getInterfaceDescriptor(){return DESCRIPTOR;}public int getCount() throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();int _result;try {_data.writeInterfaceToken(DESCRIPTOR);mRemote.transact(Stub.TRANSACTION_getCount, _data, _reply, 0);_reply.readException();_result = _reply.readInt();}finally {_reply.recycle();_data.recycle();}return _result;}public void setCount(int count) throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeInt(count);mRemote.transact(Stub.TRANSACTION_setCount, _data, _reply, 0);_reply.readException();}finally {_reply.recycle();_data.recycle();}}}static final int TRANSACTION_getCount = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);static final int TRANSACTION_setCount = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);}public int getCount() throws android.os.RemoteException;public void setCount(int count) throws android.os.RemoteException;}
其中有几个主要的部分:
a. 抽象类Stub,继承Binder实现自定义接口,作用同进程内通信服务中自定义的Binder,客户端通过它对服务进行调用。
b. 静态类Proxy,实现自定义接口,代理模式接收对Stub的调用。
(3) 服务器端定义服务
服务器端Service代码 package com.trinea.android.demo;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteException;import android.widget.Toast;public class MyAIDLService extends Service { private int mCount; private MyAIDLInterface.Stub myBinder = new MyAIDLInterface.Stub() { @Override public void setCount(int count) throws RemoteException { mCount = count; } @Override public int getCount() throws RemoteException { return mCount; } }; @Override public void onCreate() { mCount = 0; Toast.makeText(this, "Service onCreate", Toast.LENGTH_SHORT).show(); super.onCreate(); } @Override public void onDestroy() { Toast.makeText(this, "Service onDestroy", Toast.LENGTH_SHORT).show(); super.onDestroy(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(this, Integer.toString(mCount), Toast.LENGTH_SHORT).show(); return super.onStartCommand(intent, flags, startId); } public int getCount() { return mCount; } /** * 服务被绑定时调用 * 返回值用于让调用者和服务通信,传入ServiceConnection的public void onServiceConnected(ComponentName name, IBinder service)函数第二个参数 */ @Override public IBinder onBind(Intent intent) { return myBinder; }}
AndroidManifest.xml中注册服务
<service android:name=".MyAIDLService"> <intent-filter> <action android:name="com.trinea.android.demo.remote.MyAIDLServiceAction" /> </intent-filter></service>
其中的action name用于后面客户端调用时匹配
客户端(代码见AndroidAidlClient@GoogleCode):
服务器端目录结构:,客户端目录结构:
ERROR/AndroidRuntime(2104): java.lang.SecurityException: Binder invocation to an incorrect interface。后发现是因为服务器端和客户端aidl文件的包名不同导致生成的java文件不同。
客户端调用远程服务代码 private MyAIDLInterface binder = null;private Intent myAIDLServiceIntent;private ServiceConnection con = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { } @Override public void onServiceConnected(ComponentName name, IBinder service) { binder = MyAIDLInterface.Stub.asInterface(service); } };@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.client); boundAIDLServiceBtn = (Button)findViewById(R.id.boundAIDLService); myAIDLServiceIntent = new Intent("com.trinea.android.demo.remote.MyAIDLServiceAction"); boundAIDLServiceBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { boolean result = bindService(myAIDLServiceIntent, con, Context.BIND_AUTO_CREATE); if (!result) { binder = null; Toast.makeText(getApplicationContext(), "服务绑定失败。", Toast.LENGTH_SHORT).show(); } } }); getBoundAIDLServiceProBtn = (Button)findViewById(R.id.getBoundAIDLServicePro); getBoundAIDLServiceProBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { try { if (binder != null) { Toast.makeText(getApplicationContext(), "Service count:" + binder.getCount(), Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getApplicationContext(), "请先绑定服务。", Toast.LENGTH_SHORT).show(); } } catch (RemoteException e) { e.printStackTrace(); } } }); unboundAIDLServiceBtn = (Button)findViewById(R.id.unboundAIDLService); unboundAIDLServiceBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (binder != null) { unbindService(con); binder = null; } } });}
上面的三个按钮boundAIDLServiceBtn、getBoundAIDLServiceProBtn、unboundAIDLServiceBtn分别用于绑定服务、得到服务中属性值、解除绑定服务。
从上面可以看出我们先定义ServiceConnection对象用于和服务器通信,在onServiceConnected函数中通过MyAIDLInterface.Stub.asInterface(service)返回用户定义的接口对象,通过此对象调用远程接口api。在boundAIDLServiceBtn的onClick函数中绑定服务,在getBoundAIDLServiceProBtn的onClick函数中调用服务的api,在boundAIDLServiceBtn的onClick函数中取消绑定服务,
现在我们运行两个项目即可,在客户端绑定服务再获取服务属性显示。
3、生命周期
通过bindService绑定服务,若服务未启动,会先执行Service的onCreate函数,再执行onBind函数,最后执行ServiceConnection对象的onServiceConnected函数,客户端可以自动启动服务。若服务已启动但尚未绑定,先执行onBind函数,再执行ServiceConnection对象的onServiceConnected函数。若服务已绑定成功,则直接返回。这里不会自动调用onStartCommand函数。
通过unbindService解除绑定服务,若已绑定成功,会先执行Service的onUnbind函数,再执行onDestroy函数,注意这里不会执行ServiceConnection对象的onServiceDisconnected函数,因为该函数是在服务所在进程被kill或是crash时被调用。
- android AIDL服务
- android AIDL服务
- android AIDL服务
- Android创建AIDL服务
- Android服务之AIDL
- Android之AIDL服务
- Android AIDL服务学习笔记
- android AIDL绑定服务使用
- Android AIDL服务学习笔记
- Android AIDL实现远程服务
- Android中的服务(service)--AIDL远程服务
- Android 使用 aidl 文件创建服务示例
- Android 使用【AIDL】调用外部服务
- Android 使用【AIDL】调用外部服务
- Android 使用【AIDL】调用外部服务
- Android 使用【AIDL】调用外部服务
- Android AIDL远程服务使用示例
- Android AIDL远程服务使用示例
- SIP学习笔记
- 重新组织数据之十四 :Replace Type Code with Subclasses(以子类取代型别码)
- The C Programming Language 学习笔记
- DWR使用总结
- ASP.Net 文件上传大小限制解决方案修改IIS7/7.5配置
- android AIDL服务
- SIP协议简介
- php文件下载原理
- jQuery 入门教程(42): jQuery UI Tab 示例(二)
- Linux系统启动过程介绍
- 重新组织数据之十五 :Replace Type Code with State/Strategy(以State/strategy 取代型别码)
- BF and IA vulnerabilities in IBM Lotus Domino
- 黑马程序员_Java网络编程概述
- ActiveMQ 无法启动 提示端口被占用