urn false;
}
mPluginApp = loadPluginApk(apkPath);
return mPluginApp != null;
}
public PluginApp getLoadedPluginApk() {
return mPluginApp;
}
}
在MainActivity中初始化,注意Hook的时机:
public class MainActivity extends Activity implements View.OnClickListener {
// https://zhuanlan.zhihu.com/p/33017826
public static final boolean DEBUG = true;
public static final String TAG = "MainActivity";
private String mPluginPackageName = "top.vimerzhao.image";
private String mPluginClassName = "top.vimerzhao.image.MainActivity";
//读写权限
private static String[] PERMISSIONS_STORAGE = {Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE};
//请求状态码
private static int REQUEST_PERMISSION_CODE = 1;
private PluginManager mPluginManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();
initPlugin();
}
private void initPlugin() {
// !! must first
ReflectUtil.init();
mPluginManager = PluginManager.getInstance(getApplicationContext());
mPluginManager.hookInstrumentation();
mPluginManager.hookCurrentActivityInstrumentation(this);
}
private void initData() {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_PERMISSION_CODE);
}
}
}
private void initView() {
(findViewById(R.id.tv_launch)).setOnClickListener(this);
}
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(newBase);
// !!! 不要在此Hook,看源码发现mInstrumentaion会在此方法后初始化
}
@Override
public void onClick(View view) {
if (Constants.DEBUG) Log.e(TAG, "click view id: " + view.getId());
if (view.getId() == R.id.tv_launch) {
// TODO launch plugin app
if (mPluginManager.loadPlugin(Constants.PLUGIN_PATH)) {
Intent intent = new Intent();
intent.setClassName(mPluginPackageName, mPluginClassName);
startActivity(intent);
}
}
}
}
现在插件Activity不会有任何限制:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onResume() {
super.onResume();
}
}
效果和上图类似。
Demo地址
部分源码无关核心逻辑,没有给到,目录结构也没有说明,详见Demo源码。
PluginDemo
总结
看着理论感觉似懂非懂,实战发现问题其实挺多的,尤其是Hook的时机,照搬网上的文章发现根本不可行。插件化也不是一蹴而就的,而是在已有成果的基础上一次一次的小创新积累起来的,跟着插件化发展的路径自己动手实践一遍还是能发现很多自己理解不够深刻的地方的。
以上。
参考
相关阅读
获得InputStream,读取配置文件的方式
聊聊springboot session timeout参数设置
Android开发之漫漫长途 XII——Fragment详解
【每日课程推荐】机器学习实战!快速入门在线广告业务及CTR相应知识
此文已由作者授权腾讯云+社区发布,更多原文请点击
搜索关注公众号「云加社区」,第一时间获取技术干货,关注后回复1024 送你一份技术课程大礼包!
海量技术实践经验,尽在云加社区!