前言
最近使用Android studio开发的时候,需要用到系统类,导入jar包可以解决该问题,但由于该应用需要做到平台兼容,导入jar包的方式会显得APP很臃肿。最后考虑使用AIDL方式,APP端作为客户端,系统源码实现服务端。
正文
AIDL是一个缩写,全称是Android Interface Definition Language(Android接口定义语言)。主要用于进程间通信。下面详细说说服务端和客户端该如何创建AIDL,并让两个进程进行通讯。
服务端
这里服务端是在系统源码中实现,网上查找资料,都说先创建一个AIDL文件,然后在Android.mk文件中添加AIDL文件的编译,就会生成一个对应的Java文件。折腾了很久,都没生出一个Java文件,坑。 如果没有Java文件生成,则自己创建一个即可,下面说说操作。
创建AIDL文件
AIDL接口,需要有一个AIDL文件进行描述说明,说明服务端支持什么样的接口。AIDL的接口样式如下:
//ITestService.aidl
package com.xxx.yyy;
interface ITestService {
boolean write(String str);
String read();
}
这里的AIDL文件,引用的包名为服务端所在的进程包名。
Android.mk文件中引用AIDL文件
Android.mk文件中为整个进程的编译规则,这里添加了AIDL文件后,需要将AIDL文件添加进去,否则会编译失败,增加如下语句即可:
LOCAL_SRC_FILES += $(call all-Iaidl-files-under, src)
这里表示编译AIDL文件。
创建AIDL相应的Java文件
既然不能生成AIDL相应的Java文件,那我们就要自己去创建Java文件。Java文件的创建内容如下:
//TestService.java
package com.xxx.yyy;
import android.content.Context;
import android.content.IntentFilter;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class TestService extends Service {
static private final String TAG = "TestService";
@Override
public void onCreate() {
super.onCreate();
}
ITestService.Stub mBinder = new ITestService.Stub() {
@Override
public boolean write(String str) throws RemoteException {
return false;
}
@Override
public String read() throws RemoteException {
return null;
}
};
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
Androidmanifest.xml注册服务
添加服务端的AIDL和Java文件后,还需要注册服务,在Androidmanifest.xml文件中注册如下:
<service android:name=".TestService"
android:process=":remote"
android:exported="true">
<intent-filter>
<action android:name="com.xxx.yyy.TestService"/>
</intent-filter>
</service>
到这里,服务端的工作就完成了。
客户端
客户端是用AS开发的,所以我们需要在AS中也创建一个AIDL文件,不然AS没接口可调用。这里直接将服务端的AIDL文件拷贝过来即可。这里要特别注意的是,AIDL文件的路径。如果路径不匹配,AS就会编译错误。这里说的路径匹配,是指AIDL文件中,AIDL文件所在的文件路径要符合AIDL文件引用的包名。这里结合本例说明。先放上AIDL文件的路径:
as_project/src/main/aidl/com/xxx/yyy/ITestService.aidl
首先先在main目录下,创建一个aidl的文件夹,接下来的目录级别就是跟随着AIDL文件中的包名来了:
package com.xxx.yyy;
客户端绑定服务
拷贝AIDL文件后,接下来就是客户端绑定服务,使用服务端的接口。先贴上代码:
import com.xxx.yyy.ITestService;
static private ITestService mTestService;
static private ServiceConnection mCon;
void init(Context context) {
mCon = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mTestService = ITestService.Stub.asInterface((IBinder) service);
Log.d(TAG,"onServiceConnected! ");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG,"onServiceDisconnected! ");
}
};
Intent intent = new Intent();
intent.setPackage("com.xxx.yyy");
Boolean res = context.bindService(intent, mCon, Context.BIND_AUTO_CREATE);
}
init方法放在activity的onCreate方法中调用即可。
这里需要注意的地方有两点:
1.bindservice的时候,传入的intent需要setpackage,这个package名为服务端的包名,否则bindservice的时候会返回false。
2.bindservice成功后,onServiceConnected不是马上回调,会延迟,所以绑定成功后,需要等待onServiceConnected成功回调后,再去调用服务端的接口,否则你会看到报空异常。
服务端方法调用
try {
boolean res = mTestService.write(str);
}catch (Exception e) {
e.printStackTrace();
}
结语
AIDL的实现到此结束。
互动
如果文章存在错误描述,可直接留言,一起探讨!
可能感兴趣的文章
最后
我在微信公众号也有写文章,更新比较及时,有兴趣者可以关注如下公众号!