在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来实现接口的隐藏。

相关推荐
顾林海21 分钟前
Android编译插桩黑科技:ReDex带你给App"瘦个身,提个速"
android·面试·性能优化
maki0771 小时前
VR大空间资料 04 —— VRAF使用体验和源码分析
android·vr·虚幻·源码分析
消失的旧时光-19433 小时前
Kotlin 判空写法对比与最佳实践
android·java·kotlin
锅拌饭4 小时前
Android Handler(一) 同步屏障泄露导致页面假死
android
锅拌饭4 小时前
Android Handler(二) 同步屏障泄露检测
android
手机不死我是天子5 小时前
《Android 核心组件深度系列 · 第 3 篇 BroadcastReceiver》
android·android studio
用户17345666963475 小时前
Android 日志库:高性能压缩加密日志系统
android
恋猫de小郭6 小时前
React 和 React Native 不再直接归属 Meta,React 基金会成立
android·前端·ios
bst@微胖子6 小时前
鸿蒙实现滴滴出行项目之侧边抽屉栏以及权限以及搜索定位功能
android·华为·harmonyos