您的位置:首页 > 移动开发 > Android开发

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文件。

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的话可是实时去访问其他应用的数据。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息