use of com.tencent.tinker.lib.tinker.Tinker in project RxSample by Aload.
the class TinkerPatchListener method patchCheck.
@Override
public int patchCheck(String path) {
File patchFile = new File(path);
TinkerLog.i(TAG, "receive a patch file: %s, file size:%d", path, SharePatchFileUtil.getFileOrDirectorySize(patchFile));
int returnCode = super.patchCheck(path);
if (returnCode == ShareConstants.ERROR_PATCH_OK) {
returnCode = Utils.checkForPatchRecover(NEW_PATCH_RESTRICTION_SPACE_SIZE_MIN, maxMemory);
}
if (returnCode == ShareConstants.ERROR_PATCH_OK) {
String patchMd5 = SharePatchFileUtil.getMD5(patchFile);
SharedPreferences sp = context.getSharedPreferences(ShareConstants.TINKER_SHARE_PREFERENCE_CONFIG, Context.MODE_MULTI_PROCESS);
int fastCrashCount = sp.getInt(patchMd5, 0);
if (fastCrashCount >= TinkerUncaughtExceptionHandler.MAX_CRASH_COUNT) {
returnCode = Utils.ERROR_PATCH_CRASH_LIMIT;
} else {
Tinker tinker = Tinker.with(context);
if (tinker.isTinkerLoaded()) {
TinkerLoadResult tinkerLoadResult = tinker.getTinkerLoadResultIfPresent();
if (tinkerLoadResult != null) {
String currentVersion = tinkerLoadResult.currentVersion;
if (patchMd5.equals(currentVersion)) {
returnCode = Utils.ERROR_PATCH_ALREADY_APPLY;
}
}
}
}
if (returnCode == ShareConstants.ERROR_PATCH_OK) {
returnCode = UpgradePatchRetry.getInstance(context).onPatchListenerCheck(patchMd5) ? ShareConstants.ERROR_PATCH_OK : Utils.ERROR_PATCH_RETRY_COUNT_LIMIT;
}
}
if (returnCode == ShareConstants.ERROR_PATCH_OK) {
Properties properties = ShareTinkerInternals.fastGetPatchPackageMeta(patchFile);
if (properties == null) {
returnCode = Utils.ERROR_PATCH_CONDITION_NOT_SATISFIED;
} else {
String platform = properties.getProperty(Utils.PLATFORM);
TinkerLog.i(TAG, "get platform:" + platform);
if (platform == null || !platform.equals(BuildInfo.PLATFORM)) {
returnCode = Utils.ERROR_PATCH_CONDITION_NOT_SATISFIED;
}
}
}
TinkerResultReport.onTryApply(returnCode == ShareConstants.ERROR_PATCH_OK);
return returnCode;
}
use of com.tencent.tinker.lib.tinker.Tinker in project RxSample by Aload.
the class UpgradePatchRetry method onPatchRetryLoad.
public void onPatchRetryLoad() {
if (!isRetryEnable) {
TinkerLog.w(TAG, "onPatchRetryLoad retry disabled, just return");
return;
}
Tinker tinker = Tinker.with(context);
//only retry on main process
if (!tinker.isMainProcess()) {
TinkerLog.w(TAG, "onPatchRetryLoad retry is not main process, just return");
return;
}
if (!retryInfoFile.exists()) {
TinkerLog.w(TAG, "onPatchRetryLoad retry info not exist, just return");
return;
}
if (TinkerServiceInternals.isTinkerPatchServiceRunning(context)) {
TinkerLog.w(TAG, "onPatchRetryLoad tinker service is running, just return");
return;
}
//must use temp file
String path = tempPatchFile.getAbsolutePath();
if (path == null || !new File(path).exists()) {
TinkerLog.w(TAG, "onPatchRetryLoad patch file: %s is not exist, just return", path);
return;
}
TinkerLog.w(TAG, "onPatchRetryLoad patch file: %s is exist, retry to patch", path);
TinkerInstaller.onReceiveUpgradePatch(context, path);
TinkerResultReport.onReportRetryPatch();
}
use of com.tencent.tinker.lib.tinker.Tinker in project tinker by Tencent.
the class TinkerLoadLibrary method loadArmV7Library.
/**
* you can use TinkerInstaller.loadArmV7Library replace your System.loadLibrary for auto update library!
* only support auto load lib/armeabi-v7a library from patch.
* for other library in lib/* or assets,
* you can load through {@code TinkerInstaller#loadLibraryFromTinker}
*/
public static void loadArmV7Library(Context context, String libName) {
if (libName == null || libName.isEmpty() || context == null) {
throw new TinkerRuntimeException("libName or context is null!");
}
Tinker tinker = Tinker.with(context);
if (tinker.isEnabledForNativeLib()) {
if (TinkerLoadLibrary.loadLibraryFromTinker(context, "lib/armeabi-v7a", libName)) {
return;
}
}
System.loadLibrary(libName);
}
use of com.tencent.tinker.lib.tinker.Tinker in project tinker by Tencent.
the class TinkerLoadLibrary method installNavitveLibraryABI.
/**
* you can reflect your current abi to classloader library path
* as you don't need to use load*Library method above
* @param context
* @param currentABI
*/
public static void installNavitveLibraryABI(Context context, String currentABI) {
Tinker tinker = Tinker.with(context);
if (!tinker.isTinkerLoaded()) {
TinkerLog.i(TAG, "tinker is not loaded, just return");
return;
}
TinkerLoadResult loadResult = tinker.getTinkerLoadResultIfPresent();
if (loadResult.libs == null) {
TinkerLog.i(TAG, "tinker libs is null, just return");
return;
}
File soDir = new File(loadResult.libraryDirectory, "lib/" + currentABI);
if (!soDir.exists()) {
TinkerLog.e(TAG, "current libraryABI folder is not exist, path: %s", soDir.getPath());
return;
}
ClassLoader classLoader = context.getClassLoader();
if (classLoader == null) {
TinkerLog.e(TAG, "classloader is null");
return;
}
TinkerLog.i(TAG, "before hack classloader:" + classLoader.toString());
try {
installNativeLibraryPath(classLoader, soDir);
} catch (Throwable throwable) {
TinkerLog.e(TAG, "installNativeLibraryPath fail:" + throwable);
}
TinkerLog.i(TAG, "after hack classloader:" + classLoader.toString());
}
use of com.tencent.tinker.lib.tinker.Tinker in project tinker by Tencent.
the class DexDiffPatchInternal method extractDexDiffInternals.
private static boolean extractDexDiffInternals(Context context, String dir, String meta, File patchFile, int type) {
//parse
ArrayList<ShareDexDiffPatchInfo> patchList = new ArrayList<>();
ShareDexDiffPatchInfo.parseDexDiffPatchInfo(meta, patchList);
if (patchList.isEmpty()) {
TinkerLog.w(TAG, "extract patch list is empty! type:%s:", ShareTinkerInternals.getTypeString(type));
return true;
}
File directory = new File(dir);
if (!directory.exists()) {
directory.mkdirs();
}
//I think it is better to extract the raw files from apk
Tinker manager = Tinker.with(context);
ZipFile apk = null;
ZipFile patch = null;
try {
ApplicationInfo applicationInfo = context.getApplicationInfo();
if (applicationInfo == null) {
// Looks like running on a test Context, so just return without patching.
TinkerLog.w(TAG, "applicationInfo == null!!!!");
return false;
}
String apkPath = applicationInfo.sourceDir;
apk = new ZipFile(apkPath);
patch = new ZipFile(patchFile);
for (ShareDexDiffPatchInfo info : patchList) {
long start = System.currentTimeMillis();
final String infoPath = info.path;
String patchRealPath;
if (infoPath.equals("")) {
patchRealPath = info.rawName;
} else {
patchRealPath = info.path + "/" + info.rawName;
}
String dexDiffMd5 = info.dexDiffMd5;
String oldDexCrc = info.oldDexCrC;
if (!ShareTinkerInternals.isVmArt() && info.destMd5InDvm.equals("0")) {
TinkerLog.w(TAG, "patch dex %s is only for art, just continue", patchRealPath);
continue;
}
String extractedFileMd5 = ShareTinkerInternals.isVmArt() ? info.destMd5InArt : info.destMd5InDvm;
if (!SharePatchFileUtil.checkIfMd5Valid(extractedFileMd5)) {
TinkerLog.w(TAG, "meta file md5 invalid, type:%s, name: %s, md5: %s", ShareTinkerInternals.getTypeString(type), info.rawName, extractedFileMd5);
manager.getPatchReporter().onPatchPackageCheckFail(patchFile, BasePatchInternal.getMetaCorruptedCode(type));
return false;
}
File extractedFile = new File(dir + info.realName);
//check file whether already exist
if (extractedFile.exists()) {
if (SharePatchFileUtil.verifyDexFileMd5(extractedFile, extractedFileMd5)) {
//it is ok, just continue
TinkerLog.w(TAG, "dex file %s is already exist, and md5 match, just continue", extractedFile.getPath());
continue;
} else {
TinkerLog.w(TAG, "have a mismatch corrupted dex " + extractedFile.getPath());
extractedFile.delete();
}
} else {
extractedFile.getParentFile().mkdirs();
}
ZipEntry patchFileEntry = patch.getEntry(patchRealPath);
ZipEntry rawApkFileEntry = apk.getEntry(patchRealPath);
if (oldDexCrc.equals("0")) {
if (patchFileEntry == null) {
TinkerLog.w(TAG, "patch entry is null. path:" + patchRealPath);
manager.getPatchReporter().onPatchTypeExtractFail(patchFile, extractedFile, info.rawName, type);
return false;
}
//it is a new file, but maybe we need to repack the dex file
if (!extractDexFile(patch, patchFileEntry, extractedFile, info)) {
TinkerLog.w(TAG, "Failed to extract raw patch file " + extractedFile.getPath());
manager.getPatchReporter().onPatchTypeExtractFail(patchFile, extractedFile, info.rawName, type);
return false;
}
} else if (dexDiffMd5.equals("0")) {
// skip process old dex for real dalvik vm
if (!ShareTinkerInternals.isVmArt()) {
continue;
}
if (rawApkFileEntry == null) {
TinkerLog.w(TAG, "apk entry is null. path:" + patchRealPath);
manager.getPatchReporter().onPatchTypeExtractFail(patchFile, extractedFile, info.rawName, type);
return false;
}
//check source crc instead of md5 for faster
String rawEntryCrc = String.valueOf(rawApkFileEntry.getCrc());
if (!rawEntryCrc.equals(oldDexCrc)) {
TinkerLog.e(TAG, "apk entry %s crc is not equal, expect crc: %s, got crc: %s", patchRealPath, oldDexCrc, rawEntryCrc);
manager.getPatchReporter().onPatchTypeExtractFail(patchFile, extractedFile, info.rawName, type);
return false;
}
// Small patched dex generating strategy was disabled, we copy full original dex directly now.
//patchDexFile(apk, patch, rawApkFileEntry, null, info, smallPatchInfoFile, extractedFile);
extractDexFile(apk, rawApkFileEntry, extractedFile, info);
if (!SharePatchFileUtil.verifyDexFileMd5(extractedFile, extractedFileMd5)) {
TinkerLog.w(TAG, "Failed to recover dex file when verify patched dex: " + extractedFile.getPath());
manager.getPatchReporter().onPatchTypeExtractFail(patchFile, extractedFile, info.rawName, type);
SharePatchFileUtil.safeDeleteFile(extractedFile);
return false;
}
} else {
if (patchFileEntry == null) {
TinkerLog.w(TAG, "patch entry is null. path:" + patchRealPath);
manager.getPatchReporter().onPatchTypeExtractFail(patchFile, extractedFile, info.rawName, type);
return false;
}
if (!SharePatchFileUtil.checkIfMd5Valid(dexDiffMd5)) {
TinkerLog.w(TAG, "meta file md5 invalid, type:%s, name: %s, md5: %s", ShareTinkerInternals.getTypeString(type), info.rawName, dexDiffMd5);
manager.getPatchReporter().onPatchPackageCheckFail(patchFile, BasePatchInternal.getMetaCorruptedCode(type));
return false;
}
if (rawApkFileEntry == null) {
TinkerLog.w(TAG, "apk entry is null. path:" + patchRealPath);
manager.getPatchReporter().onPatchTypeExtractFail(patchFile, extractedFile, info.rawName, type);
return false;
}
//check source crc instead of md5 for faster
String rawEntryCrc = String.valueOf(rawApkFileEntry.getCrc());
if (!rawEntryCrc.equals(oldDexCrc)) {
TinkerLog.e(TAG, "apk entry %s crc is not equal, expect crc: %s, got crc: %s", patchRealPath, oldDexCrc, rawEntryCrc);
manager.getPatchReporter().onPatchTypeExtractFail(patchFile, extractedFile, info.rawName, type);
return false;
}
patchDexFile(apk, patch, rawApkFileEntry, patchFileEntry, info, extractedFile);
if (!SharePatchFileUtil.verifyDexFileMd5(extractedFile, extractedFileMd5)) {
TinkerLog.w(TAG, "Failed to recover dex file when verify patched dex: " + extractedFile.getPath());
manager.getPatchReporter().onPatchTypeExtractFail(patchFile, extractedFile, info.rawName, type);
SharePatchFileUtil.safeDeleteFile(extractedFile);
return false;
}
TinkerLog.w(TAG, "success recover dex file: %s, size: %d, use time: %d", extractedFile.getPath(), extractedFile.length(), (System.currentTimeMillis() - start));
}
}
} catch (Throwable e) {
throw new TinkerRuntimeException("patch " + ShareTinkerInternals.getTypeString(type) + " extract failed (" + e.getMessage() + ").", e);
} finally {
SharePatchFileUtil.closeZip(apk);
SharePatchFileUtil.closeZip(patch);
}
return true;
}
Aggregations