在Android中利用抽象类对外提供系统接口

需求背景

Android系统定制中,无可避免需要对外提供一些定制化的接口,使app能完成一些定制化需求。之前用过aidl文件和jar用于app和系统同步接口,但效果都不尽人意。aidl文件对接口有顺序要求,不好增删改查,且接口调用的逻辑诡异;jar需要单独编译,且不能够直接看到接口信息,需要反编译。经过一番探索,发现可以让app使用抽象类来调用系统中的接口,该抽象类类似C语言中的.h文件,只描述接口,实际实现类在系统framework中。

示意图如下:

原理介绍

CustomManager.java作为中间桥梁,内容如下:

java 复制代码
public abstract class CustomManager {  
    public static CustomManager getInstance(Context context) {  
        return (CustomManager) context.getSystemService("CustomManager");  
    }  
  
    public abstract String getVersion();  
}

app将CustomManager.java导入到项目中,并import即可使用CustomManager中的接口。

为了app导入CustomManager.java后能顺利编译通过,CustomManager.java中不能使用超出标准api以外的类,但可交由抽象方法中的实现(CustomManagerImpl)或后端CustomManagerService去做。

app导入CustomManager.java后, 先调用CustomManager.getInstance(Context context)获取实例,然后再使用接口,如:

java 复制代码
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private CustomManager mCustomManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //实例化
        mCustomManager = CustomManager.getInstance(this)

        //调用具体接口
        mCustomManager.getVersion()
    }
}

CustomManagerImpl.java继承了CustomManager.java并实现了在CustomManager.java中定义的接口:

java 复制代码
public class CustomManagerImpl extends CustomManager {
    private final ICustomManager mService;

    public CustomManagerImpl(Context context, ICustomManager service) {
        mService = service;
        mContext = context;
    }

    public String getVersion() {
        try {
            return mService.getVersion();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "unknow";
    }
}

CustomManagerImpl.java由系统端维护,编译进framework.jar, app在调用CustomManager.getInstance(Context context)后会返回一个CustomManagerImpl实例并转换为CustomManager。 为什么会返回一个CustomManagerImpl实例?因为在系统中注册了服务"CustomManager": SystemServiceRegistry:

java 复制代码
registerService("CustomManager", com.so.CustomManagerImpl.class,
        new CachedServiceFetcher<com.so.CustomManagerImpl>() {
            @Override
            public com.so.CustomManagerImpl createService(ContextImpl ctx)
                    throws ServiceNotFoundException {
                IBinder b = ServiceManager.getService("CustomManagerService");
                ICustomManager service = ICustomManager.Stub.asInterface(b);
                return new com.so.CustomManagerImpl(ctx, service);
            }});

因此在app中只要通过一个字符串"CustomManager"即可得到一个在framework中实现的CustomManagerImpl的实例:

java 复制代码
public abstract class CustomManager {
    public static CustomManager getInstance(Context context) {
        return (CustomManager) context.getSystemService("CustomManager");
    }
}

app获得CustomManager实例后,调用其接口,其实都是在调用CustomManagerImpl的接口。 如mCustomManager.getVersion(),其实走的是CustomManagerImpl.getVersion()。

与后端服务CustomManagerService的交互

CustomManagerImpl虽然在framework中实现,但运行时还在app域,受权限等的限制,能调用的系统功能有限,因此我们进一步在系统中新增一个系统级服务CustomManagerService来实现更复杂的功能。CustomManagerImpl通AIDL来与CustomManagerService交互, 新增aidl文件ICustomManager.aidl:

java 复制代码
interface ICustomManager {
    String getVersion();
}

CustomManagerService继承ICustomManager.Stub, 并实现接口:

java 复制代码
public class CustomManagerService extends ICustomManager.Stub {
    public String getVersion() {
       return "V1.0.0";
    }
}

SystemServiceRegistry在注册服务"CustomManager"时, 也将CustomManagerService的Binder引用传给了CustomManagerImpl.mService,所以在CustomManagerImpl.getVersion()中调用了mService.getVersion()即是调用CustomManagerService.getVersion()。

总结

将抽象类做"头文件"来对外提供接口,有维护简单,逻辑明了,可读性强的优点,甚至可以针对不同需求提供不完全的CustomManager.java来实现接口的隐藏。

相关推荐
深盾安全2 小时前
Android SO导出符号的深度解析与安全防护指南
android
顾林海2 小时前
Android安全防护:Runtime 调试检测与反制手段
android·安全·面试
什么半岛铁盒2 小时前
MySQL 约束知识体系:八大约束类型详细讲解
android·数据库·mysql
丐中丐9993 小时前
Android系统中如何在Native层调用java实现的系统服务
android·操作系统
stringwu3 小时前
Flutter plugin开发小知识之:ActivityAware 详解
android
whysqwhw3 小时前
Matrix.setPolyToPoly() 函数使用指南
android
张可3 小时前
在 Voyager 中使用 SharedElement 共享元素动画
android·前端·kotlin
且随疾风前行.4 小时前
在安卓中使用 FFmpegKit 剪切视频并添加文字水印
android·音视频
Yang-Never4 小时前
设计模式 -> 策略模式(Strategy Pattern)
android·开发语言·设计模式·kotlin·android studio·策略模式