问题背景
- 客户需要rom提供一些系统app才能操作的接口;
- 为客户开发了一些在rom中实现的功能,客户需要自己调用功能接口;
设计思路
- 通过增加一个系统的模块(视具体需求拥有系统签名或者system uid),提供aidl文件给第三方app进行跨进程调用。
- 在提供aidl文件的基础上,通过封装sdk,提供aar或者jar包给第三方app。
操作步骤
server端编码
android studio 创建OpenApiDemo工程
(这个工程是要放在rom中编译的,作为三方app aidl调用的对象)
以传输apn信息为例(如果不需要通过跨进程传输对象,直接参考步骤3)
-
首先需要创建一个KimApn.aidl
ps:注意包名位置
// KimApn.aidl
package com.kim.openapi;
// Declare any non-default types here with import statements
parcelable KimApn;
- 定义一个KimApn类
package com.kim.openapi;
import android.os.Parcel;
import android.os.Parcelable;
public class KimApn implements Parcelable {
private String name;
private String apn;
private String httpProxy;
private String httpPort;
private String user;
private String server;
private String password;
public static class Builder {
private String name;
private String apn;
private String httpProxy;
private String httpPort;
private String user;
private String server;
private String password;
public Builder setName(String name) {
this.name = name;
return this;
}
public Builder setApn(String apn) {
this.apn = apn;
return this;
}
public Builder setHttpProxy(String httpProxy) {
this.httpProxy = httpProxy;
return this;
}
public Builder setHttpPort(String httpPort) {
this.httpPort = httpPort;
return this;
}
public Builder setUser(String user) {
this.user = user;
return this;
}
public Builder setServer(String server) {
this.server = server;
return this;
}
public Builder setPassword(String password) {
this.password = password;
return this;
}
public KimApn createKimAPN() {
return new KimApn(name, apn, httpProxy, httpPort, user, server, password);
}
}
public static final Creator<KimApn> CREATOR = new Creator<KimApn>() {
@Override
public KimApn createFromParcel(Parcel in) {
return new KimApn(in);
}
@Override
public KimApn[] newArray(int size) {
return new KimApn[size];
}
};
@Override
public String toString() {
return "KimApn{" +
"name='" + name + '\'' +
", apn='" + apn + '\'' +
", httpProxy='" + httpProxy + '\'' +
", httpPort='" + httpPort + '\'' +
", user='" + user + '\'' +
", server='" + server + '\'' +
", password='" + password + '\'' +
'}';
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(apn);
dest.writeString(httpProxy);
dest.writeString(httpPort);
dest.writeString(user);
dest.writeString(server);
dest.writeString(password);
}
public String getName() {
return name;
}
public String getApn() {
return apn;
}
public String getHttpProxy() {
return httpProxy;
}
public String getHttpPort() {
return httpPort;
}
public String getUser() {
return user;
}
public String getServer() {
return server;
}
public String getPassword() {
return password;
}
public KimApn(String name, String apn, String httpProxy, String httpPort, String user, String server, String password) {
this.name = name;
this.apn = apn;
this.httpProxy = httpProxy;
this.httpPort = httpPort;
this.user = user;
this.server = server;
this.password = password;
}
protected KimApn(Parcel in) {
readFromParcel(in);
}
public void readFromParcel (Parcel in) {
name = in.readString();
apn = in.readString();
httpProxy = in.readString();
httpPort = in.readString();
user = in.readString();
server = in.readString();
password = in.readString();
}
}
- 定义需要提供的aidl接口
IKimOpenApiManagerService
// IKimOpenApiManagerService.aidl
package com.kim.openapi;
// Declare any non-default types here with import statements
import com.kim.openapi.KimApn;
interface IKimOpenApiManagerService {
List<KimApn> getCurrentApnList();
int addApn(inout KimApn apn);
}
- 创建一个 Service 供客户端远程绑定
package com.kim.openapi;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import java.util.List;
public class KimOpenApiManagerService extends Service {
public KimOpenApiManagerService() {
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public IBinder onBind(Intent intent) {
return stub;
}
private IKimOpenApiManagerService.Stub stub = new IKimOpenApiManagerService.Stub() {
@Override
public List<KimApn> getCurrentApnList() throws RemoteException {
return null;
}
@Override
public int addApn(KimApn apn) throws RemoteException {
return -1;
}
};
}
- AndroidManifest.xml的修改
<service android:name="com.kim.openapi.KimOpenApiManagerService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="kim.openapi.action.start"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</service>
6.将工程代码抽离到rom中编译,并赋予系统签名与权限
7.客户端(模仿第三方app调用)编码
封装aidl成jar或aar
到此步骤为止,只需要将上述aidl文件提供给客户,即可完成第三方app通过api调用rom新增的功能接口。但是提供的aidl有可能会出现被误修改等情况,为了避免这种情况,对aidl进行sdk封装。
- 使用android studio 新建一个module ,类型为Android Library,包名任意
- 将server端工程的aidl文件夹直接复制到新的module下对应位置,注意此处的包名路径不能更改
- 编写一个manager类,进行sdk封装操作
package com.kim.openapi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class KimOpenApiManager {
private static final String TAG = "KimOpenApiManager";
private Context mContext;
private IKimOpenApiManagerService mService;
private IBinder b;
private static KimOpenApiManager mInstance;
private boolean connected;
private KimOpenApiManager(Context context) {
mContext = context.getApplicationContext();
bindKimOpenApiManagerService(conn);
}
public void unRegister() {
if (connected) {
mContext.unbindService(conn);
}
}
public int addApn(KimApn apn) {
if (!connected) {
Log.e(TAG, "getService: connected= false");
}
int ret = 0;
try {
ret = getService().addApn(apn);
} catch (RemoteException e) {
e.printStackTrace();
}
return ret;
}
private IKimOpenApiManagerService getService() {
if (mService != null) {
return mService;
}
mService = IKimOpenApiManagerService.Stub.asInterface(b);
return mService;
}
public static synchronized KimOpenApiManager register(Context context) {
if (mInstance == null) {
mInstance = new KimOpenApiManager(context);
}
return mInstance;
}
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
b = service;
connected = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
connected = false;
}
};
private void bindKimOpenApiManagerService(ServiceConnection serviceConnection) {
Intent intent = new Intent();
intent.setPackage("com.kim.openapi");
intent.setAction("kim.openapi.action.start");
mContext.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
}
- 编译module,生成aar和jar包(aar在outputs中,jar包生成的名字为classes.jar 各个版本生成位置不同,搜索即可)
- 三方app中对aar以及jar的引用
将文件添加到工程的libs文件夹下
5.1 如果是aar,在module中的build.gradle中android{}下添加
repositories {
flatDir {
dirs 'libs'
}
}
在dependencies{}下添加
implementation(name: 'aar 名称不带后缀', ext: 'aar')
5.2 如果是jar,右键->add as Library即可