AIDL——你的应用不孤单

来源:互联网 发布:xampp php版本切换 编辑:程序博客网 时间:2024/06/05 18:06

今天聊聊AIDL,Android Interface Definition Language(安卓接口定义语言),即安卓进程间通信。

首先我们知道,狭义来说,一个应用对应一个进程。而如果想跨应用交互,那就涉及到进程间通信,而安卓四大组件都代表一种进程间通信的方式。

但是我们今天说的AIDL,则是通过Service,为什么选择聊Service呢 ?其一 ,因为它的自定义程度最高。其二 ,Service的优先级高。

我们简单理一下思路 。使用AIDL作为进程间通信的方式,那也就是说,我们需要至少两个应用,一个作通信的服务端,一个作通信的客户端。(当然,可以有不止一个客户端,也可以有不止一个服务端)。

那客户端与服务端如何跨进程通信呢 ?这就需要它们有一个共同的通信标准,就是AIDL,姑且理解为一种协议,服务端和客户端各自定义好一摸一样的协议(包括包名/类名/方法名) ,然后服务端提供具体的实现,客户端执行调用。

比如 :客户端通过服务端提供的XX方法 得到了XX结果。

听上去很像接口,有没有?其实个人愚见也是如此,因为接口是一个翻泛概念,你给我提供一个途径,我通过这个途径把参数给你,你处理后把结果给我。符合该模式的,我觉得都可以归为接口。


以下做一个简单的示例,(我们今天不谈IBinder,如果你想更深刻的理解 AIDL,建议还是去认真揣摩揣摩IBinder)

示例的服务端提供一个接口IMyLog ,里面有一个方法sysOut,接受一个String参数,并Log出来。客户端则是去绑定服务端,并调用IMyLog接口的这个方法,传入参数,让其执行。

步骤分为两部份:

第一部分:服务端:

1.首先创建一个文件夹,在其中定义一个AIDL类,如图:

这里写图片描述

注意,这里是AS,所以生成AIDL文件夹的方式不太一样。如果是Eclipse,直接在java路径下生成就好。

2.创建一个Service类:

public class MainService extends Service {    private IBinder iBinder = new IMyLog.Stub(){        @Override        public void sysOut(String content) throws RemoteException {            Log.i("aidl","service get " + content);        }    };    @Override    public IBinder onBind(Intent intent) {        return iBinder;    }    @Override    public void onCreate() {        super.onCreate();        Log.i("aidl","service create");    }}

第二部分:客户端:
1.首先创建一个文件夹,在其中定义一个AIDL类,如图:

这里写图片描述

注意:这个AIDL类必须和服务端的AIDL一摸一样,包括文件夹路径。

2.创建一个客户端Activity:

public class MainActivity extends AppCompatActivity {    private  IMyLog iMyLog;    //ServiceConnection,在绑定成功时返回AIDL的接口IMyLog    private ServiceConnection conn = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            Log.i("aidl","conn is success");            iMyLog = IMyLog.Stub.asInterface(service);        }        @Override        public void onServiceDisconnected(ComponentName name) {            Log.i("aidl","disconn is success");            iMyLog = null;        }    };    @Override    protected void onDestroy() {        Log.i("aidl","on Destroy");        unbindService(conn);        super.onDestroy();    }    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        doBind();    }    //隐式Intent绑定服务端Service,获得ServiceConnection    private void doBind() {        Intent intent = new Intent();        intent.setComponent(new ComponentName("com.lebang.myservice","com.lebang.myservice.MainService"));        bindService(intent,conn, Context.BIND_AUTO_CREATE);    }    //Button的点击事件,点击时调用服务端AIDL方法,传入参数“today I ...”    public void doThing (View view){        Log.i("aidl","client send message");        try {            iMyLog.sysOut(": today I do the aidl");        } catch (RemoteException e) {            e.printStackTrace();            Log.i("aidl","client error");        }    }}

然后启动模拟器,先确保安装上服务端程序,再执行客户端程序。点击Button,会发现,在服务端程序的Log下会打印出:

service get : today I do the aidl
最末,做个简单介绍,如果你发现如上操作会崩溃,原因可能是Manifest文件中未配置可通信。解决方法有两种:1.在客户端服务端Manifest主标签下配置属性 sharedUserId :
     如: android:sharedUserId="com.lebang"
2.在服务端Service中配置属性:如:
   <service            android:name=".MainService"            android:exported="true"/>

抽时间写的,没有整理好语言,谬误之处,欢迎指出。

0 0
原创粉丝点击