AIDL:Android Interface Definition Language,即Android接口定义语言
为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程
-
百度百科
过程调用(Remote Procedure Call,RPC)方式来实现。与很多其他的基于RPC的解决方案 一样,Android使用一种接口定义语言(Interface Definition Language,IDL)来公开服务的接口。我们知道4个Android应用程序组件中的3个(Activity、BroadcastReceiver和ContentProvider)都可以进行跨进程访问,另外一个Android应用程序组件Service同样可以。因此,可以将这种可以跨进程访问的服务称为AIDL(Android Interface Definition Language)服务。
- AIDL作为四大跨进程通讯手段之一,我们就算不能完全掌握它,也需要大概了解下它是如何运行的,下面我就写个小例子去展示它。
我会使用本进程AIDL的使用和跨进程AIDL的使用来讲解它
-
列表内容
新建一个项目,在其中建立一个AIDL文件
interface AIDLTest {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
int add(int x,int y);
int multiplication(int x , int y );
}
上面是定义的AIDL接口,里面有两个方法,一个加法一个乘法,我会在本进程实现加法,在外部进程实现乘法,然后log出来
5.创建一个server
private static final String TAG = "server";
public void onCreate()
{
Log.e(TAG, "onCreate");
}
public IBinder onBind(Intent t)
{
Log.e(TAG, "onBind");
return mBinder;
}
public void onDestroy()
{
Log.e(TAG, "onDestroy");
super.onDestroy();
}
public boolean onUnbind(Intent intent)
{
Log.e(TAG, "onUnbind");
return super.onUnbind(intent);
}
public void onRebind(Intent intent)
{
Log.e(TAG, "onRebind");
super.onRebind(intent);
}
private final AIDLTest.Stub mBinder = new AIDLTest.Stub()
{
@Override
public int add(int x, int y) throws RemoteException
{
return x + y;
}
@Override
public int multiplication(int x, int y) throws RemoteException {
return ;
}
注意看最后一段,在这里面实现接口里面定义的方法,然后再onBind中返回给activity,点击进Stub我们可以发现,他其实是一个继承Binder的抽象类
而Binder又是接口IBinder
所以AIDL和binder的关系其实是密不可分的,不过这里暂且不谈binder,我在这里,把乘法的返回值设为0,就是为了区分是本地进程,还是外部进程。
下面是mainactivity的代码
package com.example.myapplication;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity implements ServiceConnection {
private AIDLTest aidlTest;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* 点击BindService按钮时调用
*
* @param view
*/
public void bindService(View view) {
Intent intent = new Intent(MainActivity.this, MyService.class);
bindService(intent, this, Context.BIND_AUTO_CREATE);
}
/**
* 点击bindOtherServer按钮时调用
*
* @param view
*/
public void bindOtherServer(View view) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.example.another","com.example.another.MyOtherServer"));
bindService(intent,this,BIND_AUTO_CREATE);
}
/**
* 点击2+3按钮时调用
*
* @param view
*/
public void add(View view) throws Exception {
if (aidlTest != null) {
int addRes = aidlTest.add(, );
Log.i("bindServer", "这是当前server加法的值为" + addRes);
Toast.makeText(this, addRes + "", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "重新绑定服务端", Toast.LENGTH_SHORT)
.show();
}
}
/**
* 点击2*3按钮时调用
*
* @param view
*/
public void multiplication(View view) throws Exception {
if (aidlTest != null) {
int addRes = aidlTest.multiplication(, );
Log.i("bindServer", "这是当前server乘法的值为0?" + addRes);
Toast.makeText(this, addRes + "", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "重新绑定服务端", Toast.LENGTH_SHORT)
.show();
}
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
aidlTest = AIDLTest.Stub.asInterface(service);
if (aidlTest != null)
{
try {
int addRes = aidlTest.multiplication(, );
Log.i("bindServer", "这是外部server乘法的值为" + addRes);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
这里代码量不多 我就干脆把xml也贴出来,免得给下载链接
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="bindService"
android:text="绑定本地的服务" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="bindOtherServer"
android:text="绑定其他的服务" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="add"
android:text="2+3" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="multiplication"
android:text="2*3" />
</LinearLayout>
上面其实就可以运行了 ,点击绑定本地的服务,点击下面两个计算按键可得
11-28 10:23:56.700 7654-7654/? I/bindServer: 这是当前server加法的值为5
11-28 10:23:57.900 7654-7654/? I/bindServer: 这是当前server乘法的值为0?0
下面在写一个另外一个项目:AIDLModeAnOther,这个的MainActivity和server比较简单
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_main);
startService(new Intent(this,MyOtherServer.class));
}
}
直接启动server即可,不过server中的方法和上面一致,就是这里改一下
private final AIDLTest.Stub mBinder = new AIDLTest.Stub()
{
@Override
public int add(int x, int y) throws RemoteException
{
return x + y;
}
@Override
public int multiplication(int x, int y) throws RemoteException {
return x*y;
}
};
好知道这里能得出乘法的值。
然后再这个项目中也建立一个aidl包,重点来了,这两个项目的aidl要完全一样,从内容到包名。复制上面的下来即可
一切做完了之后,先点击下面这个AIDLModeAnOther运行,成了之后再 点击上面那个项目运行,点击绑定本地的服务,点击计算按键,显示本进程计算结果。再点击绑定其他的服务,就不用点击计算按键了,我图方便,直接就显示出来了 ,如下所示
- :: -/? I/bindServer: 这是当前server加法的值为
- :: -/? I/bindServer: 这是当前server乘法的值为?
- :: -/? I/bindServer: 这是外部server乘法的值为
到这里就算是演示完毕了 不过最后再说一个:从 Android 5.0 以后只能通信显式 Intent 来启动服务
开启服务用我上面所写的那样
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.example.another","com.example.another.MyOtherServer"));
bindService(intent,this,BIND_AUTO_CREATE);
而不能继续使用进程间通信 Intent机制 隐式启动了。
隐式启动就是在你的AndroidManifest,你要启动的服务或activity下加一个
<intent-filter>
<action android:name="xxxxxxxxxx" />
然后在程序中
这样调用它
,好了这篇博客就将这么多,希望看过的人觉得好的留个言,点个赞,谢谢了!