AIDL(Android Interface Definition Language)是Android接口定义语言的意思,它可以用于让某个Service与多个应用程序组件之间进行跨进程通信,从而可以实现多个应用程序共享同一个Service的功能。而跨进程通信的真正意义是为了让一个应用程序去访问另一个应用程序中的Service,以实现共享Service的功能。
我的AIDL中,一般是写2个项目,分为服务端和客户端。2个项目的具体代码编写和使用步骤如下:
服务端(项目名字为serviceAIDLmy,其具体目录结构如下):
(1)新建aidl文件,这个文件里面写java的代码,具体写一个interface接口,接口里面写要使用的具体函数声明。
当文件保存成功后,工具会自动在gen目录下,生成一个同名的java文件。
<span style="font-size:14px;">package com.example.serviceaidlmy;
interface MyAIDLService {
int plus(int a, int b);
String toUpperCase(String str);
}</span>
(2)写一个MyService继承Service,在其中的onBind方法中,返回一个Stub的具体实例,因为Stub是binder的子类,所以当然可以返回。然后在实例的过程中,把接口的2个抽象方法具体实现。
<span style="font-size:14px;">public class MyService extends Service {
public static final String TAG ="MyService"; //这个是常量
public IBinder onBind(Intent intent) {
// 因为Stub其实就是Binder的子类,所以在onBind()方法中可以直接返回Stub的实现。
return mbinder;
}
//郭林的博客里写 MyAIDLService.Stub mBinder = new Stub() ,但是会报错,改用下面的
Stub mbinder = new Stub() {
@Override
public String toUpperCase(String str) throws RemoteException {
if (str != null) {
return str.toUpperCase();
}
return null;
}
@Override
public int plus(int a, int b) throws RemoteException {
return a+b;
}
};
public void onCreate() {
super.onCreate();
Log.d(TAG, "service的进程号码是" +Process.myPid());
Log.d(TAG, "Service已经创建了");
}
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "ServiceonStartCommand() excuted");
return super.onStartCommand(intent, flags, startId);
}
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "Service已经销毁了");
}
}</span>
<span style="font-size:14px;"> <service
android:name="com.example.serviceaidlmy.MyService"
>
<intent-filter>
<action android:name="com.example.serviceaidlmy.MyAIDLService" />
</intent-filter>
</service></span>
接下来写客服端(项目起名为serviceAIDLmyClient)
(1)先把服务端的aidl文件和包名一同拷贝到客户端里,结构如下图
(2)在客户端的MainActivity中,编写代码
<span style="font-size:14px;">public class MainActivity extends Activity {
protected static final String TAG = "MyService";
private MyAIDLService myAIDLService;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myAIDLService = MyAIDLService.Stub.asInterface(service);
try {
int result = myAIDLService.plus(50, 50);
String upperStr = myAIDLService.toUpperCase("comes from ClientTest");
Log.d(TAG, "result is " + result);
Log.d(TAG, "upperStr is " + upperStr);
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button bindService = (Button) findViewById(R.id.bind_service);
Button unbindService = (Button) findViewById(R.id.unbind_service);
bindService.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 隐式调用服务端的Service,在这之前服务端的service要用intent filter写下下面一样的句子
Intent intent = new Intent("com.example.serviceaidlmy.MyAIDLService");
bindService(intent, connection, BIND_AUTO_CREATE);
}
});
unbindService.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
unbindService(connection);
}
});
}
}</span>
<span style="font-size:14px;"><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:id="@+id/bind_service"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Bind Service"
/>
<Button
android:id="@+id/unbind_service"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="unBind Service"
/>
</LinearLayout>
</span>
以上就把客户端也写好了,可以看到,客户端里面根本就没有写Service,而是通过AIDL调用了服务端里面的Service。
首先记得先启动服务端,然后启动客户端。可以成功运行了,在客户端的logcat里有具体打印