android 进程间通信(aidl)

来源:互联网 发布:腾讯数据分析待遇 编辑:程序博客网 时间:2024/06/09 23:49

注:由于时间关系目前先写个大概,后续再做完善

1.建立aidl
建立aidl文件夹,在文件夹中添加包tk.huayu.api,包中添加以下文件
IService.aidl

package tk.huayu.api;import tk.huayu.api.Test; // 同一个包下面的也必须导包interface IService{    // in表示这个参数是作为输入参数使用(in/out/inout),作为返回值时不用加    void fun1(in Test test); }

Test.aidl

package tk.huayu.api;parcelable Test; // 声明Test对象

Test2.aidl

package tk.huayu.api;parcelable Test2; // 声明Test2对象,这个是Test中包含的一个属性(对象)

2.实现aidl用到的对象
新建包tk.huayu.api,这个包必须和aidl中一模一样。在包中添加如下文件

Test.java

package tk.huayu.api;import android.os.Parcel;import android.os.Parcelable;public class Test implements Parcelable {    public int testInt=1;    public String testString="Test";    public Test2 test2 = new Test2();    public Test(){    }    int getTestInt(){        return testInt;    }    /**     * 实现Parcelable接口必须实现的方法:     *     * @return 描述这一Parcel是起什么作用的,通过这一整形每个bit来描述其类型,一般会返回0     */    @Override    public int describeContents() {        return 0;    }    /**     * 实现Parcelable接口必须实现的方法:     * 将类所需要传输的属性写到Parcel里,在这个方法里都是使用writeXXX()写入到Parcel     * @param dest 提供发送功能的Parcel     * @param flags 用来指定这样的发送方向,与aidl的in、out、inout三种限定符匹配     */    @Override    public void writeToParcel(Parcel dest, int flags) {        //把该对象所包含的数据写到Parcel        dest.writeInt(testInt);        dest.writeString(testString);        //dest.writeParcelable(test2,flags);        dest.writeValue(test2);    }    /**     * 这个构造方法用于从序列化数据中取出数据。读取的顺序要和writeToParcel()写入的顺序一致     * @param source 数据源     */    private Test(Parcel source){        testInt = source.readInt();        testString = source.readString();        test2 = (Test2)source.readValue(Test2.class.getClassLoader());    }    /**     * 添加一个静态成员,名为CREATOR,该对象实现了Parcelable.Creator接口     */    public static final Parcelable.Creator<Test> CREATOR = new Parcelable.Creator<Test>(){        /**         * 从Parcel中读取数据,返回Test对象。读取的顺序要和writeToParcel()写入的顺序一致         * @param source 数据源         * @return 接收到的对象(通过数据源创建的一个对象)         */        @Override        public Test createFromParcel(Parcel source){            return new Test(source);        }        /**         * 用于创建多个这种实现了Parcelable接口的类。创建多个空对象,不能以某个Parcel对象为基础创建,使用默认的类创始化方法。         * @param size 数组大小         * @return 数组         */        @Override        public Test[] newArray(int size){            return new Test[size];        }    };}

Test2.java

package tk.huayu.api;import android.os.Parcel;import android.os.Parcelable;public class Test2 implements Parcelable {    public int testInt=2;    public String testString="Test2";    public Test2(){    }    int getTestInt(){        return testInt;    }    @Override    public int describeContents() {        return 0;    }    @Override    public void writeToParcel(Parcel dest, int flags) {        dest.writeInt(testInt);        dest.writeString(testString);    }    private Test2(Parcel source){        testInt = source.readInt();        testString = source.readString();    }    public static final Parcelable.Creator<Test2> CREATOR            = new Parcelable.Creator<Test2>(){        @Override        public Test2 createFromParcel(Parcel source){            return new Test2(source);        }        @Override        public Test2[] newArray(int size){            return new Test2[size];        }    };}

3.实现接口
新建包package tk.huayu.demo

MyService .java

package tk.huayu.demo;import android.app.Service;import android.os.IBinder;import android.content.Context;import tk.huayu.api.IService;public class MyService extends Service{    /**     * 被远程调用,运行在appliction1进程中的Binder_x线程(查看进程号 android.os.Process.myPid())     */    public IService.Stub stub = new IServiceInterface();    public class IServiceInterface extends IService.Stub // 注意实现的一定要是Stub,否者远端调用得到的将是null()    {        // 实现AIDL文件中接口的定义的各个方法。        public void fun1(Test test){ // 不再注明in,添加public            ... // 代码略            Log.d("IService","fun1:"+test);        }    }    @Override    protected void onCreate(Bundle savedInstanceState) {        ... // 代码略    }    @Override    public IBinder onBind(Intent intent) {        Log.d("MyService ", "onBind "+android.os.Process.myPid());        return stub;    }    @Override    public boolean onUnbind(Intent intent) {        Log.d("MyService ", "onUnbind");        return super.onUnbind(intent);    }    @Override    public void onDestroy() {        super.onDestroy();    }}

4.声明service
AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?><manifest ...    >    <!-- 添加service外部访问许可(不添加也可以,只是提示警告)。当然,如果service添加了许可,那么客户端也要添加许可            <uses-permission android:name="tk.huayu.edog"/>, 否则客户端访问时将抛出异常 -->    <permission android:protectionLevel="normal" android:name="tk.huayu.demo"/>    <application ...        >        <!-- 声明service,要添加 android:exported="true"否则service是不允许外部的应用进行远程调用        android:process=":remote" // 添加这边表示service在独立的进程运行 -->        <service            android:name="tk.huayu.demo.MyService"            android:exported="true"            android:permission="tk.huayu.demo"            />        ...    </application></manifest>

5.编写客户端
将service的aidl包和api包拷贝到客户端app中(包名不能改变)

MainActivity.java

public class MainActivity extends Activity {    private ServiceConnection serviceConnection = new ServiceConnection(){        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            Log.d("Client","onServiceConnected "+name+"IBinder "+service);            IService service = IService.Stub.asInterface(service);            if(service!=null)            {                try {                    Log.d("Client", "call fun1");                    service.fun1(new Test());                } catch (RemoteException e) {                    e.printStackTrace();                    Log.d("Client", "service is bad");                }            }        }        @Override        public void onServiceDisconnected(ComponentName name) {            Log.d("Client","onServiceConnected "+name);        }    };      @Override    protected void onCreate(Bundle savedInstanceState) {        ...        Intent i = new Intent();        i.setClassName("tk.huayu.demo","tk.huayu.demo.MyService");        this.context.bindService(i, serviceConnection, Context.BIND_AUTO_CREATE);        Log.d("Client", "service bind "+android.os.Process.myPid());    }    @Override    protected void onDestroy() {        super.onDestroy();        unbindService(serviceConnection);    }}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?><manifest ...    >    <!-- 添加许可 -->    <uses-permission android:name="tk.huayu.demo"/>    <application ...        >        ...    </application></manifest>

注:也可以在客户端实现类似IService接口,将接口实例通过参数注册到service,这样service也能远程调用客户端的函数,如果客户端有多个(一般也是有多个)可以使用RemoteCallbackList进行批量回调。

0 0