0
点赞
收藏
分享

微信扫一扫

远程服务Service & AIDL & IPC


为了让远程Service与多个应用程序的组件(四大组件)进行跨进程通信(IPC),需要使用AIDL

IPC:Inter-Process Communication,即跨进程通信
AIDL:Android Interface Definition Language,即Android接口定义语言;用于让某个Service与多个应用程序组件之间进行跨进程通信,从而可以实现多个应用程序共享同一个Service的功能。

远程服务与本地服务不同点在于,它是运行在独立进程中,常常向多个应用提供服务。
那么其他应用应该如何与远程服务通信呢?在Android中提供了AIDL的机制进行IPC进程间通信。

创建远程服务Service

远程服务Service,要通过以下步骤建立起来:
步骤1:定义AIDL文件,并声明提供服务的接口

// IMyAidlInterface.aidl
package com.ti.remoteservice;
// Declare any non-default types here with import statements
interface IMyAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
// AIDL中支持以下的数据类型
// 1. 基本数据类型
// 2. String 和CharSequence
// 3. List 和 Map ,List和Map 对象的元素必须是AIDL支持的数据类型;
// 4. AIDL自动生成的接口(需要导入-import)
// 5. 实现android.os.Parcelable 接口的类(需要导入-import)
void aidlService();
}

步骤2:在Service子类中实现AIDL中定义的接口方法,并定义生命周期的方法

package com.ti.remoteservice;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class RemoteService extends Service {

// 实例化AIDL的Stub类(Binder的子类)
IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public void aidlService() throws RemoteException {
Log.d("远程服务##", "客户端通过AIDL与远程后台成功通信");
}
};

public RemoteService() {
}

// 重写接口里定义的方法
@Override
public void onCreate() {
super.onCreate();
Log.d("远程服务##", "onCeate创建服务");
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("远程服务##", "onStartCommand运行服务");

return super.onStartCommand(intent, flags, startId);
}

@Override
public IBinder onBind(Intent intent) {
Log.d("远程服务##", "onBind绑定服务");
// 在onBind()返回继承自Binder的Stub类型的Binder,非常重要
return mBinder;
}

@Override
public boolean onUnbind(Intent intent) {
Log.d("远程服务##", "onUnbind解绑服务");

return super.onUnbind(intent);
}

@Override
public void onDestroy() {
Log.d("远程服务##", "onDestroy销毁服务");

super.onDestroy();
}
}

步骤3:在AndroidMainfest.xml中注册服务,并且声明为远程服务

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ti.remoteservice">
...
<application
...>
<service
android:name=".RemoteService"
android:enabled="true"
android:exported="true"<!--设置可被其他进程调用-->
android:process=":remote"><!--将本地服务设置成远程服务-->
<intent-filter>
<!--该Service可以响应带有com.ti.remoteservice.IMyAidlInterface这个action的Intent。-->
<!--此处Intent的action必须写成“服务器端包名.aidl文件名”-->
<action android:name="com.ti.remoteservice.IMyAidlInterface"/>
</intent-filter>
</service>
...
</application>

</manifest>

至此,远程服务Service就已经完成了。
​​​远程服务demo已上传至Github,欢迎下载学习​​。

要使用该远程服务的应用要做的事

步骤1:原封不动地(包名要有服务端的一样)复制远程服务Service端的AIDL文件到本应用对应的目录下。(如果复制的AIDL文件所在的包路径与服务端的不一样,运行程序时就会崩溃)
步骤2:使用Stub.asInterface接口获取远程服务的Binder,根据需要调用服务提供的接口方法。

// 定义aidl接口变量
private IMyAidlInterface mAIDL_Service;

//创建ServiceConnection的匿名类
private ServiceConnection connection = new ServiceConnection() {

// 重写onServiceConnected()方法和onServiceDisconnected()方法
// 在Activity与Service建立关联和解除关联的时候调用
@Override
public void onServiceDisconnected(ComponentName name) {
}

//在Activity与Service建立关联时调用
@Override
public void onServiceConnected(ComponentName name, IBinder service) {

//使用AIDLService1.Stub.asInterface()方法获取服务器端返回的IBinder对象
//将IBinder对象传换成了mAIDL_Service接口对象
mAIDL_Service = IMyAidlInterface.Stub.asInterface(service);

try {
// 通过该对象调用在MyAIDLService.aidl文件中定义的接口方法,从而实现跨进程通信
mAIDL_Service.aidlService();

} catch (RemoteException e) {
e.printStackTrace();
}
}
};

步骤3:通过Intent指定远程服务的服务名称和所在的包,绑定远程Service。

// 通过Intent指定服务端的服务名称和所在包,与远程Service进行绑定
// 参数与服务器端的action要一致,即"服务器包名.aidl接口文件名"
Intent intent = new Intent("com.ti.remoteservice.IMyAidlInterface");
// Android5.0后无法只通过隐式Intent绑定远程Service
// 需要通过setPackage()方法指定包名
intent.setPackage("com.ti.remoteservice");
// 绑定服务,传入intent和ServiceConnection对象
bindService(intent, connection, Context.BIND_AUTO_CREATE);

​​客户端demo已上传至Github,欢迎下载学习。​​

谢谢阅读。


举报

相关推荐

0 条评论