Android开发之AIDL实现远程服务进程通信(IPC)

来源:互联网 发布:linux sftp 断点续传 编辑:程序博客网 时间:2024/05/28 18:44

首先什么是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"    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的话可是实时去访问其他应用的数据。

1 0
原创粉丝点击