privatevoidincreasingPriority() { if (Build.VERSION.SDK_INT >= 26) { TinkerLog.i(TAG, "for system version >= Android O, we just ignore increasingPriority " + "job to avoid crash or toasts."); return; }
if ("ZUK".equals(Build.MANUFACTURER)) { TinkerLog.i(TAG, "for ZUK device, we just ignore increasingPriority " + "job to avoid crash."); return; }
TinkerLog.i(TAG, "try to increase patch process priority"); // 设置为前台服务,提高优先级 try { Notificationnotification=newNotification(); if (Build.VERSION.SDK_INT < 18) { startForeground(notificationId, notification); } else { startForeground(notificationId, notification); // start InnerService startService(newIntent(this, InnerService.class)); } } catch (Throwable e) { TinkerLog.i(TAG, "try to increase patch process priority error:" + e); } }
privatestaticvoiddoApplyPatch(Context context, Intent intent) { // Since we may retry with IntentService, we should prevent // racing here again. if (!sIsPatchApplying.compareAndSet(false, true)) { TinkerLog.w(TAG, "TinkerPatchService doApplyPatch is running by another runner."); return; }
if (!manager.isTinkerEnabled() || !ShareTinkerInternals.isTinkerEnableWithSharedPreferences(context)) { TinkerLog.e(TAG, "UpgradePatch tryPatch:patch is disabled, just return"); returnfalse; }
if (!SharePatchFileUtil.isLegalFile(patchFile)) { TinkerLog.e(TAG, "UpgradePatch tryPatch:patch file is not found, just return"); returnfalse; }
//it is a new patch, we first delete if there is any files //don't delete dir for faster retry // SharePatchFileUtil.deleteDir(patchVersionDirectory); finalStringpatchName= SharePatchFileUtil.getPatchVersionDirectory(patchMd5);
//we use destPatchFile instead of patchFile, because patchFile may be deleted during the patch process // 合成 dex if (!DexDiffPatchInternal.tryRecoverDexFiles(manager, signatureCheck, context, patchVersionDirectory, destPatchFile)) { TinkerLog.e(TAG, "UpgradePatch tryPatch:new patch recover, try patch dex failed"); returnfalse; } // 合成 so 文件 if (!BsDiffPatchInternal.tryRecoverLibraryFiles(manager, signatureCheck, context, patchVersionDirectory, destPatchFile)) { TinkerLog.e(TAG, "UpgradePatch tryPatch:new patch recover, try patch library failed"); returnfalse; } // 合成资源文件 if (!ResDiffPatchInternal.tryRecoverResourceFiles(manager, signatureCheck, context, patchVersionDirectory, destPatchFile)) { TinkerLog.e(TAG, "UpgradePatch tryPatch:new patch recover, try patch resource failed"); returnfalse; }
这里面的三个合成代码我们到后面的章节再分析,这里先跳过了。
合成完后,还要对 dex 进行opt优化
1 2 3 4 5
// check dex opt file at last, some phone such as VIVO/OPPO like to change dex2oat to interpreted if (!DexDiffPatchInternal.waitAndCheckDexOptFile(patchFile, manager)) { TinkerLog.e(TAG, "UpgradePatch tryPatch:new patch recover, check dex opt file failed"); returnfalse; }
最后,就是把结果重新写入到 patch.info ,这样在加载补丁的流程中就能加载新补丁了。
1 2 3 4 5 6 7 8
if (!SharePatchInfo.rewritePatchInfoFileWithLock(patchInfoFile, newInfo, patchInfoLockFile)) { TinkerLog.e(TAG, "UpgradePatch tryPatch:new patch recover, rewrite patch info failed"); manager.getPatchReporter().onPatchInfoCorrupted(patchFile, newInfo.oldVersion, newInfo.newVersion); returnfalse; }
TinkerLog.w(TAG, "UpgradePatch tryPatch: done, it is ok"); returntrue;