您的位置:首页 > 大数据 > 人工智能

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,就可以调用其方法了

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: