Android手写占位式插件化框架之Activity通信、Service通信和BroadcastReceiver通信(二)

简介: Android手写占位式插件化框架之Activity通信、Service通信和BroadcastReceiver通信

三、插件包plugin_package中,首先实现BaseActivity类

/**
 * @Author: ly
 * @Date: 2023/7/14
 * @Description: 插件包中Activity基础类, 拿到宿主的上下文环境
 */
public class BaseActivity extends Activity implements ActivityInterface {
    private static final String TAG = "BaseActivity";
    /**
     * 宿主的环境
     */
    public Activity appActivity;
    @Override
    public void insertAppContext(Activity appActivity) {
        this.appActivity = appActivity;
    }
    @SuppressLint("MissingSuperCall")
    @Override
    public void onCreate(Bundle savedInstanceState) {
        String appName = savedInstanceState.getString("appName");
        Log.i(TAG, "appName: " + appName);
    }
    @SuppressLint("MissingSuperCall")
    @Override
    public void onStart() {
    }
    @SuppressLint("MissingSuperCall")
    @Override
    public void onResume() {
    }
    @SuppressLint("MissingSuperCall")
    @Override
    public void onPause() {
    }
    @SuppressLint("MissingSuperCall")
    @Override
    public void onStop() {
    }
    @SuppressLint("MissingSuperCall")
    @Override
    public void onDestroy() {
    }
    public void setContentView(int resId) {
        appActivity.setContentView(resId);
    }
    public View findViewById(int id) {
        return appActivity.findViewById(id);
    }
    /**
     * 启动插件包内的第二个Activity:TestActivity
     *
     * @param intent 意图数据
     */
    public void startActivity(Intent intent) {
        Intent newIntent = new Intent();
        newIntent.putExtra("className", intent.getComponent().getClassName());
        appActivity.startActivity(newIntent);
    }
    public ComponentName startService(Intent serviceIntent) {
        Intent newIntent = new Intent();
        //serviceIntent.getComponent().getClassName() 这里拿到的是TestService的全类名
        newIntent.putExtra("className", serviceIntent.getComponent().getClassName());
        return appActivity.startService(newIntent);
    }
    /**
     * 注册广播
     *
     * @param receiver
     * @param intentFilter
     * @return
     */
    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter intentFilter) {
        return appActivity.registerReceiver(receiver, intentFilter);
    }
    /**
     * 发送广播
     *
     * @param intent
     */
    public void sendBroadcast(Intent intent) {
        appActivity.sendBroadcast(intent);
    }
}

3.2 插件包中首页PluginActivity,代码如下

/**
 * 首先加载该页面PluginActivity
 */
public class PluginActivity extends BaseActivity {
    private static final String TAG = "PluginActivity";
    private static final String ACTION = "com.example.plugin_package.ACTION";
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        String appName = savedInstanceState.getString("appName");
        Log.i(TAG, "appName: " + appName);
        setContentView(R.layout.activity_plugin);
        Toast.makeText(appActivity, "我是插件", Toast.LENGTH_SHORT).show();
        //点击按钮跳转到TestActivity
        findViewById(R.id.btn_start_activity).setOnClickListener(v -> {
            startActivity(new Intent(appActivity, TestActivity.class));
        });
        //点击按钮跳转到TestService
        findViewById(R.id.btn_start_service).setOnClickListener(v -> {
            startService(new Intent(appActivity, TestService.class));
        });
        //插件内部注册插件的广播接收者
        findViewById(R.id.btn_register_receiver).setOnClickListener(v -> {
            IntentFilter filter = new IntentFilter();
            filter.addAction(ACTION);
            registerReceiver(new MyReceiver(), filter);
        });
        //插件内部发送插件的广播接收者
        findViewById(R.id.btn_send_receiver).setOnClickListener(v -> {
            Intent intent = new Intent();
            intent.setAction(ACTION);
            sendBroadcast(intent);
        });
    }
}

3.3 点击PluginActivity中的按钮,可以跳转到TestActivity,代码如下:

public class TestActivity extends BaseActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
    }
}

3.4、BaseService类

/**
 * @Author: ly
 * @Date: 2023/7/15
 * @Description: 基础Service继承标准库中ServiceInterface接口
 */
public class BaseService extends Service implements ServiceInterface {
    private Service appService;
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    @Override
    public void insertAppContext(Service appService) {
        this.appService = appService;
    }
    @Override
    public void onCreate() {
    }
    @SuppressLint("WrongConstant")
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return 0;
    }
    @Override
    public void onDestroy() {
    }
}

3.5、TestService类

/**
 * @Author: ly
 * @Date: 2023/7/15
 * @Description: 插件中的Service
 */
public class TestService extends BaseService {
    private static final String TAG = "TestService";
    @Override
    public void onCreate() {
        super.onCreate();
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //开启子线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        Log.i(TAG, "插件里面的服务正在执行中!");
                    }
                }
            }
        }).start();
        return super.onStartCommand(intent, flags, startId);
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

3.6、插件中的广播接收者MyReceiver

/**
 * @Author: ly
 * @Date: 2023/7/15
 * @Description: 插件中的广播接收者
 */
public class MyReceiver extends BroadcastReceiver implements ReceiverInterface {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "我是插件里面的广播接收者,我收到了广播!", Toast.LENGTH_SHORT).show();
    }
}

一、这个是宿主APP启动插件Activity流程:

二、这个是插件中启动Activity的流程如下图:

三、下面是插件中启动Service的流程图如下:

四、插件中启动BroadcastReceiver,这是在插件中动态注册广播接收者,并在插件内部发送广播。

五、宿主app中获取插件包中静态注册的广播接收者StaticeReceiver,并在宿主app中发送静态广播请看这篇文章

Android手写占位式插件化框架之apk解析原理系统源码分析

六、编写代码后,将plugin_package包手动放到宿主app的私有目录下,便可以正常运行,在公司项目中会将插件包放到服务器用户使用某个功能模块的时候,会下载到本地。

七、具体问题思考

1、为什么在插件中不能使用this?

因为插件是没有在手机上安装的,是无法拥有组件环境的。

2、为什么要有代理的Activity?

由于插件中的Activity并不是一个能够运行的组件,所以需要代理的Activity去代替插件中的Activity(例如Activity进出栈)

3、这种插件化,在写插件开发的时候,有什么要注意的事项?

所有关于操作组件环境的地方,都必须使用宿主的环境。

目录
相关文章
|
12天前
|
算法 JavaScript Android开发
|
23天前
|
Android开发
Android面试之Activity启动流程简述
Android面试之Activity启动流程简述
70 6
|
21天前
|
Java 程序员 API
Android|集成 slf4j + logback 作为日志框架
做个简单改造,统一 Android APP 和 Java 后端项目打印日志的体验。
83 1
|
25天前
|
消息中间件 Android开发 索引
Android面试高频知识点(4) 详解Activity的启动流程
Android面试高频知识点(4) 详解Activity的启动流程
24 3
|
25天前
|
缓存 前端开发 Android开发
Android实战之如何截取Activity或者Fragment的内容?
本文首发于公众号“AntDream”,介绍了如何在Android中截取Activity或Fragment的屏幕内容并保存为图片。包括截取整个Activity、特定控件或区域的方法,以及处理包含RecyclerView的复杂情况。
18 3
|
25天前
|
Android开发
Android面试之Activity启动流程简述
Android面试之Activity启动流程简述
17 0
|
2月前
|
消息中间件 Android开发 索引
Android面试高频知识点(4) 详解Activity的启动流程
讲解Activity的启动流程了,Activity的启动流程相对复杂一下,涉及到了Activity中的生命周期方法,涉及到了Android体系的CS模式,涉及到了Android中进程通讯Binder机制等等, 首先介绍一下Activity,这里引用一下Android guide中对Activity的介绍:
49 4
|
2月前
|
前端开发 Java 数据库
💡Android开发者必看!掌握这5大框架,轻松打造爆款应用不是梦!🏆
在Android开发领域,框架犹如指路明灯,助力开发者加速应用开发并提升品质。本文将介绍五大必备框架:Retrofit简化网络请求,Room优化数据库访问,MVVM架构提高代码可维护性,Dagger 2管理依赖注入,Jetpack Compose革新UI开发。掌握这些框架,助你在竞争激烈的市场中脱颖而出,打造爆款应用。
343 3
|
2月前
|
编译器 Android开发 开发者
带你了解Android Jetpack库中的依赖注入框架:Hilt
本文介绍了Hilt,这是Google为Android开发的依赖注入框架,基于Dagger构建,旨在简化依赖注入过程。Hilt通过自动化的组件和注解减少了DI的样板代码,提高了应用的可测试性和可维护性。文章详细讲解了Hilt的主要概念、基本用法及原理,帮助开发者更好地理解和应用Hilt。
77 8
|
2月前
|
Java Android开发 数据安全/隐私保护
Android中多进程通信有几种方式?需要注意哪些问题?
本文介绍了Android中的多进程通信(IPC),探讨了IPC的重要性及其实现方式,如Intent、Binder、AIDL等,并通过一个使用Binder机制的示例详细说明了其实现过程。
307 4