背景:Google对Instant Run一直有着持续的升级,部分前辈们介绍的东西发生了变化,故更新一下部分源码级别的分析。
参考:https://yq.aliyun.com/articles/202917
https://www.jianshu.com/p/5947855e3362
1、获取Server构造函数内初始化的serverSocket。打开Socket
private void handle(DataInputStream paramDataInputStream, DataOutputStream paramDataOutputStream)
throws IOException
{
long l = paramDataInputStream.readLong();
if (l != 890269988L)
{
Log.w("InstantRun", "Unrecognized header format " + Long.toHexString(l));
return;
}
int i = paramDataInputStream.readInt();
paramDataOutputStream.writeInt(4);
boolean bool1;
if (i != 4)
{
Log.w("InstantRun", "Mismatched protocol versions; app is using version 4 and tool is using version " + i);
return;
if (Restarter.getForegroundActivity(Server.this.context) == null) {
break label246;
}
bool1 = true;
paramDataOutputStream.writeBoolean(bool1);
if (Log.isLoggable("InstantRun", 2)) {
Log.v("InstantRun", "Received Ping message from the IDE; returned active = " + bool1);
}
}
for (;;)
{
i = paramDataInputStream.readInt();
label246:
Object localObject;
switch (i)
{
case 2:
default:
if (!Log.isLoggable("InstantRun", 6)) {
break;
}
Log.e("InstantRun", "Unexpected message type: " + i);
return;
case 7:
if (!Log.isLoggable("InstantRun", 2)) {
break;
}
Log.v("InstantRun", "Received EOF from the IDE");
return;
bool1 = false;
break;
case 3:
if (Log.isLoggable("InstantRun", 6)) {
Log.e("InstantRun", "Unexpected message type: " + i);
}
break;
case 4:
if (Log.isLoggable("InstantRun", 6)) {
Log.e("InstantRun", "Unexpected message type: " + i);
}
break;
case 5:
if (!authenticate(paramDataInputStream)) {
break;
}
localObject = Restarter.getForegroundActivity(Server.this.context);
if (localObject != null)
{
if (Log.isLoggable("InstantRun", 2)) {
Log.v("InstantRun", "Restarting activity per user request");
}
Restarter.restartActivityOnUiThread((Activity)localObject);
}
break;
case 1:
if (!authenticate(paramDataInputStream)) {
break;
}
localObject = ApplicationPatch.read(paramDataInputStream);
if (localObject != null)
{
bool1 = Server.hasResources((List)localObject);
i = paramDataInputStream.readInt();
i = Server.this.handlePatches((List)localObject, bool1, i);
boolean bool2 = paramDataInputStream.readBoolean();
paramDataOutputStream.writeBoolean(true);
Server.this.restart(i, bool1, bool2);
}
break;
case 6:
localObject = paramDataInputStream.readUTF();
Activity localActivity = Restarter.getForegroundActivity(Server.this.context);
if (localActivity != null) {
Restarter.showToast(localActivity, (String)localObject);
} else if (Log.isLoggable("InstantRun", 2)) {
Log.v("InstantRun", "Couldn't show toast (no activity) : " + (String)localObject);
}
break;
}
}
private int handleHotSwapPatch(int paramInt, ApplicationPatch paramApplicationPatch)
{
if (Log.isLoggable("InstantRun", 2)) {
Log.v("InstantRun", "Received incremental code patch");
}
for (;;)
{
try
{
paramApplicationPatch = FileManager.writeTempDexFile(paramApplicationPatch.getBytes()); //将patch文件写入临时存放目录,以为 dex-temp命名
if (paramApplicationPatch == null)
{
Log.e("InstantRun", "No file to write the code to");
return paramInt;
}
if (Log.isLoggable("InstantRun", 2)) {
Log.v("InstantRun", "Reading live code from " + paramApplicationPatch);
}
localObject = FileManager.getNativeLibraryFolder().getPath();
localObject = Class.forName("com.android.tools.fd.runtime.AppPatchesLoaderImpl", true, new DexClassLoader(paramApplicationPatch, this.context.getCacheDir().getPath(), (String)localObject, getClass().getClassLoader()));
}
catch (Throwable paramApplicationPatch)
{
Object localObject;
boolean bool;
Log.e("InstantRun", "Couldn't apply code changes", paramApplicationPatch);
paramInt = 3;
continue;
}
try
{
if (Log.isLoggable("InstantRun", 2)) {
Log.v("InstantRun", "Got the patcher class " + localObject);
}
paramApplicationPatch = (PatchesLoader)((Class)localObject).newInstance();
if (Log.isLoggable("InstantRun", 2)) {
Log.v("InstantRun", "Got the patcher instance " + paramApplicationPatch);
}
localObject = (String[])((Class)localObject).getDeclaredMethod("getPatchedClasses", new Class[0]).invoke(paramApplicationPatch, new Object[0]);
if (Log.isLoggable("InstantRun", 2))
{
Log.v("InstantRun", "Got the list of classes ");
int j = localObject.length;
int i = 0;
if (i < j)
{
String str = localObject[i];
Log.v("InstantRun", "class " + str);
i += 1;
continue;
}
}
bool = paramApplicationPatch.load();
if (!bool) {
paramInt = 3;
}
}
catch (Exception paramApplicationPatch)
{
Log.e("InstantRun", "Couldn't apply code changes", paramApplicationPatch);
paramApplicationPatch.printStackTrace();
paramInt = 3;
}
}
return paramInt;
}
PS:相关后续问题
1、源码地址 :https://android.googlesource.com/platform/tools/base/+/studio-master-dev/instant-run/
2、能否通过改变dex再打包成jar以验证?Log.v 能打出来么?
3、resource.ap_ 这个 和 resource.arsc文件有何不同?
4、新版本为何去掉了 BootstrapApplication Service Instant_run.zip这套东西。