写在前面
前面实现了插件APP的Activity和Service的启动,今天咱来说一下动态广播的使用。还是老套路:使用宿主环境注册和发送,基于宿主Activity注入到插件Activity的Context。
一、项目目录
新增文件
- 宿主APP新增广播接收代理类
- 插件APP新增广播接收类
- 接口标准新增广播标准
二、撸码
1. 接口标准制定
public interface IBroadcastReceiver {
// 提供一个接收广播通知的方法
void onReceive(Context context, Intent intent);
}
2. 插件APP
- 实现接口标准
public class BroadcastReceivers extends BroadcastReceiver implements IBroadcastReceiver {
@Override// 为了不省事儿把接口里方法定义成父类一样的了
public void onReceive(Context context, Intent intent) {
// 收到广播后的相应提示
Toast.makeText(context, "BroadcastReceivers: 收到动态广播", Toast.LENGTH_SHORT).show();
System.out.println("BroadcastReceivers: 收到动态广播");
}
}
- 在插件APP内提供注册和发送方法
public class PluginActivity extends BaseActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_plugin);// 父类重写了此方法
// 不能在插件Activity的xml里使用onClick直接设置点击事件,需要用id的方式
findViewById(R.id.btn_plugin_register_broadcast).setOnClickListener( v -> registerBroadcast());
findViewById(R.id.btn_plugin_send_broadcast).setOnClickListener( v -> sendBroadcast());
}
/**
* 插件内注册Broadcast
*/
private void registerBroadcast() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Constant.BROADCAST_INTENT_FILTER);
// 父类重写此方法,调用到宿主环境
registerReceiver(new BroadcastReceivers(), intentFilter);
}
/**
* 插件内发送Broadcast
*/
private void sendBroadcast() {
Intent intent = new Intent();
intent.setAction(Constant.BROADCAST_INTENT_FILTER);
// 父类重写此方法,调用到宿主环境
sendBroadcast(intent);
}
}
- BaseActivity重写注册和发送方法,使用宿主环境
public class BaseActivity extends implements IActivity{
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
// 调用到宿主环境去
return appActivity.registerReceiver(receiver, filter);
}
@Override
public void sendBroadcast(Intent intent) {
// 调用到宿主的发送方法
appActivity.sendBroadcast(intent);
}
}
3. 宿主APP
- 创建广播接收代理类
public class ProxyBroadcastReceiver extends BroadcastReceiver {
private String broadcastReceiverName;
public ProxyBroadcastReceiver(String broadcastReceiverName) {
this.broadcastReceiverName = broadcastReceiverName;
}
@Override
public void onReceive(Context context, Intent intent) {
try {
// 反射创建插件内BroadcastReceiver类实例
Class clazz = PluginManager.getInstance(context).getClassLoader().loadClass(broadcastReceiverName);
Object instance = clazz.newInstance();
IBroadcastReceiver iReceiver = (IBroadcastReceiver) instance;
// 调用方法
iReceiver.onReceive(context,intent);
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 代理Activity拦截插件APP的注册和发送意图
public class ProxyActivity extends Activity {
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
// 拦截插件APP传来的receiver
String broadcastReceiverName = receiver.getClass().getName();
// 最终广播在宿主环境的代理类里注册
return super.registerReceiver(new ProxyBroadcastReceiver(broadcastReceiverName), filter);
}
@Override
public void sendBroadcast(Intent intent) {
super.sendBroadcast(intent);
}
}
三、结束
至此,插件APP内使用动态广播就完成了。有任何问题欢迎评论区交流。