android中的AIDL进程间通信示例
关于ipc应该不用多介绍了,android系统中的进程之间不能共享内存,那么如果两个不同的应用程序之间需要通讯怎么办呢?比如公司的一个项目要更新,产品的需求是依附于当前项目开发一个插件,但是呢这个插件功能以及界面比较复杂,不能和当前项目在一个进程中,同时呢,还要用到当前项目中已经写好了的一些东西,那么因为新开发的依附于当前项目的插件和当前项目不是一个进程,因此不能共享内存,就出现了问题,于是,需要提供一些机制在不同进程之间进行数据通信,这个机制就是aidl了。
一、一个android中aidl的简单例子
假如是这样,现在有一个项目中提供了比较成熟的计算的方法,而现在我想开发一款软件其中一个模块想用到一个计算类,而我又不想重新写了,那么就可以通过aidl实现啦。假设,已经开发完成的那个已经提供了比较成熟的计算类的程序叫aidlcalculatedemoserver(相当于服务器),而我要写的程序叫aidlcalculatedemoclient(相当于客户端),类似与客户端服务器模式。首先至关的看下工程结构图:
图1-1 服务器 图1-2 客户端
现在假设自己写的程序要调用服务端的运算界面,输入num1和num2,进行远程运算,调用服务端的接口,服务端运算好之后,返回结果给客户端,效果图如下:
然后来看看实现,首先需要定义aidl接口,客户端和服务器端都要定义,并且要在同一包中,也就是图1-1和图1-2 com.example.aidl.calculate中的calculateinterface,其中的代码如下:
package com.example.aidl.calculate; interface calculateinterface { double docalculate(double a, double b); }
编译发现,目录结构如图1-1和图1-2中gen/com.example.aidl.calculate中多了calculateinterface.java文件,内容如下:
package com.example.aidl.calculate; interface calculateinterface { double docalculate(double a, double b); }
定义好接口就是要看服务端和客户端的代码啦,其中服务端主要看calculateservice代码,这个一个继承service的类,在其中对aidl中的接口进行赋予实际意义,如下:
package com.example.calculate; import com.example.aidl.calculate.calculateinterface; import com.example.aidl.calculate.calculateinterface.stub; import android.app.service; import android.content.intent; import android.os.ibinder; import android.os.remoteexception; import android.util.log; public class calculateservice extends service { private static final string tag = "calculateservice"; @override public ibinder onbind(intent arg0) { // todo auto-generated method stub loge("onbind()"); return mbinder; } @override public void oncreate() { // todo auto-generated method stub loge("oncreate()"); super.oncreate(); } @override public void onstart(intent intent, int startid) { // todo auto-generated method stub loge("onstart()"); super.onstart(intent, startid); } @override public boolean onunbind(intent intent) { // todo auto-generated method stub loge("onunbind()"); return super.onunbind(intent); } @override public void ondestroy() { // todo auto-generated method stub loge("ondestroy()"); super.ondestroy(); } private static void loge(string str) { log.e(tag, "--------" + str + "--------"); } private final calculateinterface.stub mbinder = new calculateinterface.stub() { @override public double docalculate(double a, double b) throws remoteexception { // todo auto-generated method stub log.e("calculate", "远程计算中"); calculate calculate = new calculate(); double answer = calculate.calculatesum(a, b); return answer; } }; }
然后可以看看,关键的服务都提供完毕,那么在客户端是怎么访问的呢,要进行绑定服务和一个serviceconnection类完成,如下:
package com.example.calculate; import android.app.activity; import android.content.componentname; import android.content.context; import android.content.intent; import android.content.serviceconnection; import android.graphics.color; import android.os.bundle; import android.os.ibinder; import android.os.remoteexception; import android.util.log; import android.view.view; import android.widget.button; import android.widget.edittext; import android.widget.textview; import com.example.aidl.calculate.calculateinterface; import com.example.aidlcalculatedemoclient.r; public class calculateclient extends activity { private static final string tag = "calculateclient"; private button btncalculate; private edittext etnum1; private edittext etnum2; private textview tvresult; private calculateinterface mservice; private serviceconnection mserviceconnection = new serviceconnection() { @override public void onservicedisconnected(componentname name) { // todo auto-generated method stub loge("disconnect service"); mservice = null; } @override public void onserviceconnected(componentname name, ibinder service) { // todo auto-generated method stub loge("connect service"); mservice = calculateinterface.stub.asinterface(service); } }; @override protected void oncreate(bundle savedinstancestate) { // todo auto-generated method stub super.oncreate(savedinstancestate); setcontentview(r.layout.main); bundle args = new bundle(); intent intent = new intent("com.example.calculate.calculateservice"); intent.putextras(args); bindservice(intent, mserviceconnection, context.bind_auto_create); etnum1 = (edittext) findviewbyid(r.id.et_num_one); etnum2 = (edittext) findviewbyid(r.id.et_num_two); tvresult = (textview) findviewbyid(r.id.tv_result); btncalculate = (button) findviewbyid(r.id.btn_cal); btncalculate.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { // todo auto-generated method stub loge("开始远程运算"); try { double num1 = double.parsedouble(etnum1.gettext().tostring()); double num2 = double.parsedouble(etnum2.gettext().tostring()); string answer = "计算结果:" + mservice.docalculate(num1, num2); tvresult.settextcolor(color.blue); tvresult.settext(answer); } catch (remoteexception e) { } } }); } private void loge(string str) { log.e(tag, "--------" + str + "--------"); } }
如此一来,大功已经基本告成,最后,我们在来看看服务端的配置文件吧:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.aidlcaculatedemoserver" android:versioncode="1" android:versionname="1.0" > <uses-sdk android:minsdkversion="8" android:targetsdkversion="17" /> <application android:allowbackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/apptheme" > <activity android:name="com.example.aidlcaculatedemoserver.mainactivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.main" /> <category android:name="android.intent.category.launcher" /> </intent-filter> </activity> <service android:name="com.example.calculate.calculateservice"> <intent-filter> <action android:name="com.example.calculate.calculateservice" /> </intent-filter> </service> </application> </manifest>
二、写aidl注意事项
1. 客户端和服务端的aidl接口文件所在的包必须相同
2. 需要一个service类的配合
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。