1.開始安裝APK使用之前需要判斷一下插件服務是否連接(待研究)
if (!PluginManager.getInstance().isConnected()) {
//return "連接失敗"; // 連接失敗
Toast.makeText(MainActivity.this, "連接失敗", Toast.LENGTH_SHORT).show();
}
2.插件安裝
真正的實現(xiàn)在IPluginManagerImpl中,(具體的從PliginManager調(diào)用鏈過程之后分析)。
@Override
public int installPackage(String filepath, int flags) throws RemoteException {
//install plugin
String apkfile = null;
try {
//拿到pcakageInfo信息
PackageManager pm = mContext.getPackageManager();
PackageInfo info = pm.getPackageArchiveInfo(filepath, 0);
if (info == null) {
return PackageManagerCompat.INSTALL_FAILED_INVALID_APK;
}
apkfile = PluginDirHelper.getPluginApkFile(mContext, info.packageName);
//打印下:apkfile: /data/data/com.example.TestPlugin/Plugin/com.iflytek.flownotification/apk/base-1.apk
//這里暫時理解為安裝后的路徑
if ((flags & PackageManagerCompat.INSTALL_REPLACE_EXISTING) != 0) {
//新安裝的插件
// 停止,???
forceStopPackage(info.packageName);
//刪除插件的緩存 ??
if (mPluginCache.containsKey(info.packageName)) {
deleteApplicationCacheFiles(info.packageName, null);
}
//刪除文件???
new File(apkfile).delete();
//將安裝包拷貝到apkfile
Utils.copyFile(filepath, apkfile);
//初始化解析器并完成Mainfest的解析,返回解析器,保存了解析內(nèi)容
PluginPackageParser parser = new PluginPackageParser(mContext, new File(apkfile));
//獲取應用簽名
parser.collectCertificates(0);
//獲取權(quán)限和簽名
PackageInfo pkgInfo = parser.getPackageInfo(PackageManager.GET_PERMISSIONS | PackageManager.GET_SIGNATURES);
//校驗權(quán)限是否在宿主中有聲明過
if (pkgInfo != null && pkgInfo.requestedPermissions != null && pkgInfo.requestedPer
//保存簽名信息
saveSignatures(pkgInfo);
// if (pkgInfo.reqFeatures != null && pkgInfo.reqFeatures.length > 0) {
// for (FeatureInfo reqFeature : pkgInfo.reqFeatures) {
// Log.e(TAG, "reqFeature name=%s,flags=%s,glesVersion=%s", reqFeature.name, reqFeature.flags, reqFeature.getGlEsVersion());
// }
// }
// 拷貝插件中的native庫文件。
copyNativeLibs(mContext, apkfile, parser.getApplicationInfo(0));
//opt,暫時沒用到,忽略
dexOpt(mContext, apkfile, parser);
//緩存下
mPluginCache.put(parser.getPackageName(), parser);
//回調(diào)函數(shù)???,通知插件安裝
mActivityManagerService.onPkgInstalled(mPluginCache, parser, parser.getPackageName());
sendInstalledBroadcast(info.packageName);
return PackageManagerCompat.INSTALL_SUCCEEDED;
} else {
//已經(jīng)安裝過了,做升級處理
if (mPluginCache.containsKey(info.packageName)) {
return PackageManagerCompat.INSTALL_FAILED_ALREADY_EXISTS;
} else {
forceStopPackage(info.packageName);
new File(apkfile).delete();
Utils.copyFile(filepath, apkfile);
PluginPackageParser parser = new PluginPackageParser(mContext, new File(apkfile));
parser.collectCertificates(0);
PackageInfo pkgInfo = parser.getPackageInfo(PackageManager.GET_PERMISSIONS | PackageManager.GET_SIGNATURES);
if (pkgInfo != null && pkgInfo.requestedPermissions != null && pkgInfo.requestedPermissions.length > 0) {
for (String requestedPermission : pkgInfo.requestedPermissions) {
boolean b = false;
try {
b = pm.getPermissionInfo(requestedPermission, 0) != null;
} catch (NameNotFoundException e) {
}
if (!mHostRequestedPermission.contains(requestedPermission) && b) {
Log.e(TAG, "No Permission %s", requestedPermission);
new File(apkfile).delete();
return PluginManager.INSTALL_FAILED_NO_REQUESTEDPERMISSION;
}
}
}
saveSignatures(pkgInfo);
// if (pkgInfo.reqFeatures != null && pkgInfo.reqFeatures.length > 0) {
// for (FeatureInfo reqFeature : pkgInfo.reqFeatures) {
// Log.e(TAG, "reqFeature name=%s,flags=%s,glesVersion=%s", reqFeature.name, reqFeature.flags, reqFeature.getGlEsVersion());
// }
// }
copyNativeLibs(mContext, apkfile, parser.getApplicationInfo(0));
dexOpt(mContext, apkfile, parser);
mPluginCache.put(parser.getPackageName(), parser);
mActivityManagerService.onPkgInstalled(mPluginCache, parser, parser.getPackageName());
sendInstalledBroadcast(info.packageName);
return PackageManagerCompat.INSTALL_SUCCEEDED;
}
}
} catch (Exception e) {
if (apkfile != null) {
new File(apkfile).delete();
}
handleException(e);
return PackageManagerCompat.INSTALL_FAILED_INTERNAL_ERROR;
}
}
其中
PluginPackageParser構(gòu)造函數(shù)部分代碼如下:
public PluginPackageParser(Context hostContext, File pluginFile) throws Exception {
mHostContext = hostContext; //保存宿主進程Context
mPluginFile = pluginFile;//插件Apk文件路徑。
mParser = PackageParser.newPluginParser(hostContext);//PackageParser(插件自定義)類實例,他是一個兼容系統(tǒng)各個版本的PackageParser,解析Mainfest
mParser.parsePackage(pluginFile, 0);
mPackageName = mParser.getPackageName();//解析后獲得插件Apk的包名。
mHostPackageInfo = mHostContext.getPackageManager().getPackageInfo(mHostContext.getPackageName(), 0);// 宿主進程的PackageInfo實例。
//mActivityIntentFilterCache,mServiceIntentFilterCache,mProviderIntentFilterCache,mReceiverIntentFilterCache: 這幾個變量主要保存四大組件ComponentName對應的IntentFilter。
//獲取保存Activity
List datas = mParser.getActivities();
for (Object data : datas) {
ComponentName componentName = new ComponentName(mPackageName, mParser.readNameFromComponent(data));
synchronized (mActivityObjCache) {
mActivityObjCache.put(componentName, data);
}
synchronized (mActivityInfoCache) {
ActivityInfo value = mParser.generateActivityInfo(data, 0);
fixApplicationInfo(value.applicationInfo);
if (TextUtils.isEmpty(value.processName)) {
value.processName = value.packageName;
}
mActivityInfoCache.put(componentName, value);
}
List<IntentFilter> filters = mParser.readIntentFilterFromComponent(data);
synchronized (mActivityIntentFilterCache) {
mActivityIntentFilterCache.remove(componentName);
mActivityIntentFilterCache.put(componentName, new ArrayList<IntentFilter>(filters));
}
}
//獲取保存Service
//獲取保存ContentProvide
//獲取保存 Receiver
//獲取保存Instrumentation
//獲取保存Permissions
//獲取保存PermissionGroups
//獲取保存PermissionGroups
}
總結(jié):插件的安裝過程其實就是,
1 把插件Apk文件保存在宿主進程:/data/data/宿主進程報名/plugin/plugin包名/apk/base-1.apk下面。
2 通過PluginPackageParser解析插件Apk AndroidManifest文件,保存插件Apk 四大組件以及權(quán)限等信息,來方便查詢。
3 PluginClassLoader保存優(yōu)化后的Dex文件,加載插件Apk的類。
3.卸載
@Override
public int deletePackage(String packageName, int flags) throws RemoteException {
try {
if (mPluginCache.containsKey(packageName)) {
forceStopPackage(packageName);
PluginPackageParser parser;
synchronized (mPluginCache) {
parser = mPluginCache.remove(packageName);
}
Utils.deleteDir(PluginDirHelper.makePluginBaseDir(mContext, packageName));
mActivityManagerService.onPkgDeleted(mPluginCache, parser, packageName);
mSignatureCache.remove(packageName);
sendUninstalledBroadcast(packageName);
return PackageManagerCompat.DELETE_SUCCEEDED;
}
} catch (Exception e) {
handleException(e);
}
return PackageManagerCompat.DELETE_FAILED_INTERNAL_ERROR;
}
這個函數(shù)主要工作如下:
? 從mPluginCache中通過要卸載的插件Apk包名查看是否已經(jīng)安裝并緩存相關(guān)信息。如果在mPluginCache存在對應包的PluginPackageParser類實例,就對一些緩存進行處理:
- 停止包運行的所在進程,
- 把包對應的PluginPackageParser從緩存中刪除
- 刪除宿主進程安裝包對應的目錄(/data/data/宿主進程報名/plugin/plugin包名)中的文件
- 移除插件包對應的簽名
- 發(fā)送卸載成功廣播