Search in sources :

Example 1 with Tinker

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

the class TinkerLoadLibrary method loadLibraryFromTinker.

/**
     * sample usage for native library
     *
     * @param context
     * @param relativePath such as lib/armeabi
     * @param libName      for the lib libTest.so, you can pass Test or libTest, or libTest.so
     * @return boolean
     * @throws UnsatisfiedLinkError
     */
public static boolean loadLibraryFromTinker(Context context, String relativePath, String libName) throws UnsatisfiedLinkError {
    final Tinker tinker = Tinker.with(context);
    libName = libName.startsWith("lib") ? libName : "lib" + libName;
    libName = libName.endsWith(".so") ? libName : libName + ".so";
    String relativeLibPath = relativePath + "/" + libName;
    //TODO we should add cpu abi, and the real path later
    if (tinker.isEnabledForNativeLib() && tinker.isTinkerLoaded()) {
        TinkerLoadResult loadResult = tinker.getTinkerLoadResultIfPresent();
        if (loadResult.libs != null) {
            for (String name : loadResult.libs.keySet()) {
                if (name.equals(relativeLibPath)) {
                    String patchLibraryPath = loadResult.libraryDirectory + "/" + name;
                    File library = new File(patchLibraryPath);
                    if (library.exists()) {
                        //whether we check md5 when load
                        boolean verifyMd5 = tinker.isTinkerLoadVerify();
                        if (verifyMd5 && !SharePatchFileUtil.verifyFileMd5(library, loadResult.libs.get(name))) {
                            tinker.getLoadReporter().onLoadFileMd5Mismatch(library, ShareConstants.TYPE_LIBRARY);
                        } else {
                            System.load(patchLibraryPath);
                            TinkerLog.i(TAG, "loadLibraryFromTinker success:" + patchLibraryPath);
                            return true;
                        }
                    }
                }
            }
        }
    }
    return false;
}
Also used : TinkerLoadResult(com.tencent.tinker.lib.tinker.TinkerLoadResult) Tinker(com.tencent.tinker.lib.tinker.Tinker) File(java.io.File)

Example 2 with Tinker

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

the class TinkerLoadLibrary method loadArmLibrary.

/**
     * you can use TinkerInstaller.loadLibrary replace your System.loadLibrary for auto update library!
     * only support auto load lib/armeabi library from patch.
     * for other library in lib/* or assets,
     * you can load through {@code TinkerInstaller#loadLibraryFromTinker}
     */
public static void loadArmLibrary(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", libName)) {
            return;
        }
    }
    System.loadLibrary(libName);
}
Also used : TinkerRuntimeException(com.tencent.tinker.loader.TinkerRuntimeException) Tinker(com.tencent.tinker.lib.tinker.Tinker)

Example 3 with Tinker

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

the class DefaultPatchListener method patchCheck.

protected int patchCheck(String path) {
    Tinker manager = Tinker.with(context);
    //check SharePreferences also
    if (!manager.isTinkerEnabled() || !ShareTinkerInternals.isTinkerEnableWithSharedPreferences(context)) {
        return ShareConstants.ERROR_PATCH_DISABLE;
    }
    File file = new File(path);
    if (!SharePatchFileUtil.isLegalFile(file)) {
        return ShareConstants.ERROR_PATCH_NOTEXIST;
    }
    //patch service can not send request
    if (manager.isPatchProcess()) {
        return ShareConstants.ERROR_PATCH_INSERVICE;
    }
    //if the patch service is running, pending
    if (TinkerServiceInternals.isTinkerPatchServiceRunning(context)) {
        return ShareConstants.ERROR_PATCH_RUNNING;
    }
    return ShareConstants.ERROR_PATCH_OK;
}
Also used : Tinker(com.tencent.tinker.lib.tinker.Tinker) File(java.io.File)

Example 4 with Tinker

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

the class BsDiffPatchInternal method extractBsDiffInternals.

private static boolean extractBsDiffInternals(Context context, String dir, String meta, File patchFile, int type) {
    //parse
    ArrayList<ShareBsDiffPatchInfo> patchList = new ArrayList<>();
    ShareBsDiffPatchInfo.parseDiffPatchInfo(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);
    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;
    }
    ZipFile apk = null;
    ZipFile patch = null;
    try {
        String apkPath = applicationInfo.sourceDir;
        apk = new ZipFile(apkPath);
        patch = new ZipFile(patchFile);
        for (ShareBsDiffPatchInfo info : patchList) {
            long start = System.currentTimeMillis();
            final String infoPath = info.path;
            String patchRealPath;
            if (infoPath.equals("")) {
                patchRealPath = info.name;
            } else {
                patchRealPath = info.path + "/" + info.name;
            }
            final String fileMd5 = info.md5;
            if (!SharePatchFileUtil.checkIfMd5Valid(fileMd5)) {
                TinkerLog.w(TAG, "meta file md5 mismatch, type:%s, name: %s, md5: %s", ShareTinkerInternals.getTypeString(type), info.name, info.md5);
                manager.getPatchReporter().onPatchPackageCheckFail(patchFile, BasePatchInternal.getMetaCorruptedCode(type));
                return false;
            }
            String middle;
            middle = info.path + "/" + info.name;
            File extractedFile = new File(dir + middle);
            //check file whether already exist
            if (extractedFile.exists()) {
                if (fileMd5.equals(SharePatchFileUtil.getMD5(extractedFile))) {
                    //it is ok, just continue
                    TinkerLog.w(TAG, "bsdiff 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();
            }
            String patchFileMd5 = info.patchMd5;
            //it is a new file, just copy
            ZipEntry patchFileEntry = patch.getEntry(patchRealPath);
            if (patchFileEntry == null) {
                TinkerLog.w(TAG, "patch entry is null. path:" + patchRealPath);
                manager.getPatchReporter().onPatchTypeExtractFail(patchFile, extractedFile, info.name, type);
                return false;
            }
            if (patchFileMd5.equals("0")) {
                if (!extract(patch, patchFileEntry, extractedFile, fileMd5, false)) {
                    TinkerLog.w(TAG, "Failed to extract file " + extractedFile.getPath());
                    manager.getPatchReporter().onPatchTypeExtractFail(patchFile, extractedFile, info.name, type);
                    return false;
                }
            } else {
                //we do not check the intermediate files' md5 to save time, use check whether it is 32 length
                if (!SharePatchFileUtil.checkIfMd5Valid(patchFileMd5)) {
                    TinkerLog.w(TAG, "meta file md5 mismatch, type:%s, name: %s, md5: %s", ShareTinkerInternals.getTypeString(type), info.name, patchFileMd5);
                    manager.getPatchReporter().onPatchPackageCheckFail(patchFile, BasePatchInternal.getMetaCorruptedCode(type));
                    return false;
                }
                ZipEntry rawApkFileEntry = apk.getEntry(patchRealPath);
                if (rawApkFileEntry == null) {
                    TinkerLog.w(TAG, "apk entry is null. path:" + patchRealPath);
                    manager.getPatchReporter().onPatchTypeExtractFail(patchFile, extractedFile, info.name, type);
                    return false;
                }
                String rawApkCrc = info.rawCrc;
                //check source crc instead of md5 for faster
                String rawEntryCrc = String.valueOf(rawApkFileEntry.getCrc());
                if (!rawEntryCrc.equals(rawApkCrc)) {
                    TinkerLog.e(TAG, "apk entry %s crc is not equal, expect crc: %s, got crc: %s", patchRealPath, rawApkCrc, rawEntryCrc);
                    manager.getPatchReporter().onPatchTypeExtractFail(patchFile, extractedFile, info.name, type);
                    return false;
                }
                InputStream oldStream = null;
                InputStream newStream = null;
                try {
                    oldStream = apk.getInputStream(rawApkFileEntry);
                    newStream = patch.getInputStream(patchFileEntry);
                    BSPatch.patchFast(oldStream, newStream, extractedFile);
                } finally {
                    SharePatchFileUtil.closeQuietly(oldStream);
                    SharePatchFileUtil.closeQuietly(newStream);
                }
                //go go go bsdiff get the
                if (!SharePatchFileUtil.verifyFileMd5(extractedFile, fileMd5)) {
                    TinkerLog.w(TAG, "Failed to recover diff file " + extractedFile.getPath());
                    manager.getPatchReporter().onPatchTypeExtractFail(patchFile, extractedFile, info.name, type);
                    SharePatchFileUtil.safeDeleteFile(extractedFile);
                    return false;
                }
                TinkerLog.w(TAG, "success recover bsdiff file: %s, use time: %d", extractedFile.getPath(), (System.currentTimeMillis() - start));
            }
        }
    } catch (Throwable e) {
        //            e.printStackTrace();
        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) InputStream(java.io.InputStream) ZipEntry(java.util.zip.ZipEntry) ArrayList(java.util.ArrayList) ApplicationInfo(android.content.pm.ApplicationInfo) Tinker(com.tencent.tinker.lib.tinker.Tinker) ZipFile(java.util.zip.ZipFile) ShareBsDiffPatchInfo(com.tencent.tinker.loader.shareutil.ShareBsDiffPatchInfo) File(java.io.File) ZipFile(java.util.zip.ZipFile)

Example 5 with Tinker

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

the class DexDiffPatchInternal method patchDexExtractViaDexDiff.

private static boolean patchDexExtractViaDexDiff(Context context, String patchVersionDirectory, String meta, final File patchFile) {
    String dir = patchVersionDirectory + "/" + DEX_PATH + "/";
    if (!extractDexDiffInternals(context, dir, meta, patchFile, TYPE_DEX)) {
        TinkerLog.w(TAG, "patch recover, extractDiffInternals fail");
        return false;
    }
    final Tinker manager = Tinker.with(context);
    File dexFiles = new File(dir);
    File[] files = dexFiles.listFiles();
    optFiles.clear();
    if (files != null) {
        final String optimizeDexDirectory = patchVersionDirectory + "/" + DEX_OPTIMIZE_PATH + "/";
        File optimizeDexDirectoryFile = new File(optimizeDexDirectory);
        if (!optimizeDexDirectoryFile.exists() && !optimizeDexDirectoryFile.mkdirs()) {
            TinkerLog.w(TAG, "patch recover, make optimizeDexDirectoryFile fail");
            return false;
        }
        // add opt files
        for (File file : files) {
            String outputPathName = SharePatchFileUtil.optimizedPathFor(file, optimizeDexDirectoryFile);
            optFiles.add(new File(outputPathName));
        }
        TinkerLog.w(TAG, "patch recover, try to optimize dex file count:%d", files.length);
        // only use parallel dex optimizer for art
        if (ShareTinkerInternals.isVmArt()) {
            failOptDexFile.clear();
            // try parallel dex optimizer
            TinkerParallelDexOptimizer.optimizeAll(files, optimizeDexDirectoryFile, new TinkerParallelDexOptimizer.ResultCallback() {

                long startTime;

                @Override
                public void onStart(File dexFile, File optimizedDir) {
                    startTime = System.currentTimeMillis();
                    TinkerLog.i(TAG, "start to parallel optimize dex %s, size: %d", dexFile.getPath(), dexFile.length());
                }

                @Override
                public void onSuccess(File dexFile, File optimizedDir, File optimizedFile) {
                    // Do nothing.
                    TinkerLog.i(TAG, "success to parallel optimize dex %s, opt file size: %d, use time %d", dexFile.getPath(), optimizedFile.length(), (System.currentTimeMillis() - startTime));
                }

                @Override
                public void onFailed(File dexFile, File optimizedDir, Throwable thr) {
                    TinkerLog.i(TAG, "fail to parallel optimize dex %s use time %d", dexFile.getPath(), (System.currentTimeMillis() - startTime));
                    failOptDexFile.add(dexFile);
                }
            });
            // try again
            for (File retryDexFile : failOptDexFile) {
                try {
                    String outputPathName = SharePatchFileUtil.optimizedPathFor(retryDexFile, optimizeDexDirectoryFile);
                    if (!SharePatchFileUtil.isLegalFile(retryDexFile)) {
                        manager.getPatchReporter().onPatchDexOptFail(patchFile, retryDexFile, optimizeDexDirectory, retryDexFile.getName(), new TinkerRuntimeException("retry dex optimize file is not exist, name: " + retryDexFile.getName()));
                        return false;
                    }
                    TinkerLog.i(TAG, "try to retry dex optimize file, path: %s, size: %d", retryDexFile.getPath(), retryDexFile.length());
                    long start = System.currentTimeMillis();
                    DexFile.loadDex(retryDexFile.getAbsolutePath(), outputPathName, 0);
                    TinkerLog.i(TAG, "success retry dex optimize file, path: %s, opt file size: %d, use time: %d", retryDexFile.getPath(), new File(outputPathName).length(), (System.currentTimeMillis() - start));
                } catch (Throwable e) {
                    TinkerLog.e(TAG, "retry dex optimize or load failed, path:" + retryDexFile.getPath());
                    manager.getPatchReporter().onPatchDexOptFail(patchFile, retryDexFile, optimizeDexDirectory, retryDexFile.getName(), e);
                    return false;
                }
            }
        // for dalvik, machine hardware performance is much worse than art machine
        } else {
            for (File file : files) {
                try {
                    String outputPathName = SharePatchFileUtil.optimizedPathFor(file, optimizeDexDirectoryFile);
                    long start = System.currentTimeMillis();
                    DexFile.loadDex(file.getAbsolutePath(), outputPathName, 0);
                    TinkerLog.i(TAG, "success single dex optimize file, path: %s, opt file size: %d, use time: %d", file.getPath(), new File(outputPathName).length(), (System.currentTimeMillis() - start));
                } catch (Throwable e) {
                    TinkerLog.e(TAG, "single dex optimize or load failed, path:" + file.getPath());
                    manager.getPatchReporter().onPatchDexOptFail(patchFile, file, optimizeDexDirectory, file.getName(), e);
                    return false;
                }
            }
        }
    }
    return true;
}
Also used : TinkerRuntimeException(com.tencent.tinker.loader.TinkerRuntimeException) TinkerParallelDexOptimizer(com.tencent.tinker.loader.TinkerParallelDexOptimizer) Tinker(com.tencent.tinker.lib.tinker.Tinker) ZipFile(java.util.zip.ZipFile) DexFile(dalvik.system.DexFile) 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