Android aidl封装成sdk

作者: Kpower | 来源:发表于2020-10-16 15:45 被阅读0次

问题背景

  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

相关文章

网友评论

    本文标题:Android aidl封装成sdk

    本文链接:https://www.haomeiwen.com/subject/pzqzpktx.html