com.tencent.tinker.loader.shareutil.SharePatchFileUtil Java Examples

The following examples show how to use com.tencent.tinker.loader.shareutil.SharePatchFileUtil. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: TinkerServerPatchRequestCallback.java    From tinkerpatch-sdk with MIT License 6 votes vote down vote up
private boolean handlePatchFile(Context context, Integer version, File patchFile) {
    SharedPreferences sp = context.getSharedPreferences(
        TinkerServerClient.SHARE_SERVER_PREFERENCE_CONFIG, Context.MODE_PRIVATE
    );
    int current = sp.getInt(TINKER_RETRY_PATCH, 0);
    if (current >= TINKER_MAX_RETRY_COUNT) {
        SharePatchFileUtil.safeDeleteFile(patchFile);
        sp.edit().putInt(TINKER_RETRY_PATCH, 0).commit();
        TinkerLog.w(TAG,
            "beforePatchRequest, retry patch install more than %d times, version: %d, patch:%s",
            current, version, patchFile.getPath()
        );
    } else {
        TinkerLog.w(TAG, "beforePatchRequest, have pending patch to install, version: %d, patch:%s",
            version, patchFile.getPath()
        );

        sp.edit().putInt(TINKER_RETRY_PATCH, ++current).commit();
        TinkerInstaller.onReceiveUpgradePatch(context, patchFile.getAbsolutePath());
        return true;
    }
    return false;
}
 
Example #2
Source File: DefaultPatchRequestCallback.java    From tinkerpatch-sdk with MIT License 6 votes vote down vote up
@Override
public boolean onPatchUpgrade(File file, Integer newVersion, Integer currentVersion) {
    TinkerLog.i(TAG, "onPatchUpgrade, file:%s, newVersion:%d, currentVersion:%d",
        file.getPath(), newVersion, currentVersion);
    TinkerServerClient client = TinkerServerClient.get();
    Context context = client.getContext();
    client.reportPatchDownloadSuccess(newVersion);

    ShareSecurityCheck securityCheck = new ShareSecurityCheck(context);
    if (!securityCheck.verifyPatchMetaSignature(file)) {
        TinkerLog.e(TAG, "onPatchUpgrade, signature check fail. file: %s, version:%d", file.getPath(), newVersion);
        //treat it as download fail
        if (increaseDownloadError(context)) {
            //update tinker version also, don't request again
            client.updateTinkerVersion(newVersion, SharePatchFileUtil.getMD5(file));
            client.reportPatchFail(newVersion, ERROR_DOWNLOAD_CHECK_FAIL);
        }
        SharePatchFileUtil.safeDeleteFile(file);
        return false;
    }
    tryPatchFile(file, newVersion);
    return true;
}
 
Example #3
Source File: DefaultPatchRequestCallback.java    From tinkerpatch-sdk with MIT License 6 votes vote down vote up
private void tryPatchFile(File patchFile, Integer newVersion) {
    TinkerServerClient client = TinkerServerClient.get();
    Context context = client.getContext();
    //In order to calculate the user number, just report success here
    String patchMd5 = SharePatchFileUtil.getMD5(patchFile);
    //update version
    client.updateTinkerVersion(newVersion, patchMd5);
    //delete old patch sever file
    File serverDir = ServerUtils.getServerDirectory(context);
    if (serverDir != null) {
        File[] files = serverDir.listFiles();
        if (files != null) {
            String currentName = patchFile.getName();
            for (File file : files) {
                String fileName = file.getName();
                if (fileName.equals(currentName) || fileName.equals(ServerUtils.TINKER_VERSION_FILE)) {
                    continue;
                }
                SharePatchFileUtil.safeDeleteFile(file);
            }
        }
        client.reportPatchApplySuccess(newVersion);
        //try install
        TinkerInstaller.onReceiveUpgradePatch(context, patchFile.getAbsolutePath());
    }
}
 
Example #4
Source File: SamplePatchListener.java    From HotFixDemo with MIT License 5 votes vote down vote up
/**
 * 若检查成功,我们会调用TinkerPatchService.runPatchService唤起:patch进程,去尝试完成补丁合成操作。反之,会回调检验失败的接口。
 * 若检查失败,会在LoadReporter的onLoadPatchListenerReceiveFail中回调。
 * <p>
 * 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, String patchMd5) {
    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, patchMd5);

    if (returnCode == ShareConstants.ERROR_PATCH_OK) {
        returnCode = TinkerUtils.checkForPatchRecover(NEW_PATCH_RESTRICTION_SPACE_SIZE_MIN, maxMemory);
    }

    if (returnCode == ShareConstants.ERROR_PATCH_OK) {
        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 = TinkerUtils.ERROR_PATCH_CRASH_LIMIT;
        }
    }
    // Warning, it is just a sample case, you don't need to copy all of these
    // Interception some of the request
    if (returnCode == ShareConstants.ERROR_PATCH_OK) {
        Properties properties = ShareTinkerInternals.fastGetPatchPackageMeta(patchFile);
        if (properties == null) {
            returnCode = TinkerUtils.ERROR_PATCH_CONDITION_NOT_SATISFIED;
        } else {
            String platform = properties.getProperty(TinkerUtils.PLATFORM);
            TinkerLog.i(TAG, "get platform:" + platform);
            // check patch platform require
            if (platform == null || !platform.equals("all")) {
                returnCode = TinkerUtils.ERROR_PATCH_CONDITION_NOT_SATISFIED;
            }
        }
    }

    SampleTinkerReport.onTryApply(returnCode == ShareConstants.ERROR_PATCH_OK);
    return returnCode;
}
 
Example #5
Source File: SampleLoadReporter.java    From tinker-manager with Apache License 2.0 5 votes vote down vote up
/**
 * 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);

    // only try to recover opt file
    // check dex opt file at last, some phone such as VIVO/OPPO like to change dex2oat to interpreted
    if (fileType == ShareConstants.TYPE_DEX_OPT) {
        Tinker tinker = Tinker.with(context);
        //we can recover at any process except recover process
        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();
    }
    SampleTinkerReport.onLoadFileNotFound(fileType);
}
 
Example #6
Source File: SamplePatchListener.java    From tinker-manager with Apache License 2.0 5 votes vote down vote up
/**
 * 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, String patchMd5) {
    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, patchMd5);

    if (returnCode == ShareConstants.ERROR_PATCH_OK) {
        returnCode = SampleUtils.checkForPatchRecover(NEW_PATCH_RESTRICTION_SPACE_SIZE_MIN, maxMemory);
    }

    if (returnCode == ShareConstants.ERROR_PATCH_OK) {
        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 = SampleUtils.ERROR_PATCH_CRASH_LIMIT;
        }
    }
    // Warning, it is just a sample case, you don't need to copy all of these
    // Interception some of the request
    if (returnCode == ShareConstants.ERROR_PATCH_OK) {
        Properties properties = ShareTinkerInternals.fastGetPatchPackageMeta(patchFile);
        if (properties == null) {
            returnCode = SampleUtils.ERROR_PATCH_CONDITION_NOT_SATISFIED;
        } else {
            String platform = properties.getProperty(SampleUtils.PLATFORM);
            TinkerLog.i(TAG, "get platform:" + platform);
            // check patch platform require
            if (platform == null) {
                returnCode = SampleUtils.ERROR_PATCH_CONDITION_NOT_SATISFIED;
            }
        }
    }

    SampleTinkerReport.onTryApply(returnCode == ShareConstants.ERROR_PATCH_OK);
    return returnCode;
}
 
Example #7
Source File: SamplePatchListener.java    From tinker-manager with Apache License 2.0 5 votes vote down vote up
@Override
public int onPatchReceived(String path) {

    path = PatchUtils.release(path);

    int returnCode = patchCheck(path, SharePatchFileUtil.getMD5(new File(path)));

    if (returnCode == ShareConstants.ERROR_PATCH_OK) {
        SamplePatchService.runPatchService(context, path);
    } else {
        Tinker.with(context).getLoadReporter().onLoadPatchListenerReceiveFail(new File(path), returnCode);
    }
    return returnCode;

}
 
Example #8
Source File: SampleDexDiffPatchInternal.java    From tinker-manager with Apache License 2.0 5 votes vote down vote up
public static boolean waitDexOptFile() {
        if (optFiles.isEmpty()) {
            return true;
        }

        int size = optFiles.size() * 6;
        if (size > MAX_WAIT_COUNT) {
            size = MAX_WAIT_COUNT;
        }
        TinkerLog.i(TAG, "dex count: %d, final wait time: %d", optFiles.size(), size);

        for (int i = 0; i < size; i++) {
            if (!checkAllDexOptFile(optFiles, i + 1)) {
                try {
                    Thread.sleep(WAIT_ASYN_OAT_TIME);
                } catch (InterruptedException e) {
                    TinkerLog.e(TAG, "thread sleep InterruptedException e:" + e);
                }
            }
        }

        // check again, if still can be found, just return
        for (File file : optFiles) {
            TinkerLog.i(TAG, "check dex optimizer file %s, size %d", file.getName(), file.length());

            if (!SharePatchFileUtil.isLegalFile(file)) {
                TinkerLog.e(TAG, "final parallel dex optimizer file %s is not exist, return false", file.getName());
                // don't report fail
//                manager.getPatchReporter()
//                    .onPatchDexOptFail(patchFile, file, file.getParentFile().getPath(),
//                        file.getName(), new TinkerRuntimeException("dexOpt file:" + file.getName() + " is not exist"));
                return false;

            }
        }
        return true;
    }
 
Example #9
Source File: SampleDexDiffPatchInternal.java    From tinker-manager with Apache License 2.0 5 votes vote down vote up
/**
 * for ViVo or some other rom, they would make dex2oat asynchronous
 * so we need to check whether oat file is actually generated.
 * @param files
 * @param count
 * @return
 */
private static boolean checkAllDexOptFile(ArrayList<File> files, int count) {
    for (File file : files) {
        if (!SharePatchFileUtil.isLegalFile(file)) {
            TinkerLog.e(TAG, "parallel dex optimizer file %s is not exist, just wait %d times", file.getName(), count);
            return false;
        }
    }
    return true;
}
 
Example #10
Source File: SampleDexDiffPatchInternal.java    From tinker-manager with Apache License 2.0 5 votes vote down vote up
private static boolean extractDexFile(ZipFile zipFile, ZipEntry entryFile, File extractTo, ShareDexDiffPatchInfo dexInfo) throws IOException {
    final String fileMd5 = ShareTinkerInternals.isVmArt() ? dexInfo.destMd5InArt : dexInfo.destMd5InDvm;
    final String rawName = dexInfo.rawName;
    final boolean isJarMode = dexInfo.isJarMode;
    //it is raw dex and we use jar mode, so we need to zip it!
    if (SharePatchFileUtil.isRawDexFile(rawName) && isJarMode) {
        return extractDexToJar(zipFile, entryFile, extractTo, fileMd5);
    }
    return extract(zipFile, entryFile, extractTo, fileMd5, true);
}
 
Example #11
Source File: TinkerServerPatchListener.java    From tinkerpatch-sdk with MIT License 5 votes vote down vote up
/**
 * 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);

    //把这个添加到你的PatchListener实现中
    String patchMd5 = SharePatchFileUtil.getMD5(patchFile);
    TinkerServerManager.reportTinkerPatchListenerFail(returnCode, patchMd5);
    return returnCode;
}
 
Example #12
Source File: TinkerServerManager.java    From tinkerpatch-sdk with MIT License 5 votes vote down vote up
/**
 * 上报补丁合成情况
 * @param patchResult
 */
public static void reportTinkerPatchFail(PatchResult patchResult) {
    if (sTinkerServerClient == null) {
        TinkerLog.e(TAG, "reportTinkerPatchFail, sTinkerServerClient == null");
        return;
    }
    if (patchResult == null) {
        TinkerLog.e(TAG, "reportTinkerPatchFail, patchResult == null");
        return;
    }

    if (patchResult.isSuccess) {
        TinkerLog.i(TAG, "reportTinkerPatchFail, patch success, just return");
        return;
    }
    String patchMd5 = (patchResult.patchVersion != null)
        ? patchResult.patchVersion : SharePatchFileUtil.getMD5(new File(patchResult.rawPatchFilePath));

    if (!patchMd5.equals(sTinkerServerClient.getCurrentPatchMd5())) {
        TinkerLog.e(TAG, "reportTinkerPatchFail, md5 not equal, patchMd5:%s, currentPatchMd5:%s",
            patchMd5, sTinkerServerClient.getCurrentPatchMd5()
        );
        return;
    }
    sTinkerServerClient.reportPatchFail(
        sTinkerServerClient.getCurrentPatchVersion(),
        DefaultPatchRequestCallback.ERROR_PATCH_FAIL
    );
}
 
Example #13
Source File: UrlConnectionStreamFetcher.java    From tinkerpatch-sdk with MIT License 5 votes vote down vote up
@Override
public void run() {
    InputStream inputStream = null;
    try {
        HttpURLConnection conn = (HttpURLConnection) url.toURL().openConnection();
        conn.setRequestMethod(url.getMethod());
        conn.setDoOutput(true);
        conn.setReadTimeout(10000 /* milliseconds */);
        conn.setConnectTimeout(15000 /* milliseconds */);
        conn.setInstanceFollowRedirects(false);
        conn.setUseCaches(false);
        for (Map.Entry<String, String> entry : url.getHeaders().entrySet()) {
            conn.setRequestProperty(entry.getKey(), entry.getValue());
        }
        switch (url.getMethod()) {
            case "GET":
                break;
            case "POST":
                OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), ServerUtils.CHARSET);
                writer.write(url.getBody());
                writer.flush();
                writer.close();
                break;
            default:
                throw new RuntimeException("Unsupported request method" + url.getMethod());
        }
        conn.connect();
        TinkerLog.d(TAG, "response code " + conn.getResponseCode() + " msg: " + conn.getResponseMessage());
        inputStream = conn.getInputStream();
        this.callback.onDataReady(inputStream);
    } catch (IOException e) {
        e.printStackTrace();
        this.callback.onLoadFailed(e);
    } finally {
        SharePatchFileUtil.closeQuietly(inputStream);
    }
}
 
Example #14
Source File: TinkerServerResultService.java    From tinkerpatch-sdk with MIT License 4 votes vote down vote up
@Override
public void onPatchResult(final PatchResult result) {
    if (result == null) {
        TinkerLog.e(TAG, "received null result!!!!");
        return;
    }
    TinkerLog.i(TAG, "receive result: %s", result.toString());

    //first, we want to kill the recover process
    TinkerServiceInternals.killTinkerPatchServiceProcess(getApplicationContext());
    TinkerServerManager.reportTinkerPatchFail(result);

    if (result.isSuccess) {
        TinkerLog.i(TAG, "patch success, please restart process");
        File rawFile = new File(result.rawPatchFilePath);
        if (rawFile.exists()) {
            TinkerLog.i(TAG, "save delete raw patch file");
            SharePatchFileUtil.safeDeleteFile(rawFile);
        }
        //not like TinkerResultService, I want to restart just when I am at background!
        //if you have not install tinker this moment, you can use TinkerApplicationHelper api
        if (checkIfNeedKill(result)) {
            if (TinkerServerUtils.isBackground()) {
                TinkerLog.i(TAG, "it is in background, just restart process");
                restartProcess();
            } else {
                //we can wait process at background, such as onAppBackground
                //or we can restart when the screen off
                TinkerLog.i(TAG, "tinker wait screen to restart process");
                new TinkerServerUtils.ScreenState(
                    getApplicationContext(), new TinkerServerUtils.IOnScreenOff() {
                    @Override
                    public void onScreenOff() {
                        restartProcess();
                    }
                });
            }
        } else {
            TinkerLog.i(TAG, "I have already install the newly patch version!");
        }
    } else {
        TinkerLog.i(TAG, "patch fail, please check reason");
    }

    //repair current patch fail, just clean!
    if (!result.isSuccess) {
        //if you have not install tinker this moment, you can use TinkerApplicationHelper api
        Tinker.with(getApplicationContext()).cleanPatch();
    }
}