Java源码示例:com.tencent.tinker.lib.tinker.Tinker
示例1
public static boolean tryRecoverDexFiles(Tinker manager, ShareSecurityCheck checker, Context context,
String patchVersionDirectory, File patchFile) {
if (!manager.isEnabledForDex()) {
TinkerLog.w(TAG, "patch recover, dex is not enabled");
return true;
}
String dexMeta = checker.getMetaContentMap().get(DEX_META_FILE);
if (dexMeta == null) {
TinkerLog.w(TAG, "patch recover, dex is not contained");
return true;
}
long begin = SystemClock.elapsedRealtime();
boolean result = patchDexExtractViaDexDiff(context, patchVersionDirectory, dexMeta, patchFile);
long cost = SystemClock.elapsedRealtime() - begin;
TinkerLog.i(TAG, "recover dex result:%b, cost:%d", result, cost);
return result;
}
示例2
public static boolean tryRecoverLibraryFiles(Tinker manager, ShareSecurityCheck checker, Context context,
String patchVersionDirectory, File patchFile) {
if (!manager.isEnabledForNativeLib()) {
TinkerLog.w(TAG, "patch recover, library is not enabled");
return true;
}
String libMeta = checker.getMetaContentMap().get(SO_META_FILE);
if (libMeta == null) {
TinkerLog.w(TAG, "patch recover, library is not contained");
return true;
}
long begin = SystemClock.elapsedRealtime();
boolean result = patchLibraryExtractViaBsDiff(context, patchVersionDirectory, libMeta, patchFile);
long cost = SystemClock.elapsedRealtime() - begin;
TinkerLog.i(TAG, "recover lib result:%b, cost:%d", result, cost);
return result;
}
示例3
public static boolean tryRecoverResourceFiles(Tinker manager, ShareSecurityCheck checker, Context context,
String patchVersionDirectory, File patchFile) {
if (!manager.isEnabledForResource()) {
TinkerLog.w(TAG, "patch recover, resource is not enabled");
return true;
}
String resourceMeta = checker.getMetaContentMap().get(RES_META_FILE);
if (resourceMeta == null || resourceMeta.length() == 0) {
TinkerLog.w(TAG, "patch recover, resource is not contained");
return true;
}
long begin = SystemClock.elapsedRealtime();
boolean result = patchResourceExtractViaResourceDiff(context, patchVersionDirectory, resourceMeta, patchFile);
long cost = SystemClock.elapsedRealtime() - begin;
TinkerLog.i(TAG, "recover resource result:%b, cost:%d", result, cost);
return result;
}
示例4
/**
* 初始化 TinkerServer 实例
* @param context context
* @param tinker {@link Tinker} 实例
* @param hours 访问服务器的时间间隔, 单位为小时, 应为 >= 0
* @param appKey 从Tinkerpatch中得到的appKey
* @param appVersion 在Tinkerpatch中填写的appVersion
* @param channel 发布的渠道名称,由于GooglePlay渠道的政策限制,我们会停止所有channel中含有google关键字的动态下发功能。
*/
public static void installTinkerServer(
Context context,
Tinker tinker,
int hours,
String appKey,
String appVersion,
String channel
) {
installTinkerServer(
context,
tinker,
hours,
appKey,
appVersion,
channel,
new TinkerServerPatchRequestCallback()
);
}
示例5
/**
* 检查服务器是否有补丁更新
* @param immediately 是否立刻检查,忽略时间间隔限制
*/
public static void checkTinkerUpdate(final boolean immediately) {
if (sTinkerServerClient == null) {
TinkerLog.e(TAG, "checkTinkerUpdate, sTinkerServerClient == null");
return;
}
Tinker tinker = sTinkerServerClient.getTinker();
//only check at the main process
if (tinker.isMainProcess()) {
Looper.getMainLooper().myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
@Override public boolean queueIdle() {
sTinkerServerClient.checkTinkerUpdate(immediately);
return false;
}
});
}
}
示例6
/**
* 向服务器请求在线参数信息
* @param configRequestCallback
* @param immediately 是否立刻请求,忽略时间间隔限制
*/
public static void getDynamicConfig(final ConfigRequestCallback configRequestCallback, final boolean immediately) {
if (sTinkerServerClient == null) {
TinkerLog.e(TAG, "checkTinkerUpdate, sTinkerServerClient == null");
return;
}
Tinker tinker = sTinkerServerClient.getTinker();
//only check at the main process
if (tinker.isMainProcess()) {
Looper.getMainLooper().myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
@Override public boolean queueIdle() {
sTinkerServerClient.getDynamicConfig(configRequestCallback, immediately);
return false;
}
});
}
}
示例7
public void show_info(View view) {
// 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(this);
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(this);
builder.setCancelable(true);
builder.setView(v);
final AlertDialog alert = builder.create();
alert.show();
}
示例8
private void initTinker(Context base) {
// tinker需要你开启MultiDex
MultiDex.install(base);
TinkerManager.setTinkerApplicationLike(this);
// 设置全局异常捕获
TinkerManager.initFastCrashProtect();
//开启升级重试功能(在安装Tinker之前设置)
TinkerManager.setUpgradeRetryEnable(true);
//设置Tinker日志输出类
TinkerInstaller.setLogIml(new MyLogImp());
//安装Tinker(在加载完multiDex之后,否则你需要将com.tencent.tinker.**手动放到main dex中)
TinkerManager.installTinker(this);
mTinker = Tinker.with(getApplication());
}
示例9
/**
* 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);
}
示例10
@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;
}
示例11
@Override
public boolean beforePatchRequest() {
boolean result = super.beforePatchRequest();
if (result) {
TinkerServerClient client = TinkerServerClient.get();
Tinker tinker = client.getTinker();
Context context = client.getContext();
if (!tinker.isMainProcess()) {
TinkerLog.e(TAG, "beforePatchRequest, only request on the main process");
return false;
}
if (TinkerServerManager.isGooglePlayChannel()) {
TinkerLog.e(TAG, "beforePatchRequest, google play channel, return false");
return false;
}
// main process must be the newly version
// check whether it is pending work
String currentPatchMd5 = client.getCurrentPatchMd5();
TinkerLoadResult tinkerLoadResult = tinker.getTinkerLoadResultIfPresent();
if (tinkerLoadResult.currentVersion == null || !currentPatchMd5.equals(tinkerLoadResult.currentVersion)) {
Integer version = client.getCurrentPatchVersion();
if (version > 0) {
File patchFile = ServerUtils.getServerFile(
context, client.getAppVersion(), String.valueOf(version)
);
if (patchFile.exists() && patchFile.isFile() && handlePatchFile(context, version, patchFile)) {
return false;
}
}
}
}
return result;
}
示例12
/**
* 初始化 TinkerServer 实例
* @param context context
* @param tinker {@link Tinker} 实例
* @param hours 访问服务器的时间间隔, 单位为小时, 应为 >= 0
* @param appKey 从Tinkerpatch中得到的appKey
* @param appVersion 在Tinkerpatch中填写的appVersion
* @param channel 发布的渠道名称,由于GooglePlay渠道的政策限制,我们会停止所有channel中含有google关键字的动态下发功能。
* @param patchRequestCallback {@link PatchRequestCallback} patch请求的callback
*/
public static void installTinkerServer(
Context context,
Tinker tinker,
int hours,
String appKey,
String appVersion,
String channel,
PatchRequestCallback patchRequestCallback
) {
final boolean debug = Debugger.getInstance(context).isDebug();
TinkerLog.i(TAG, String.format("installTinkerServer, debug value: %s appVersion: %s, channel: %s",
String.valueOf(debug), appVersion, channel)
);
sTinkerServerClient = TinkerServerClient.init(
context,
tinker,
appKey,
appVersion,
debug,
patchRequestCallback
);
// add channel condition
sTinkerServerClient.updateTinkerCondition(CONDITION_CHANNEL, channel);
sTinkerServerClient.setCheckIntervalByHours(hours);
TinkerServerManager.channel = channel;
}
示例13
public void rollbackPatchDirectly() {
TinkerServerClient client = TinkerServerClient.get();
final Context context = client.getContext();
final Tinker tinker = client.getTinker();
//restart now
tinker.cleanPatch();
ShareTinkerInternals.killAllOtherProcess(context);
android.os.Process.killProcess(android.os.Process.myPid());
}
示例14
public TinkerServerClient(Context context, Tinker tinker, String appKey,
String appVersion, Boolean debug, PatchRequestCallback patchRequestCallback) {
this.tinker = tinker;
this.context = context;
this.clientAPI = TinkerClientAPI.init(context, appKey, appVersion, debug);
this.patchRequestCallback = patchRequestCallback;
makeDefaultConditions();
}
示例15
/**
* 初始化 TinkerPatch 的 SDK, 使用默认的 {@link DefaultPatchRequestCallback}
* @param context
* @param tinker
* @param appKey
* @param appVersion
* @param debug
* @return
*/
public static TinkerServerClient init(Context context, Tinker tinker,
String appKey, String appVersion, Boolean debug) {
if (client == null) {
synchronized (TinkerClientAPI.class) {
if (client == null) {
client = new TinkerServerClient(context, tinker, appKey,
appVersion, debug, new DefaultPatchRequestCallback());
}
}
}
return client;
}
示例16
/**
* 初始化 TinkerPatch 的 SDK, 使用自定义的 {@link PatchRequestCallback}
* @param context
* @param tinker
* @param appKey
* @param appVersion
* @param debug
* @param patchRequestCallback
* @return
*/
public static TinkerServerClient init(Context context, Tinker tinker, String appKey,
String appVersion, Boolean debug, PatchRequestCallback patchRequestCallback) {
if (client == null) {
synchronized (TinkerClientAPI.class) {
if (client == null) {
client = new TinkerServerClient(context, tinker, appKey, appVersion, debug, patchRequestCallback);
}
}
}
return client;
}
示例17
public void uninstall_patch(View view) {
ShareTinkerInternals.killAllOtherProcess(getApplicationContext());
Tinker.with(getApplicationContext()).cleanPatch();
}
示例18
@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();
}
}
示例19
public Tinker getTinker() {
return tinker;
}