Service进程间通信AIDL
2016-06-13 11:40
483 查看
AIDL是Android Interface Definition Language的缩写,意思就是安卓接口定义语言。
IPC是Interprocess Communication的缩写,意思就是进程间通信。
类似于其他你使用过的接口定义语言,AIDL允许你使用接口来实现客户端和服务端的进程通信(IPC)。
在Android系统中,一个进程是不能访问另一个进程的内存的,也就是无法数据或方法共用。所以,我们要把对象分解为系统可以识别的原始数据,从而达到数据共通。而这个代码的编写是非常枯燥和麻烦的。所以Android系统中我们使用AIDL来实现!
注意:如果你要使多个客户端访问服务或者要在服务中使用多线程,那么使用AIDL是必要的。如果你不需要在不同的应用之间执行并发的IPC,那么是用Binder的方式就够了。或者你需要实现IPC,但是不需要用到多线程,那么使用Messenger的方式就可以实现进程通信了。不管怎样,在使用AIDL之前,你最好已经明白绑定服务的具体作用和含义!
在你开始设计你的AIDL接口前,注意调用AIDL接口使用的函数。你不应该对调用发生的线程做假设。所发生的不同取决于调用是从本地进程或远程进程中的线程的,例如abc:
a.本地进程中的调用是在同一个线程中执行的。如果这是你的主线程,该线程在AIDL接口中继续执行。如果是另一个线程,那就是在服务中执行你的代码。因此,如果只有本地线程访问服务,你可以完全是用绑定服务的方式来实现就可以了!
b.从一个远程线程池中调用方法到你自己的进程中。您必须为来自未知线程的数据同步做准备,同时可能发生在同一时间发生多个回调。意思就是,AIDL接口的实现必须是线程安全的。
c.当调用远程的数据时,如果远程服务并没有阻塞,它仅仅发送数据并立即返回,接口的实现就将定期收到数据,类似于通过远程服务得到Binder对象!如果只是单独的使用本地数据,就没有关系,数据是同步的。
1.定义一个AIDL接口
a.AS创建一个服务端项目(modle)并新建一个.aidl的文件
AS会创建相应目录并生成一个AIDL文件,在文件中我们写上自己需要的方法,类似于普通接口
b.然后我们需要使用Build菜单的Make Project,这个操作千万不要忘记,用于创建aidl相关的java文件。但是在AS的目录中你是找不到这个java文件的,因为它隐藏项目构建的debug目录中,安装使用的时候才会添加进去,所以你每修改一次aidl,就需要make project一下!
c.创建一个Service服务,实例化aidl并具体实现其中的方法,通过它的Stub()方法得到stub对象(myBinder),最后在service的onBind()方法中返回它就可以与客户端建立联系了。
d.最后,还需要在AndroidManifest.xml中配置service
2.在客户端建立AIDL进行通信
a.我们新建一个项目(modle),并把Service中建立的aidl文件连同包都复制过来
b.少不了的,客户端也需要Make Project
c.在客户端的一个Activity中,绑定远程服务,注意setPackage就是服务端apk文件的包名
d.最后,在建立连接的方法中得到IBinder对象,通过它实例化aidl,就可以调用其方法了
3.实践:安装服务端,安装客户端。服务端就算没有启动,我们也可以通过客户端来调用服务端的方法。并且多个客户端共用此服务的方法!
到此关于AIDL进程间通信就介绍完成了,还有不明白的同学可以去看看官方文档:
https://developer.android.com/guide/components/aidl.html
IPC是Interprocess Communication的缩写,意思就是进程间通信。
类似于其他你使用过的接口定义语言,AIDL允许你使用接口来实现客户端和服务端的进程通信(IPC)。
在Android系统中,一个进程是不能访问另一个进程的内存的,也就是无法数据或方法共用。所以,我们要把对象分解为系统可以识别的原始数据,从而达到数据共通。而这个代码的编写是非常枯燥和麻烦的。所以Android系统中我们使用AIDL来实现!
注意:如果你要使多个客户端访问服务或者要在服务中使用多线程,那么使用AIDL是必要的。如果你不需要在不同的应用之间执行并发的IPC,那么是用Binder的方式就够了。或者你需要实现IPC,但是不需要用到多线程,那么使用Messenger的方式就可以实现进程通信了。不管怎样,在使用AIDL之前,你最好已经明白绑定服务的具体作用和含义!
在你开始设计你的AIDL接口前,注意调用AIDL接口使用的函数。你不应该对调用发生的线程做假设。所发生的不同取决于调用是从本地进程或远程进程中的线程的,例如abc:
a.本地进程中的调用是在同一个线程中执行的。如果这是你的主线程,该线程在AIDL接口中继续执行。如果是另一个线程,那就是在服务中执行你的代码。因此,如果只有本地线程访问服务,你可以完全是用绑定服务的方式来实现就可以了!
b.从一个远程线程池中调用方法到你自己的进程中。您必须为来自未知线程的数据同步做准备,同时可能发生在同一时间发生多个回调。意思就是,AIDL接口的实现必须是线程安全的。
c.当调用远程的数据时,如果远程服务并没有阻塞,它仅仅发送数据并立即返回,接口的实现就将定期收到数据,类似于通过远程服务得到Binder对象!如果只是单独的使用本地数据,就没有关系,数据是同步的。
1.定义一个AIDL接口
a.AS创建一个服务端项目(modle)并新建一个.aidl的文件
AS会创建相应目录并生成一个AIDL文件,在文件中我们写上自己需要的方法,类似于普通接口
b.然后我们需要使用Build菜单的Make Project,这个操作千万不要忘记,用于创建aidl相关的java文件。但是在AS的目录中你是找不到这个java文件的,因为它隐藏项目构建的debug目录中,安装使用的时候才会添加进去,所以你每修改一次aidl,就需要make project一下!
c.创建一个Service服务,实例化aidl并具体实现其中的方法,通过它的Stub()方法得到stub对象(myBinder),最后在service的onBind()方法中返回它就可以与客户端建立联系了。
d.最后,还需要在AndroidManifest.xml中配置service
2.在客户端建立AIDL进行通信
a.我们新建一个项目(modle),并把Service中建立的aidl文件连同包都复制过来
b.少不了的,客户端也需要Make Project
c.在客户端的一个Activity中,绑定远程服务,注意setPackage就是服务端apk文件的包名
d.最后,在建立连接的方法中得到IBinder对象,通过它实例化aidl,就可以调用其方法了
package cq.cake.service.client; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.TextView; import butterknife.Bind; import butterknife.ButterKnife; import butterknife.OnClick; import cq.cake.servicetest.IMyAidlInterface; public class MainActivity extends AppCompatActivity { public static boolean mBind = false; @Bind(R.id.tv_text) TextView tvText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); } @OnClick(R.id.btn_bindservice) public void doClick(View view) { Log.d("TAG", "点击了绑定 "); //.首先要绑定服务,这里的Intent参数就是服务端AndroidManifest.xml中配置的action名称 Intent intent = new Intent("cq.cake.servicetest.MyAIDL_ACTION"); intent.setPackage("cq.cake.servicetest"); bindService(intent, connection, BIND_AUTO_CREATE); } private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { IMyAidlInterface iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service); try { int result = iMyAidlInterface.plus(50, 50); String upperStr = iMyAidlInterface.toUpperCase("comes from ClientTest"); tvText.setText("调用远程服务运行方法后" + "\n" + "50+50 = " + result + "\n" + "comes from ClientTest 转换大写为 " + "\n" + upperStr); } catch (RemoteException e) { e.printStackTrace(); } mBind = true; } @Override public void onServiceDisconnected(ComponentName name) { mBind = false; } }; @Override protected void onDestroy() { super.onDestroy(); Log.d("TAG", "onDestroy "); if (mBind) { unbindService(connection); mBind = false; } } }
3.实践:安装服务端,安装客户端。服务端就算没有启动,我们也可以通过客户端来调用服务端的方法。并且多个客户端共用此服务的方法!
到此关于AIDL进程间通信就介绍完成了,还有不明白的同学可以去看看官方文档:
https://developer.android.com/guide/components/aidl.html
相关文章推荐
- web.xml中<security-constraint>和四种认证类型
- AIDL文件简析
- max plugin wizard,project creation faild解法
- 关于flex的安全沙箱问题配置crossdomain.xml仍然出现安全沙箱问题
- kylin mondrian saiku interaction
- Table is marked as crashed and should be repaired
- AIX下设置ASM的共享访问
- Kylin, Mondrian, Saiku系统的整合
- 意念控制飞行器
- Error Domain=NSCocoaErrorDomain Code
- POJ_1273_Drainage Ditches(USACO 93)_最大流
- Paint(画笔)类的使用
- Factorial Trailing Zeroes
- 线段树(main函数自由)
- RAID磁盘阵列
- Lock wait timeout exceeded; try restarting......
- 责任链模式(Chain of Responsibility Pattern)
- Django TemplateSyntaxError Could not parse the remainder: '()'
- main方法的参数
- setCentralWidget就可以把Qwidget设置为QMainWindow的主窗口