Aidl 进程间语言的简单使用与demo

    AIDL (Android Interface Definition Language), Android接口定义语言,Android提供的IPC (进程间通信)的一种独特实现。

      当你需要一个远程的service帮助你完成一些东西(最常见的音乐播放程序),同时也需要与它进行一些交互的时候  你就可以用Aidl实现(当然也可以用广播 不过效率比较低下 )

如何定义一个Aidl文件

  必须在一个.aidl文件中使用java语法定义你的AIDL接口,然后在提供service的应用中和任何绑定到这个service的应用中的源代码中保存它。 注意几个问题 1.不能使用public等关键字去定义你的接口  抽象方法同理。2.你使用的任何一个自定义类 都需要导包 即使你的自定义类与aidl文件在同一个接口下 下面贴出来一个实例

 首先建立一个新工程 工程完成以后 就建立最重要的aidl文件  

aidl既然是接口定义语言 自然写法与接口类似 本人使用的是as 建造方法是右键你的moudle 选择AIDL 新建文件


文件创建后 会在src下生成一个与java同级的文件夹 你建立的aidl文件就在这个文件夹下

下面就可以编写你自己想定义的抽象方法 (注意不要使用public 关键字)

// IMyAidl.aidl
package com.example.main.aidltest;

// Declare any non-default types here with import statements

import com.example.main.aidltest.enity.Human;

interface IMyAidl {

    String getMse();

    void send(in Human human);

    void sendMes(String str);

     Human getHuman(String name,int age,String sex);

}

我定义了四个方法  基本涵盖了常用的几种形式  这里注意  aidl语言支持Java 的原生类型、String CharSequence、List  Map(里面的类型也必须是java的基本类型与String CharSequence)这些类型在使用的时候不需要导包就可以直接使用 但如果你需要使用自定义类型时候  一定要注意我以下说的话

自定义类可以使用  但是要注意  一定要继承Parcelable接口 如果不清楚什么是Parcelable的话 

请看http://blog.csdn.net/u012702547/article/details/47151001  点击打开链接

实现接口以后 也不能使用  因为你编译以后会报 couldn't find import for class 

你需要在你的aidl文件夹下建立一个与你的自定义类同名的aidl文件  并在在你的抽象方法中 引包(引的是你的自定义类名.aidl文件位置  不是自定义类的位置)

并且标注你文件是 in out 还是 inout属性 不明白的这三种关键字用法的 请看

http://www.open-open.com/lib/view/open1469494342021.html点击打开链接

我们实际操作下

首先是你自己的自定义类 

public class Human implements Parcelable {
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    private String name ;//名字
    private int age;//年龄
    private String sex;//性别

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.name);
        dest.writeInt(this.age);
        dest.writeString(this.sex);
    }

    public Human(String name,int age,String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    protected Human(Parcel in) {
        this.name = in.readString();
        this.age = in.readInt();
        this.sex = in.readString();
    }

    public static final Parcelable.Creator<Human> CREATOR = new Parcelable.Creator<Human>() {
        @Override
        public Human createFromParcel(Parcel source) {
            return new Human(source);
        }

        @Override
        public Human[] newArray(int size) {
            return new Human[size];
        }
    };
}

同时 在你的aidl文件夹下建立你的自定义类的aidl文件 


// Human.aidl
package com.example.main.aidltest.enity;

parcelable Human;

最后在你需要的方法上 加入你的自定义类并加上关键字 

void send(in Human human);

一个进程间通信的文件就建好了  下面就该建立一个远程服务了  不多说 直接上代码 

public class YCService extends Service {
    public YCService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        //   return super.onStartCommand(intent, flags, startId);
        return START_NOT_STICKY;//不重启
    }
private final IMyAidl.Stub aidl=new IMyAidl.Stub() {
    @Override
    public String getMse() throws RemoteException {
        return "远程service 向你问好";
    }

    @Override
    public void send(Human human) throws RemoteException {LPLogUtil.debug(" 服务",human.getName()+human.getSex()+human.getAge());
    }

    @Override
    public void sendMes(String str) throws RemoteException {
        Toast.("服务",“activity说:”+str);
    }

    @Override
    public Human getHuman(String name, int age, String sex) throws RemoteException {
        Human human=new Human(name,age,sex);
        return human;
    }
};

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return aidl;
    }
}

同时注意在你的manifests中注册

<service
            android:name=".service.YCService"
            android:enabled="true"
            android:exported="true"
            android:launchMode="singleTop"
            android:process=":remote">
        </service>

  Android SDk工具基于你的.aidl文件使用java语言生成一个接口 这个接口有一个内部抽象类,叫做Stub,它是继承Binder并且实现你AIDL接口的 你必须继承这个Stub类并且实现这些方法 实现service并且覆盖onBind()方法返回你的Stub实现类。 当你编译你的应用时,Android SDK工具生成一个.java接口文件用你的.aidl文件命名生成的接口包含一个名字为Stub的子类,这是一个它父类的抽象实现,并且声明了.aidl中所有的方法。 Stub也定义了一些辅助的方法,最显著的就是asInterface(),它是用来接收一个IBinder(通常IBinder传递给客户端的onServiceConnected()回调方法)并且返回一个Stub接口的实例 。一旦你为service实现了接口,你需要把它暴露给客户端,这样他们才能绑定到上面 为了给你的service暴露接口,继承Service并且实现onBind()方法返回一个你实现生成的Stub类。

这样一个远程服务就做好了  现在做本地处理   

一个最简单的activity 与四个按钮 这里就不粘上xml文件了  

public class MainActivity extends AppCompatActivity {
    private Activity activity;
    private IMyAidl myAidl;
    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            myAidl = IMyAidl.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            myAidl = null;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        activity = this;
        init();
    }



    private void init() {
        Button startbind = (Button) findViewById(R.id.button);
        Button getmse = (Button) findViewById(R.id.button2);
        Button getHuman = (Button) findViewById(R.id.button3);
        Button interactive = (Button) findViewById(R.id.button4);
        startbind.setOnClickListener(listener);
        getmse.setOnClickListener(listener);
        getHuman.setOnClickListener(listener);
        interactive.setOnClickListener(listener);
    }
    Human human = new Human("张三", 12, "男");
    private final View.OnClickListener listener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.button:
                    Intent intent = new Intent(activity, YCService.class);
                    bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
                    break;
                case R.id.button2:
                    try {
                        if (myAidl != null) {
                            myAidl.sendMes("给远程大佬递茶");
                            myAidl.send(human);
                        } else {
                            Toast.makeText(activity, "服务未绑定", Toast.LENGTH_SHORT).show();
                        }
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                    break;
                case R.id.button3:
                    try {
                        if (myAidl != null) {
                            Toast.makeText(activity, myAidl.getMse(), Toast.LENGTH_SHORT).show();
                        } else {
                            Toast.makeText(activity, "服务未绑定", Toast.LENGTH_SHORT).show();
                        }
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                    break;
                case R.id.button4:
                    try {
                        if (myAidl != null) {
                            Human human = myAidl.getHuman("李雪", 11, "女");
                            Toast.makeText(activity, human.getName() + human.getAge() + human.getSex(), Toast.LENGTH_SHORT).show();
                        } else {
                            Toast.makeText(activity, "服务未绑定", Toast.LENGTH_SHORT).show();
                        }
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                    break;
                default:

                    break;
            }
        }
    };

}

ServiceConnection的作用就是将远程服务转化成一个你能直接使用的对象 注意要与远程服务绑定  不然就是空哦
ok都完事了 我们运行一下   

远程端







   
最后 我的demo  点击打开链接
  
 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值