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、这种插件化,在写插件开发的时候,有什么要注意的事项?

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

目录
相关文章
|
2月前
|
物联网 区块链 vr&ar
未来已来:探索区块链、物联网与虚拟现实技术的融合与应用安卓与iOS开发中的跨平台框架选择
【8月更文挑战第30天】在科技的巨轮下,新技术不断涌现,引领着社会进步。本文将聚焦于当前最前沿的技术——区块链、物联网和虚拟现实,探讨它们各自的发展趋势及其在未来可能的应用场景。我们将从这些技术的基本定义出发,逐步深入到它们的相互作用和集成应用,最后展望它们如何共同塑造一个全新的数字生态系统。
|
7天前
|
消息中间件 Android开发 索引
Android面试高频知识点(4) 详解Activity的启动流程
讲解Activity的启动流程了,Activity的启动流程相对复杂一下,涉及到了Activity中的生命周期方法,涉及到了Android体系的CS模式,涉及到了Android中进程通讯Binder机制等等, 首先介绍一下Activity,这里引用一下Android guide中对Activity的介绍:
24 4
|
14天前
|
前端开发 Java 数据库
💡Android开发者必看!掌握这5大框架,轻松打造爆款应用不是梦!🏆
在Android开发领域,框架犹如指路明灯,助力开发者加速应用开发并提升品质。本文将介绍五大必备框架:Retrofit简化网络请求,Room优化数据库访问,MVVM架构提高代码可维护性,Dagger 2管理依赖注入,Jetpack Compose革新UI开发。掌握这些框架,助你在竞争激烈的市场中脱颖而出,打造爆款应用。
80 3
|
22天前
|
编译器 Android开发 开发者
带你了解Android Jetpack库中的依赖注入框架:Hilt
本文介绍了Hilt,这是Google为Android开发的依赖注入框架,基于Dagger构建,旨在简化依赖注入过程。Hilt通过自动化的组件和注解减少了DI的样板代码,提高了应用的可测试性和可维护性。文章详细讲解了Hilt的主要概念、基本用法及原理,帮助开发者更好地理解和应用Hilt。
40 8
|
20天前
|
Java Android开发 数据安全/隐私保护
Android中多进程通信有几种方式?需要注意哪些问题?
本文介绍了Android中的多进程通信(IPC),探讨了IPC的重要性及其实现方式,如Intent、Binder、AIDL等,并通过一个使用Binder机制的示例详细说明了其实现过程。
117 4
|
7天前
|
Android开发 开发者
Android面试之Activity启动流程简述
每个Android开发者都熟悉的Activity,但你是否了解它的启动流程呢?本文将带你深入了解。启动流程涉及四个关键角色:Launcher进程、SystemServer的AMS、应用程序的ActivityThread及Zygote进程。核心在于AMS与ActivityThread间的通信。文章详细解析了从Launcher启动Activity的过程,包括通过AIDL获取AMS、Zygote进程启动以及ActivityThread与AMS的通信机制。接着介绍了如何创建Application及Activity的具体步骤。整体流程清晰明了,帮助你更深入理解Activity的工作原理。
16 0
|
2月前
|
设计模式 Java Android开发
探索安卓应用开发:从新手到专家的旅程探索iOS开发中的SwiftUI框架
【8月更文挑战第29天】本文旨在通过一个易于理解的旅程比喻,带领读者深入探讨安卓应用开发的各个方面。我们将从基础概念入手,逐步过渡到高级技术,最后讨论如何维护和推广你的应用。无论你是编程新手还是有经验的开发者,这篇文章都将为你提供有价值的见解和实用的代码示例。让我们一起开始这段激动人心的旅程吧!
|
2月前
|
Android开发
基于Amlogic 安卓9.0, 驱动简说(三):使用misc框架,让驱动更简单
如何使用Amlogic T972安卓9.0系统上的misc框架来简化驱动程序开发,通过misc框架自动分配设备号并创建设备文件,从而减少代码量并避免设备号冲突。
24 0
基于Amlogic 安卓9.0, 驱动简说(三):使用misc框架,让驱动更简单
|
Android开发
【Android 进程保活】应用进程拉活 ( 系统 Service 机制拉活 | Service 组件 onStartCommand 方法分析 | 源码资源 )(三)
【Android 进程保活】应用进程拉活 ( 系统 Service 机制拉活 | Service 组件 onStartCommand 方法分析 | 源码资源 )(三)
322 0
【Android 进程保活】应用进程拉活 ( 系统 Service 机制拉活 | Service 组件 onStartCommand 方法分析 | 源码资源 )(三)
|
Android开发
【Android 进程保活】应用进程拉活 ( 系统 Service 机制拉活 | Service 组件 onStartCommand 方法分析 | 源码资源 )(二)
【Android 进程保活】应用进程拉活 ( 系统 Service 机制拉活 | Service 组件 onStartCommand 方法分析 | 源码资源 )(二)
243 0
下一篇
无影云桌面