日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android实战】DroidPlugin插件化应用分析

發(fā)布時間:2025/3/15 Android 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android实战】DroidPlugin插件化应用分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

簡介

DroidPlugin 是360手機助手在Android系統(tǒng)上實現(xiàn)的一種新的插件機制:它可以在無需安裝、修改的情況下運行APK文件,此機制對改進大型APP的架構(gòu),實現(xiàn)多團隊協(xié)作開發(fā)具有一定的好處?
詳情請查看DroidPlugin的github地址

背景

  • 將項目中某個相對獨立的功能模塊分解出來
  • 例如:語音搜索功能模塊獨立出來,這樣減少了項目中依賴包的數(shù)量,減少了項目中某些包的層層依賴關(guān)系,將語音搜索模塊獨立成一個單獨的apk
  • 可以獨立開發(fā)語音搜索模塊
  • 假設(shè)主項目為Host,依賴library為DroidPlugin,獨立出來的語音模塊生成為voice.apk

應(yīng)用

這里將獨立出來的語音搜索模塊打包成單獨的apk,放在項目的assets目錄下

項目中的設(shè)置步驟:

  • 導(dǎo)入DroidPlugin相關(guān)的library
  • 在自己的Application當(dāng)中添加如下代碼
@Override public void onCreate() {super.onCreate();//這里必須在super.onCreate方法之后,順序不能變PluginHelper.getInstance().applicationOnCreate(getBaseContext()); }@Override protected void attachBaseContext(Context base) {PluginHelper.getInstance().applicationAttachBaseContext(base);super.attachBaseContext(base); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 配置主應(yīng)用AndroidManifest.xml中相關(guān)的組件和權(quán)限?
    這里需要注意DroidPlugin library中需要的權(quán)限以及組件要在主項目Host中聲明?
    還有就是Host中的權(quán)限只能比voice的多,不能少,否則會有問題
  • 讀取assets里面的voice.apk并復(fù)制到sd上或者其他的可讀取存儲位置,然后再使用DroidPlugin進行安裝,這里將需要用到的一些方法封裝在PluginUtils工具類中。
  • 當(dāng)voice.apk通過插件式的形式安裝完成以后,我們就可以通過如下方式啟動voice.apk
PluginUtils.startActivity(SearchResultActivity.this,"com.storm.smart.voice");
  • 1
  • 1
  • 在Application或者MainActivty中加載voice.apk
/*** 通過DroidPlugin插件安裝voice.apk* 從sd卡根目錄讀取*/private void droidPluginInstall() {BfExecutor.getInstance().execute(new Runnable() {@Overridepublic void run() {if (PluginUtils.copyApkFromAssets(getApplicationContext(), "voice.apk",Environment.getExternalStorageDirectory().getAbsolutePath() + "/voice.apk")) {PluginUtils.installApk(getApplicationContext(),Environment.getExternalStorageDirectory().getAbsolutePath() + "/voice.apk","com.storm.smart.voice");}}});}/*** 通過DroidPlugin插件安裝voice.apk* 從data下讀取,需要權(quán)限(有可能手機沒有sd卡)*/private void droidPluginInstall() {BfExecutor.getInstance().execute(new Runnable() {@Overridepublic void run() {String path = "/data/data/" + getApplicationContext().getPackageName() + "/files" + "/voice.apk";try {String command = "chmod " + "666" + " " + path;Runtime runtime = Runtime.getRuntime();runtime.exec(command);} catch (IOException e) {e.printStackTrace();}if (PluginUtils.copyApkFromAssets(getApplicationContext(), "voice.apk", path)) {PluginUtils.installApk(getApplicationContext(), path, "com.storm.smart.voice");}}});}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • PluginUtils全部代碼如下:
public class PluginUtils {public static void startActivity(Activity activity, String packageName){PackageManager pm = activity.getPackageManager();Intent intent = pm.getLaunchIntentForPackage(packageName);intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);activity.startActivity(intent);}/*** 刪除apk* @param activity* @param packageName*/public static void doUninstall( Activity activity, String packageName) {if (!PluginManager.getInstance().isConnected()) {Toast.makeText(activity, "服務(wù)未連接", Toast.LENGTH_SHORT).show();} else {try {PluginManager.getInstance().deletePackage(packageName, 0);Toast.makeText(activity, "刪除完成", Toast.LENGTH_SHORT).show();} catch (RemoteException e) {e.printStackTrace();}}}/*** 應(yīng)該在線程中安裝,此方法僅供測試* @param activity* @param apkPath* @param packageName*/public static boolean installApk(Context context, String apkPath, String packageName) {if (!PluginManager.getInstance().isConnected()) {//installTips(context,"插件服務(wù)正在初始化,請稍后再試。。。");return false;}try {if (PluginManager.getInstance().getPackageInfo(packageName, 0) != null) {//installTips(context,"已經(jīng)安裝了,不能再安裝");} else {int re = PluginManager.getInstance().installPackage(apkPath, 0);if(re == PluginManager.INSTALL_FAILED_NO_REQUESTEDPERMISSION){//安裝失敗,文件請求的權(quán)限太多//installTips(context,"安裝失敗,文件請求的權(quán)限太多");}else{//安裝完成//installTips(context,"安裝完成");return true;}}} catch (Exception e) {e.printStackTrace();}return false;} /**安裝提示* @param context* @param tips*/public static void installTips(Context context,String tips){Looper.prepare();//1、初始化Looper Toast.makeText(context, tips, Toast.LENGTH_SHORT).show();Looper.loop();//4、啟動消息循環(huán)}/** 將assets文件下的apk讀取到讀取到指定路徑* @param context* @param fileName* @param path* @return*/public static boolean copyApkFromAssets(Context context, String fileName, String path) { boolean copyIsFinish = false; try { InputStream is = context.getAssets().open(fileName); File file = new File(path); file.createNewFile(); FileOutputStream fos = new FileOutputStream(file); byte[] temp = new byte[1024]; int i = 0; while ((i = is.read(temp)) > 0) { fos.write(temp, 0, i); } fos.close(); is.close(); copyIsFinish = true; } catch (IOException e) { e.printStackTrace(); } return copyIsFinish; } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97

總結(jié)

最終我們會發(fā)現(xiàn)在/data/data/【host packageName】下有一個Plugin文件夾,文件夾中有個【voice packageName】文件夾,里面有voice的相關(guān)數(shù)據(jù)?

這樣voice.apk就以插件的方式嵌入到我們的主應(yīng)用中了。


原文地址:?http://blog.csdn.net/s003603u/article/details/50750335

總結(jié)

以上是生活随笔為你收集整理的Android实战】DroidPlugin插件化应用分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。