自动生成TinkerApplication
接入 Tinker 第一步就是改造 Application 。官方推荐是利用 @DefaultLifeCycle 动态生成 Application
@DefaultLifeCycle(application = "tinker.sample.android.app.SampleApplication",
flags = ShareConstants.TINKER_ENABLE_ALL,
loadVerifyFlag = false)
public class SampleApplicationLike extends DefaultApplicationLike {
}
那我们来解析一下 Tinker 是如何生成 Application 以及在 Application 中做了什么事?
看到 @DefaultLifeCycle 注解,我们可想而知应该是经过 processor 处理后动态生成了 Application 。
查看 Tinker 工程可以发现在 tinker-android-anno 下面有一个 AnnotationProcessor。
private void processDefaultLifeCycle(Set<? extends Element> elements) {
// DefaultLifeCycle
for (Element e : elements) {
DefaultLifeCycle ca = e.getAnnotation(DefaultLifeCycle.class);
String lifeCycleClassName = ((TypeElement) e).getQualifiedName().toString();
String lifeCyclePackageName = lifeCycleClassName.substring(0, lifeCycleClassName.lastIndexOf('.'));
lifeCycleClassName = lifeCycleClassName.substring(lifeCycleClassName.lastIndexOf('.') + 1);
String applicationClassName = ca.application();
if (applicationClassName.startsWith(".")) {
applicationClassName = lifeCyclePackageName + applicationClassName;
}
String applicationPackageName = applicationClassName.substring(0, applicationClassName.lastIndexOf('.'));
applicationClassName = applicationClassName.substring(applicationClassName.lastIndexOf('.') + 1);
String loaderClassName = ca.loaderClass();
if (loaderClassName.startsWith(".")) {
loaderClassName = lifeCyclePackageName + loaderClassName;
}
final InputStream is = AnnotationProcessor.class.getResourceAsStream(APPLICATION_TEMPLATE_PATH);
final Scanner scanner = new Scanner(is);
final String template = scanner.useDelimiter("\\A").next();
final String fileContent = template
.replaceAll("%PACKAGE%", applicationPackageName) //包名
.replaceAll("%APPLICATION%", applicationClassName)
.replaceAll("%APPLICATION_LIFE_CYCLE%", lifeCyclePackageName + "." + lifeCycleClassName)
.replaceAll("%TINKER_FLAGS%", "" + ca.flags())
.replaceAll("%TINKER_LOADER_CLASS%", "" + loaderClassName)
.replaceAll("%TINKER_LOAD_VERIFY_FLAG%", "" + ca.loadVerifyFlag())
.replaceAll("%TINKER_USE_DLC%", "" + ca.useDelegateLastClassLoader());
try {
JavaFileObject fileObject = processingEnv.getFiler().createSourceFile(applicationPackageName + "." + applicationClassName);
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Creating " + fileObject.toUri());
Writer writer = fileObject.openWriter();
try {
PrintWriter pw = new PrintWriter(writer);
pw.print(fileContent);
pw.flush();
} finally {
writer.close();
}
} catch (IOException x) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, x.toString());
}
}
}
整个 processDefaultLifeCycle 方法看下来,其实主要在做的就是去读取一份模版,然后用注解中设置的值替换里面的一些占位符。这个模版就是 resouces/TinkerAnnoApplication.tmpl
package %PACKAGE%;
import com.tencent.tinker.loader.app.TinkerApplication;
/**
*
* Generated application for tinker life cycle
*
*/
public class %APPLICATION% extends TinkerApplication {
public %APPLICATION%() {
super(%TINKER_FLAGS%, "%APPLICATION_LIFE_CYCLE%", "%TINKER_LOADER_CLASS%", %TINKER_LOAD_VERIFY_FLAG%, %TINKER_USE_DLC%);
}
}
最终生成的 SampleApplication:
public class SampleApplication extends TinkerApplication {
public SampleApplication() {
super(15, "tinker.sample.android.app.SampleApplicationLike", "com.tencent.tinker.loader.TinkerLoader", false);
}
}
解析TinkerApplication
TinkerApplication的构造函数
protected TinkerApplication(int tinkerFlags, String delegateClassName,
String loaderClassName, boolean tinkerLoadVerifyFlag) {
this.tinkerFlags = tinkerFlags;
this.delegateClassName = delegateClassName; //代理类
this.loaderClassName = loaderClassName;//
this.tinkerLoadVerifyFlag = tinkerLoadVerifyFlag;
}
attachBaseContext()
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
final long applicationStartElapsedTime = SystemClock.elapsedRealtime();
final long applicationStartMillisTime = System.currentTimeMillis();
Thread.setDefaultUncaughtExceptionHandler(new TinkerUncaughtHandler(this));
onBaseContextAttached(base, applicationStartElapsedTime, applicationStartMillisTime);
}
onBaseContextAttached()
protected void onBaseContextAttached(Context base, long applicationStartElapsedTime, long applicationStartMillisTime) {
try {
loadTinker(); //加载Tinker
mCurrentClassLoader = base.getClassLoader();//获取ClassLoader
//创建Handler实例
mInlineFence = createInlineFence(this, tinkerFlags, delegateClassName,
tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime,
tinkerResultIntent);
//发送消息
TinkerInlineFenceAction.callOnBaseContextAttached(mInlineFence, base);
//reset save mode
if (useSafeMode) {
ShareTinkerInternals.setSafeModeCount(this, 0);
}
} catch (TinkerRuntimeException e) {
throw e;
} catch (Throwable thr) {
throw new TinkerRuntimeException(thr.getMessage(), thr);
}
}
loadTinker()
private void loadTinker() {
try {
//reflect tinker loader, because loaderClass may be define by user!
//创建TinkerLoader
Class<?> tinkerLoadClass = Class.forName(loaderClassName, false, TinkerApplication.class.getClassLoader());
//获取tryLoad方法
Method loadMethod = tinkerLoadClass.getMethod(TINKER_LOADER_METHOD, TinkerApplication.class);
Constructor<?> constructor = tinkerLoadClass.getConstructor();
//执行tryLoad方法
tinkerResultIntent = (Intent) loadMethod.invoke(constructor.newInstance(), this);
} catch (Throwable e) {
//has exception, put exception error code
tinkerResultIntent = new Intent();
ShareIntentUtil.setIntentReturnCode(tinkerResultIntent, ShareConstants.ERROR_LOAD_PATCH_UNKNOWN_EXCEPTION);
tinkerResultIntent.putExtra(INTENT_PATCH_EXCEPTION, e);
}
}
createInlineFence()
private Handler createInlineFence(Application app,
int tinkerFlags,
String delegateClassName,
boolean tinkerLoadVerifyFlag,
long applicationStartElapsedTime,
long applicationStartMillisTime,
Intent resultIntent) {
try {
// Use reflection to create the delegate so it doesn't need to go into the primary dex.
// And we can also patch it
//反射获取代理类
final Class<?> delegateClass = Class.forName(delegateClassName, false, mCurrentClassLoader);
//获取代理类的构造函数
final Constructor<?> constructor = delegateClass.getConstructor(Application.class, int.class, boolean.class,
long.class, long.class, Intent.class);
//创建代理类实例
final Object appLike = constructor.newInstance(app, tinkerFlags, tinkerLoadVerifyFlag,
applicationStartElapsedTime, applicationStartMillisTime, resultIntent);
//反射获取TinkerApplicationInlineFence Class
final Class<?> inlineFenceClass = Class.forName(
"com.tencent.tinker.entry.TinkerApplicationInlineFence", false, mCurrentClassLoader);
//获取ApplicationLike
final Class<?> appLikeClass = Class.forName(
"com.tencent.tinker.entry.ApplicationLike", false, mCurrentClassLoader);
final Constructor<?> inlineFenceCtor = inlineFenceClass.getConstructor(appLikeClass);
inlineFenceCtor.setAccessible(true);
//创建TinkerApplicationInlineFence实例
return (Handler) inlineFenceCtor.newInstance(appLike);
} catch (Throwable thr) {
throw new TinkerRuntimeException("createInlineFence failed", thr);
}
}
TinkerApplicationInlineFence
TinkerApplicationInlineFence继承Handler。TinkerApplication的相应的生命周期会发送消息,然后在handleMessage中调用
ApplicationLike对应的声明周期。
@Keep
public final class TinkerApplicationInlineFence extends Handler {
private final ApplicationLike mAppLike;
public TinkerApplicationInlineFence(ApplicationLike appLike) {
mAppLike = appLike;
}
@Override
public void handleMessage(Message msg) {
handleMessage_$noinline$(msg);
}
private void handleMessage_$noinline$(Message msg) {
try {
dummyThrowExceptionMethod();
} finally {
handleMessageImpl(msg);
}
}
private void handleMessageImpl(Message msg) {
switch (msg.what) {
case ACTION_ON_BASE_CONTEXT_ATTACHED: {
mAppLike.onBaseContextAttached((Context) msg.obj);
break;
}
case ACTION_ON_CREATE: {
mAppLike.onCreate();
break;
}
case ACTION_ON_CONFIGURATION_CHANGED: {
mAppLike.onConfigurationChanged((Configuration) msg.obj);
break;
}
case ACTION_ON_TRIM_MEMORY: {
mAppLike.onTrimMemory((Integer) msg.obj);
break;
}
case ACTION_ON_LOW_MEMORY: {
mAppLike.onLowMemory();
break;
}
case ACTION_ON_TERMINATE: {
mAppLike.onTerminate();
break;
}
case ACTION_GET_CLASSLOADER: {
msg.obj = mAppLike.getClassLoader((ClassLoader) msg.obj);
break;
}
case ACTION_GET_BASE_CONTEXT: {
msg.obj = mAppLike.getBaseContext((Context) msg.obj);
break;
}
case ACTION_GET_ASSETS: {
msg.obj = mAppLike.getAssets((AssetManager) msg.obj);
break;
}
case ACTION_GET_RESOURCES : {
msg.obj = mAppLike.getResources((Resources) msg.obj);
break;
}
case ACTION_GET_SYSTEM_SERVICE : {
final Object[] params = (Object[]) msg.obj;
msg.obj = mAppLike.getSystemService((String) params[0], params[1]);
break;
}
case ACTION_MZ_NIGHTMODE_USE_OF: {
msg.obj = mAppLike.mzNightModeUseOf();
break;
}
default: {
throw new IllegalStateException("Should not be here.");
}
}
}
private static void dummyThrowExceptionMethod() {
if (TinkerApplicationInlineFence.class.isPrimitive()) {
throw new RuntimeException();
}
}
}
参考
- 微信Android热补丁实践演进之路
- 微信Tinker的一切都在这里,包括源码(一)
- ART下的方法内联策略及其对Android热修复方案的影响分析
- Tinker:技术的初心与坚持
- Tinker Dexdiff算法解析
- DexDiff格式查看工具
- Tinker源码分析(一):TinkerApplication
`