Android aidl封装成sdk

问题背景

  1. 客户需要rom提供一些系统app才能操作的接口;
  2. 为客户开发了一些在rom中实现的功能,客户需要自己调用功能接口;

设计思路

  1. 通过增加一个系统的模块(视具体需求拥有系统签名或者system uid),提供aidl文件给第三方app进行跨进程调用。
  2. 在提供aidl文件的基础上,通过封装sdk,提供aar或者jar包给第三方app。

操作步骤

server端编码

android studio 创建OpenApiDemo工程
(这个工程是要放在rom中编译的,作为三方app aidl调用的对象)
以传输apn信息为例(如果不需要通过跨进程传输对象,直接参考步骤3)

  1. 首先需要创建一个KimApn.aidl
    ps:注意包名位置


    image.png
// KimApn.aidl
package com.kim.openapi;
// Declare any non-default types here with import statements
parcelable KimApn;
  1. 定义一个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();
    }

}

  1. 定义需要提供的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);
}
  1. 创建一个 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;
        }
    };

}
  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封装。

  1. 使用android studio 新建一个module ,类型为Android Library,包名任意
  2. 将server端工程的aidl文件夹直接复制到新的module下对应位置,注意此处的包名路径不能更改
image.png
  1. 编写一个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);
    }

}

  1. 编译module,生成aar和jar包(aar在outputs中,jar包生成的名字为classes.jar 各个版本生成位置不同,搜索即可)
  2. 三方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即可

[代码参考] https://gitee.com/kpower/OpenApiDemo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,254评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,875评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,682评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,896评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,015评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,152评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,208评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,962评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,388评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,700评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,867评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,551评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,186评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,901评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,689评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,757评论 2 351