Android开发之AIDL实现远程服务进程通信(IPC)
2016-06-08 17:02
656 查看
首先什么是AIDL呢,它是Android系统中的一种接口定义语言,用于约束两个进程间的通讯规则,供编译器生成代码。
实现Android设备上的两个进程间通信(IPC),进程之间的通信信息首先会被转换成AIDL协议信息,然后发送给对方;对方接收到AIDL协议信息后再转换成相应的对象,由于进程之间的通信信息需要双向的转换,Android系统采用代理类在背后实现了信息的双向转换,代理类是由Android编译器生成,对于开发人员来数是透明个。
两个进程间也就是应用间的通信,一个是访问者A应用 client另一个则是B应用的service,A要想访问B的service是不可能直接的去调用B的方法的,但是如果要实现AIDL规则的话,则可以间接的访问。这就类似于在开发webA应用的时候我们的应用要获取另一个webB应用的数据,但是我们不知道webB应用在哪里,但是如果WebB给给我提供一个WSDL文件,我们就可以通过webservice去访问应用中的方法,其实就是一个道理只是系统的不同。
首先我们来介绍下整个过程
A应用请求B应用的 service ,如果A应用与B应用的 service绑定了以后那么 B应用就会返回一个Binder ,A应用可以拿着这个Binder 去调用 B应用service中的方法。但是这个Binder 这是一个代理。
接下来我们看一下具体的代码:
我们先来配置一下B应用的 service
创建一个QueryPerson.aidl文件,这时候编译器会自动的给我们在gen下相同的包生成一个java文件。
接下来创建service
最后别忘了在AndroidMainifest.xml配置service
到这我们的service端的就写完了
接下来A应用的代码
同样的必须将service中的aidl文件复制到A应用中
配置activity代码:
布局文件:
实际的效果就是下图所示的:
这就是简单的远程服务进程间通信,很简答吧!
之前想过不同应用之间为啥不直接用contentprovider呢 ,因为contentprovider只是向调用者暴露了你的数据库而已,而且还不是实时的数据;但是用AIDL的话可是实时去访问其他应用的数据。
实现Android设备上的两个进程间通信(IPC),进程之间的通信信息首先会被转换成AIDL协议信息,然后发送给对方;对方接收到AIDL协议信息后再转换成相应的对象,由于进程之间的通信信息需要双向的转换,Android系统采用代理类在背后实现了信息的双向转换,代理类是由Android编译器生成,对于开发人员来数是透明个。
两个进程间也就是应用间的通信,一个是访问者A应用 client另一个则是B应用的service,A要想访问B的service是不可能直接的去调用B的方法的,但是如果要实现AIDL规则的话,则可以间接的访问。这就类似于在开发webA应用的时候我们的应用要获取另一个webB应用的数据,但是我们不知道webB应用在哪里,但是如果WebB给给我提供一个WSDL文件,我们就可以通过webservice去访问应用中的方法,其实就是一个道理只是系统的不同。
首先我们来介绍下整个过程
A应用请求B应用的 service ,如果A应用与B应用的 service绑定了以后那么 B应用就会返回一个Binder ,A应用可以拿着这个Binder 去调用 B应用service中的方法。但是这个Binder 这是一个代理。
接下来我们看一下具体的代码:
我们先来配置一下B应用的 service
创建一个QueryPerson.aidl文件,这时候编译器会自动的给我们在gen下相同的包生成一个java文件。
package com.my.aidl; //aidl的语法和我们定义接口很是类似,但是aidl不可以有任何的修饰符 interface QueryPerson { String query(int num); }
接下来创建service
public class QuerypersonService extends Service { private IBinder iBinder = new QuerypersonBinder(); @Override public IBinder onBind(Intent intent) { return iBinder; } /** * 这个方法里我们就不能再继承IBinder了, 因为我们要让这个service具有远程通信的能力 * * 所以这我们要继承刚才系统帮我们生成的aidl 类 * * 这个方法继承的是系统的android.os.Binder * public static abstract class Stub extends android.os.Binder * */ private final class QuerypersonBinder extends QueryPerson.Stub{ //这里就简单的放一些数据测试 @Override public String queryPerson(int num) throws RemoteException { String[] names = new String[]{"张三","李四","王五","z赵六"}; String name = names[num]; return name; } } }
最后别忘了在AndroidMainifest.xml配置service
<service android:name=".QuerypersonService" > <intent-filter> <action android:name="com.my.aidlservice" /> </intent-filter> </service>
到这我们的service端的就写完了
接下来A应用的代码
同样的必须将service中的aidl文件复制到A应用中
配置activity代码:
public class MainActivity extends Activity { private EditText mEditText; private TextView mText; private PersonServiceConnection conn = new PersonServiceConnection(); private QueryPerson queryPerson; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mText = (TextView) findViewById(R.id.Text); mEditText = (EditText) findViewById(R.id.content); // 采用隐世的intent 去启动service Intent service = new Intent("com.my.aidlservice"); // 绑定service bindService(service, conn, BIND_AUTO_CREATE); } //按钮的点击事件 public void QueryPerson(View v) { String number = mEditText.getText().toString(); int num = Integer.parseInt(number); try { String name = queryPerson.queryPerson(num); mText.setText(name); } catch (RemoteException e) { e.printStackTrace(); } } // 创建一个ServiceConnection private final class PersonServiceConnection implements ServiceConnection { // 当service绑定时 @Override public void onServiceConnected(ComponentName name, IBinder service) { //service 返回的IBinder 必须要进行转换才可以使用,用asInterface()方法就可以转换 queryPerson = QueryPerson.Stub.asInterface(service); } // 当service撤销绑定时 @Override public void onServiceDisconnected(ComponentName name) { } } // 当activity销毁时 会取消绑定service @Override protected void onDestroy() { unbindService(conn); super.onDestroy(); } }
布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" b86c xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <EditText android:id="@+id/content" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="QueryPerson" android:text="Click"/> <TextView android:id="@+id/Text" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
实际的效果就是下图所示的:
这就是简单的远程服务进程间通信,很简答吧!
之前想过不同应用之间为啥不直接用contentprovider呢 ,因为contentprovider只是向调用者暴露了你的数据库而已,而且还不是实时的数据;但是用AIDL的话可是实时去访问其他应用的数据。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories