Search in sources :

Example 11 with Tinker

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;
}
Also used : SharedPreferences(android.content.SharedPreferences) TinkerLoadResult(com.tencent.tinker.lib.tinker.TinkerLoadResult) Properties(java.util.Properties) File(java.io.File) Tinker(com.tencent.tinker.lib.tinker.Tinker)

Example 12 with Tinker

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();
}
Also used : Tinker(com.tencent.tinker.lib.tinker.Tinker) File(java.io.File)

Example 13 with Tinker

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);
}
Also used : TinkerRuntimeException(com.tencent.tinker.loader.TinkerRuntimeException) Tinker(com.tencent.tinker.lib.tinker.Tinker)

Example 14 with Tinker

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());
}
Also used : TinkerLoadResult(com.tencent.tinker.lib.tinker.TinkerLoadResult) Tinker(com.tencent.tinker.lib.tinker.Tinker) File(java.io.File)

Example 15 with Tinker

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;
}
Also used : TinkerRuntimeException(com.tencent.tinker.loader.TinkerRuntimeException) ZipFile(java.util.zip.ZipFile) ZipEntry(java.util.zip.ZipEntry) ArrayList(java.util.ArrayList) ApplicationInfo(android.content.pm.ApplicationInfo) ZipFile(java.util.zip.ZipFile) DexFile(dalvik.system.DexFile) File(java.io.File) Tinker(com.tencent.tinker.lib.tinker.Tinker) ShareDexDiffPatchInfo(com.tencent.tinker.loader.shareutil.ShareDexDiffPatchInfo)

Aggregations

Tinker (com.tencent.tinker.lib.tinker.Tinker)21 File (java.io.File)16 TinkerRuntimeException (com.tencent.tinker.loader.TinkerRuntimeException)8 TinkerLoadResult (com.tencent.tinker.lib.tinker.TinkerLoadResult)5 ZipFile (java.util.zip.ZipFile)5 ApplicationInfo (android.content.pm.ApplicationInfo)3 ZipEntry (java.util.zip.ZipEntry)3 SharedPreferences (android.content.SharedPreferences)2 TinkerZipEntry (com.tencent.tinker.commons.ziputil.TinkerZipEntry)2 TinkerZipFile (com.tencent.tinker.commons.ziputil.TinkerZipFile)2 SharePatchInfo (com.tencent.tinker.loader.shareutil.SharePatchInfo)2 ShareResPatchInfo (com.tencent.tinker.loader.shareutil.ShareResPatchInfo)2 DexFile (dalvik.system.DexFile)2 InputStream (java.io.InputStream)2 ArrayList (java.util.ArrayList)2 Properties (java.util.Properties)2 TargetApi (android.annotation.TargetApi)1 AlertDialog (android.app.AlertDialog)1 Context (android.content.Context)1 ViewGroup (android.view.ViewGroup)1