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,將project\Libraries\DroidPlugin導入到工程中

  

  

  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

 

 

 

 

 

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM