您的位置:首页 > 移动开发 > Android开发

Android中的IPC——AIDL方式

2016-08-09 22:35 411 查看
AIDL是实现Android中IPC的一种方式。

通过AIDL我们将各种通信操作以接口方式进行定义,Android SDK则会按照AIDL的规则将AIDL编码成java类嵌入到应用中,然后我们就可以在APP运行时以调用函数的形式来进行IPC了。

与Messenger的区别

实际Messenger进行IPC本质也是以AIDL方式实现的,只不过通过上层接口封装我们不用自己实现AIDL的接口定义。Messenger与AIDL的区别在于——由于Messenger使用Handler处理消息序列,因此Service一次仅接受一个请求,适用于单线程的IPC通讯;AIDL则可以同时处理多个请求,不过这也要求我们的Service具备多线程处理能力。

构成

以下表格是APP与Service中组件及说明:

备注APP类型Service备注
在Service绑定回调中获取到AIDL对象onServiceConnectedConnectiononBindonBind声明周期调用时返回AIDL Stub
获取到AIDL对象,以调用接口AIDLVariableAIDL Stub实现AIDL定义的接口
需要与Service中定义相同AIDL定义文件AIDLAIDL定义文件需要与APP中定义相同
通过图片来展现这种关系,大致为:



实现步骤

使用AIDL大致需要一下步骤:

1.在Service及APP工程中创建相同的AIDL文件,并定义相同接口。

2.在Service的onBind中返回AIDL的Stub

3.在APP中实现ServiceConnection,在onServiceConnected函数中调用Stub.asInterface获取到AIDL对象。

4.在事件响应中按需调用AIDL接口

首先,我们再App与Service工程中建立相同的AIDL接口:

App中——



Service中——



创建好AIDL接口后,在其中添加一个简单的函数,接收两个int值,返回两者相加:

interface TestAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
//String basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
//        double aDouble, String aString);

int add(int alpha, int beta);
}


Android Studio默认添加了一个函数说明在AIDL中可接受的参数类型。

在定义完
add
接口后,Android Studio会触发Gradle自动生成interface的实现类,可以在build文件夹中找到:

package com.example.testaidlservice;
// Declare any non-default types here with import statements

public interface TestAidlInterface extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.example.testaidlservice.TestAidlInterface
{
private static final java.lang.String DESCRIPTOR = "com.example.testaidlservice.TestAidlInterface";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.example.testaidlservice.TestAidlInterface interface,
* generating a proxy if needed.
*/
public static com.example.testaidlservice.TestAidlInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.example.testaidlservice.TestAidlInterface))) {
return ((com.example.testaidlservice.TestAidlInterface)iin);
}
return new com.example.testaidlservice.TestAidlInterface.Stub.Proxy(obj);
}

// 余下略
}


asInterface
即为在App中获取实现AIDL接口的Service的方法。

接下来,在Service工程中创建一个Service,在其中实现AIDL的接口:

public class TestService extends Service {

private static final String TAG = TestService.class.getSimpleName();

public TestService() {
}

// 实现AIDL接口,并在onBind中返回给App
TestAidlInterface.Stub mStub = new TestAidlInterface.Stub() {

@Override
public int add(int alpha, int beta) throws RemoteException {
return alpha + beta;
}
};

@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
Log.i(TAG, "testService onBind");
// 返回AIDL接口的对象
return mStub;
}

}


然后在App工程中,启动Service,并通过
asInterface
接口获取到AIDL的实现,进一步调用:

public class MainActivity extends AppCompatActivity {

private Context mContext;

private TextView resultText;
private Button testAddButton;

// 定义AIDL接口实现类的对象
private TestAidlInterface testAidl;

private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// onBind对象返回了AIDL的实现类,调用其中的asInterface方法来获取到可调用对象
testAidl = TestAidlInterface.Stub.asInterface(service);
}

@Override
public void onServiceDisconnected(ComponentName name) {

}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mContext = this;

resultText = (TextView) findViewById(R.id.result_text);
testAddButton = (Button) findViewById(R.id.test_add);

testAddButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 判断是否需要启动Service
if (testAidl == null) {
Intent intent = new Intent();
intent.setAction("android.intent.action.TestAidlService");
intent.setPackage("com.example.testaidlservice");
bindService(intent, conn, Context.BIND_AUTO_CREATE);
} else {
try {
// 调用AIDL接口获取返回值
String result = "result: " + testAidl.add(5, 8);
resultText.setText(result);
} catch (RemoteException e) {
e.printStackTrace();
Toast.makeText(MainActivity.this, "RemoteException", Toast.LENGTH_SHORT).show();
}

}

}
});

}

@Override
public void onBackPressed() {
super.onBackPressed();
unbindService(conn);
}
}


安装两个APP后,无需启动Service,直接运行TestAidlApp。

此时含有AIDL的Service尚未启动,因此第一次点击按钮,会触发启动Service,这时Service会直接在另一个进程中启动;

然后再次点击按钮,就可以通过获取到的AIDL对象直接运行Service中方法,并拿到返回结果显示在界面上了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android