Search in sources :

Example 6 with Tinker

use of com.tencent.tinker.lib.tinker.Tinker in project tinker by Tencent.

the class ResDiffPatchInternal method checkAndExtractResourceLargeFile.

private static boolean checkAndExtractResourceLargeFile(Context context, String apkPath, File directory, File patchFile, ShareResPatchInfo resPatchInfo, int type) {
    long start = System.currentTimeMillis();
    Tinker manager = Tinker.with(context);
    ZipFile apkFile = null;
    ZipFile patchZipFile = null;
    try {
        //recover resources.arsc first
        apkFile = new ZipFile(apkPath);
        ZipEntry arscEntry = apkFile.getEntry(ShareConstants.RES_ARSC);
        File arscFile = new File(directory, ShareConstants.RES_ARSC);
        if (arscEntry == null) {
            TinkerLog.w(TAG, "resources apk entry is null. path:" + ShareConstants.RES_ARSC);
            manager.getPatchReporter().onPatchTypeExtractFail(patchFile, arscFile, ShareConstants.RES_ARSC, type);
            return false;
        }
        //use base resources.arsc crc to identify base.apk
        String baseArscCrc = String.valueOf(arscEntry.getCrc());
        if (!baseArscCrc.equals(resPatchInfo.arscBaseCrc)) {
            TinkerLog.e(TAG, "resources.arsc's crc is not equal, expect crc: %s, got crc: %s", resPatchInfo.arscBaseCrc, baseArscCrc);
            manager.getPatchReporter().onPatchTypeExtractFail(patchFile, arscFile, ShareConstants.RES_ARSC, type);
            return false;
        }
        //resource arsc is not changed, just return true
        if (resPatchInfo.largeModRes.isEmpty()) {
            TinkerLog.i(TAG, "no large modify resources, just return");
            return true;
        }
        for (String name : resPatchInfo.largeModRes) {
            long largeStart = System.currentTimeMillis();
            ShareResPatchInfo.LargeModeInfo largeModeInfo = resPatchInfo.largeModMap.get(name);
            if (largeModeInfo == null) {
                TinkerLog.w(TAG, "resource not found largeModeInfo, type:%s, name: %s", ShareTinkerInternals.getTypeString(type), name);
                manager.getPatchReporter().onPatchPackageCheckFail(patchFile, BasePatchInternal.getMetaCorruptedCode(type));
                return false;
            }
            largeModeInfo.file = new File(directory, name);
            SharePatchFileUtil.ensureFileDirectory(largeModeInfo.file);
            //we do not check the intermediate files' md5 to save time, use check whether it is 32 length
            if (!SharePatchFileUtil.checkIfMd5Valid(largeModeInfo.md5)) {
                TinkerLog.w(TAG, "resource meta file md5 mismatch, type:%s, name: %s, md5: %s", ShareTinkerInternals.getTypeString(type), name, largeModeInfo.md5);
                manager.getPatchReporter().onPatchPackageCheckFail(patchFile, BasePatchInternal.getMetaCorruptedCode(type));
                return false;
            }
            patchZipFile = new ZipFile(patchFile);
            ZipEntry patchEntry = patchZipFile.getEntry(name);
            if (patchEntry == null) {
                TinkerLog.w(TAG, "large mod patch entry is null. path:" + name);
                manager.getPatchReporter().onPatchTypeExtractFail(patchFile, largeModeInfo.file, name, type);
                return false;
            }
            ZipEntry baseEntry = apkFile.getEntry(name);
            if (baseEntry == null) {
                TinkerLog.w(TAG, "resources apk entry is null. path:" + name);
                manager.getPatchReporter().onPatchTypeExtractFail(patchFile, largeModeInfo.file, name, type);
                return false;
            }
            InputStream oldStream = null;
            InputStream newStream = null;
            try {
                oldStream = apkFile.getInputStream(baseEntry);
                newStream = patchZipFile.getInputStream(patchEntry);
                BSPatch.patchFast(oldStream, newStream, largeModeInfo.file);
            } finally {
                SharePatchFileUtil.closeQuietly(oldStream);
                SharePatchFileUtil.closeQuietly(newStream);
            }
            //go go go bsdiff get the
            if (!SharePatchFileUtil.verifyFileMd5(largeModeInfo.file, largeModeInfo.md5)) {
                TinkerLog.w(TAG, "Failed to recover large modify file:%s", largeModeInfo.file.getPath());
                SharePatchFileUtil.safeDeleteFile(largeModeInfo.file);
                manager.getPatchReporter().onPatchTypeExtractFail(patchFile, largeModeInfo.file, name, type);
                return false;
            }
            TinkerLog.w(TAG, "success recover large modify file:%s, file size:%d, use time:%d", largeModeInfo.file.getPath(), largeModeInfo.file.length(), (System.currentTimeMillis() - largeStart));
        }
        TinkerLog.w(TAG, "success recover all large modify use time:%d", (System.currentTimeMillis() - start));
    } catch (Throwable e) {
        //            e.printStackTrace();
        throw new TinkerRuntimeException("patch " + ShareTinkerInternals.getTypeString(type) + " extract failed (" + e.getMessage() + ").", e);
    } finally {
        SharePatchFileUtil.closeZip(apkFile);
        SharePatchFileUtil.closeZip(patchZipFile);
    }
    return true;
}
Also used : TinkerRuntimeException(com.tencent.tinker.loader.TinkerRuntimeException) TinkerZipFile(com.tencent.tinker.commons.ziputil.TinkerZipFile) ZipFile(java.util.zip.ZipFile) ShareResPatchInfo(com.tencent.tinker.loader.shareutil.ShareResPatchInfo) InputStream(java.io.InputStream) TinkerZipEntry(com.tencent.tinker.commons.ziputil.TinkerZipEntry) ZipEntry(java.util.zip.ZipEntry) Tinker(com.tencent.tinker.lib.tinker.Tinker) TinkerZipFile(com.tencent.tinker.commons.ziputil.TinkerZipFile) File(java.io.File) ZipFile(java.util.zip.ZipFile)

Example 7 with Tinker

use of com.tencent.tinker.lib.tinker.Tinker in project tinker by Tencent.

the class MainActivity method showInfo.

public boolean showInfo(Context context) {
    // add more Build Info
    final StringBuilder sb = new StringBuilder();
    Tinker tinker = Tinker.with(getApplicationContext());
    if (tinker.isTinkerLoaded()) {
        sb.append(String.format("[patch is loaded] \n"));
        sb.append(String.format("[buildConfig TINKER_ID] %s \n", BuildInfo.TINKER_ID));
        sb.append(String.format("[buildConfig BASE_TINKER_ID] %s \n", BaseBuildInfo.BASE_TINKER_ID));
        sb.append(String.format("[buildConfig MESSSAGE] %s \n", BuildInfo.MESSAGE));
        sb.append(String.format("[TINKER_ID] %s \n", tinker.getTinkerLoadResultIfPresent().getPackageConfigByName(ShareConstants.TINKER_ID)));
        sb.append(String.format("[packageConfig patchMessage] %s \n", tinker.getTinkerLoadResultIfPresent().getPackageConfigByName("patchMessage")));
        sb.append(String.format("[TINKER_ID Rom Space] %d k \n", tinker.getTinkerRomSpace()));
    } else {
        sb.append(String.format("[patch is not loaded] \n"));
        sb.append(String.format("[buildConfig TINKER_ID] %s \n", BuildInfo.TINKER_ID));
        sb.append(String.format("[buildConfig BASE_TINKER_ID] %s \n", BaseBuildInfo.BASE_TINKER_ID));
        sb.append(String.format("[buildConfig MESSSAGE] %s \n", BuildInfo.MESSAGE));
        sb.append(String.format("[TINKER_ID] %s \n", ShareTinkerInternals.getManifestTinkerID(getApplicationContext())));
    }
    sb.append(String.format("[BaseBuildInfo Message] %s \n", BaseBuildInfo.TEST_MESSAGE));
    final TextView v = new TextView(context);
    v.setText(sb);
    v.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
    v.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 10);
    v.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
    v.setTextColor(0xFF000000);
    v.setTypeface(Typeface.MONOSPACE);
    final int padding = 16;
    v.setPadding(padding, padding, padding, padding);
    final AlertDialog.Builder builder = new AlertDialog.Builder(context);
    builder.setCancelable(true);
    builder.setView(v);
    final AlertDialog alert = builder.create();
    alert.show();
    return true;
}
Also used : AlertDialog(android.app.AlertDialog) ViewGroup(android.view.ViewGroup) TextView(android.widget.TextView) Tinker(com.tencent.tinker.lib.tinker.Tinker)

Example 8 with Tinker

use of com.tencent.tinker.lib.tinker.Tinker in project tinker by Tencent.

the class SamplePatchListener method patchCheck.

/**
     * because we use the defaultCheckPatchReceived method
     * the error code define by myself should after {@code ShareConstants.ERROR_RECOVER_INSERVICE
     *
     * @param path
     * @param newPatch
     * @return
     */
@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);
        //optional, only disable this patch file with md5
        int fastCrashCount = sp.getInt(patchMd5, 0);
        if (fastCrashCount >= SampleUncaughtExceptionHandler.MAX_CRASH_COUNT) {
            returnCode = Utils.ERROR_PATCH_CRASH_LIMIT;
        } else {
            //for upgrade patch, version must be not the same
            //for repair patch, we won't has the tinker load flag
            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;
                    }
                }
            }
        }
        //check whether retry so many times
        if (returnCode == ShareConstants.ERROR_PATCH_OK) {
            returnCode = UpgradePatchRetry.getInstance(context).onPatchListenerCheck(patchMd5) ? ShareConstants.ERROR_PATCH_OK : Utils.ERROR_PATCH_RETRY_COUNT_LIMIT;
        }
    }
    // Interception some of the request
    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);
            // check patch platform require
            if (platform == null || !platform.equals(BuildInfo.PLATFORM)) {
                returnCode = Utils.ERROR_PATCH_CONDITION_NOT_SATISFIED;
            }
        }
    }
    SampleTinkerReport.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 9 with Tinker

use of com.tencent.tinker.lib.tinker.Tinker in project tinker by Tencent.

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

Example 10 with Tinker

use of com.tencent.tinker.lib.tinker.Tinker in project RxSample by Aload.

the class TinkerLoadReporter method onLoadFileNotFound.

/**
     * try to recover patch oat file
     *
     * @param file
     * @param fileType
     * @param isDirectory
     */
@Override
public void onLoadFileNotFound(File file, int fileType, boolean isDirectory) {
    TinkerLog.i(TAG, "patch loadReporter onLoadFileNotFound: patch file not found: %s, fileType:%d, isDirectory:%b", file.getAbsolutePath(), fileType, isDirectory);
    if (fileType == ShareConstants.TYPE_DEX_OPT) {
        Tinker tinker = Tinker.with(context);
        if (tinker.isMainProcess()) {
            File patchVersionFile = tinker.getTinkerLoadResultIfPresent().patchVersionFile;
            if (patchVersionFile != null) {
                if (UpgradePatchRetry.getInstance(context).onPatchListenerCheck(SharePatchFileUtil.getMD5(patchVersionFile))) {
                    TinkerLog.i(TAG, "try to repair oat file on patch process");
                    TinkerInstaller.onReceiveUpgradePatch(context, patchVersionFile.getAbsolutePath());
                } else {
                    TinkerLog.i(TAG, "repair retry exceed must max time, just clean");
                    checkAndCleanPatch();
                }
            }
        }
    } else {
        checkAndCleanPatch();
    }
    TinkerResultReport.onLoadFileNotFound(fileType);
}
Also used : Tinker(com.tencent.tinker.lib.tinker.Tinker) File(java.io.File)

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