DroidPlugin知识整合

一、DroidPlugin的优点

  •   宿主和插件完全隔离,插件不依赖宿主,可以独立安装运行
  •   低入侵设计,插件不需要集成任何类,和正常的app是一样的
  •   宿主程序集成DroidPlugin框架简单
  •   支持四大组件,完全使用Android的API

二、DroidPlugin的缺点

  •   插件启动速度慢
  •   宿主只能调用插件为Launcher的Activity,宿主不能和插件中其他的Activity交互,也就是说插件是一个单独的模块,只能单一入口

三、集成DroidPlugin

  1. 下载DroidPlugin

            下载地址:https://github.com/DroidPluginTeam/DroidPlugin

     

  2. 创建一个新功能,新建一个plugin模块。(假设app为宿主工程,plugin为插件工程)

  

  

  3. 导入DroidPlugin库

  找到下载的DroidPlugin,将projectLibrariesDroidPlugin导入到工程中

  

  

  4. 修改DroidPlugin中的build.gradle 文件

  

            (原build.gradle文件)

  

             (修改后build.gradle文件)

  5. 修改DroidPlugin的AndroidManifest.xml文件,将所有的provide对应的authorities修改为自己的包名

  因为AndroidManifest.xml文件中,provide对应的authorities使用的是变量,所以修改build.gradle文件即可,请参考tip2

  

  6. 在宿主工程中添加DroidPlugin库。

四、集成中报错总结

错误一:

  

  解决方案:

  修改DroidPlugin中build.gradle文件的comileSdkVersion属性值,因为我app使用的28,所以也改为28

  =================================

错误二:

解决方案:

修改DroidPlugin中build.gradle文件的buildToolsVersion 属性值,与app保持一致即可

=================================

错误三:

解决方案:

修改DroidPlugin中build.gradle文件,将“instrumentTest”属性改为“androidTest”

=================================

错误四:

解决方案:

将DroidPlugin中的AndroidManifext.xml中的minSDKVersion 去掉即可

=================================

错误五:

定位到DroidPlugin中build.gradle文件,删除一下语句:

=================================

错误六:

  

将compile关键字替换为implementation

  =================================

  错误七:

解决方案:

因为DroidPlugin使用的是lib文件夹,不是libs,所以将libs替换为lib,请参考tip1.

=================================

五、使用DroidPlugin插件 

  1. 自定义Application,在onCreate 和attachBaseContext方法中添加如下代码:
 1 public class PluginApplication extends Application {
 2     @Override
 3     public void onCreate() {
 4         super.onCreate();
 5         //must be after super.onCreate()
 6         PluginHelper.getInstance().applicationOnCreate(getBaseContext());
 7     }
 8 
 9     @Override
10     protected void attachBaseContext(Context base) {
11         PluginHelper.getInstance().applicationAttachBaseContext(base);
12         super.attachBaseContext(base);
13     }
14 }

  2. 开发宿主工程(app)

 1 /**
 2  * 安装插件的方法
 3  * */
 4 private void installPlugin() {
 5     // 获取插件
 6     String path = Environment.getExternalStorageDirectory().toString() + "/plugins";
 7     File file = new File(path);
 8     if(!file.exists()){
 9         file.mkdirs();
10     }
11     plugins = file.listFiles();
12     if(plugins == null || plugins.length == 0 ){ // 没有插件
13         Toast.makeText(this,"没有插件",Toast.LENGTH_SHORT).show();
14         return;
15     }
16     // 安装第一个插件
17     try {
18         PluginManager.getInstance().installPackage(plugins[0].getAbsolutePath(),
19                 PackageManagerCompat.INSTALL_REPLACE_EXISTING);
20     } catch (RemoteException e) {
21         e.printStackTrace();
22     }
23 }
 1 // 调用插件
 2 findViewById(R.id.btn_test).setOnClickListener(new View.OnClickListener() {
 3     @Override
 4     public void onClick(View v) {
 5         PackageManager pm = getPackageManager();
 6         Intent intent = pm.getLaunchIntentForPackage("ayinger.plugin");
 7         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
8 startActivityForResult(intent,1); 9 10 } 11 });

  注意:

  •   上述方法为插件工程不安装,将插件工程直接放在了/storage/emulated/0/plugins目录下,调用installPlugin()来安装插件工程。
  •   另外,还有一种是插件工程已经安装成功,直接,可省略installPlugin()步骤,直接调用插件,即可,这里注意一点,getLaunchIntentForPackage()方法  中,传入的参数是插件的applicationId 属性的值。
  •   创建文件夹的时候,要注意检查是否授权,不然文件夹创建不成功。(入过坑)。

六、 其他

  1. 安装/更新

  PluginManager.getInstance().installPackage(String packageName, int flags)

    安装插件到插件系统中,packageName为插件apk路径,flags可以设置为0,如果要更新插件,则设置为PackageManagerCompat.INSTALL_REPLACE_EXISTING

  2. 删除

  PluginManager.getInstance().deletePackage(String packageName,int flags);

    从插件系统中卸载某个插件,packageName: 需卸载插件包名, flags: 设置为0

  3. 宿主和插件通信

 1 // 宿主和插件如何互通SharedPreferences
 2 try {
 3     Context otherAppsContext = createPackageContext("HostPackageName",
 4             Context.CONTEXT_IGNORE_SECURITY);
 5     SharedPreferences sharedPreferences = otherAppsContext.
 6             getSharedPreferences("test", Context.MODE_WORLD_READABLE);
 7     if (sharedPreferences != null) {
 8         String str1 = sharedPreferences.getString("key",null);
 9         Toast.makeText(getApplicationContext(), "result: " + str,
10                 Toast.LENGTH_SHORT).show();
11     }
12 } catch (PackageManager.NameNotFoundException e) {
13     e.printStackTrace();
14 }

七、 参考博客

  https://blog.csdn.net/chaozhung_no_l/article/details/71439919

  https://blog.csdn.net/wushipan/article/details/51577850

 

 

原文地址:https://www.cnblogs.com/Ayinger/p/11023589.html