提交 00486b79 编写于 作者: N neighbWang 提交者: Johnson Lee

WebView optimization

上级 3cc21ae1
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
dependencies {
compileOnly project(':booster-android-api')
compile project(':booster-android-instrument')
}
\ No newline at end of file
package com.didiglobal.booster.instrument;
import android.app.Application;
import android.os.MessageQueue;
import android.os.SystemClock;
import android.util.Log;
import static com.didiglobal.booster.android.bugfix.Constants.TAG;
import static com.didiglobal.booster.android.bugfix.Reflection.invokeMethod;
import static com.didiglobal.booster.android.bugfix.Reflection.invokeStaticMethod;
/**
* @author neighbWang
*/
public class ShadowWebView {
public static void preloadWebView(final Application app) {
try {
app.getMainLooper().getQueue().addIdleHandler(new MessageQueue.IdleHandler() {
@Override
public boolean queueIdle() {
startChromiumEngine();
return false;
}
});
} catch (final Throwable t) {
Log.e(TAG, "Oops!", t);
}
}
private static void startChromiumEngine() {
try {
final long t0 = SystemClock.uptimeMillis();
final Object provider = invokeStaticMethod(Class.forName("android.webkit.WebViewFactory"), "getProvider");
invokeMethod(provider, "startYourEngines", new Class[]{boolean.class}, new Object[]{true});
Log.i(TAG, "Start chromium engine complete: " + (SystemClock.uptimeMillis() - t0) + " ms");
} catch (final Throwable t) {
Log.e(TAG, "Start chromium engine error", t);
}
}
}
\ No newline at end of file
......@@ -6,4 +6,5 @@ dependencies {
compile project(':booster-transform-toast')
compile project(':booster-transform-usage')
compile project(':booster-transform-media-player')
compile project(':booster-transform-webview')
}
apply from: '../gradle/booster.gradle'
dependencies {
kapt "com.google.auto.service:auto-service:1.0-rc4"
implementation project(':booster-android-gradle-api')
implementation project(':booster-task-spi')
implementation project(':booster-transform-asm')
compileOnly 'com.android.tools.build:gradle:3.0.0'
testCompileOnly 'com.android.tools.build:gradle:3.0.0'
}
package com.didiglobal.booster.transform.webview
import com.didiglobal.booster.kotlinx.file
import com.didiglobal.booster.kotlinx.touch
import com.didiglobal.booster.transform.ArtifactManager
import com.didiglobal.booster.transform.TransformContext
import com.didiglobal.booster.transform.asm.ClassTransformer
import com.didiglobal.booster.transform.asm.className
import com.didiglobal.booster.transform.asm.findAll
import com.didiglobal.booster.util.ComponentHandler
import com.google.auto.service.AutoService
import org.objectweb.asm.Opcodes.ACC_PUBLIC
import org.objectweb.asm.Opcodes.ALOAD
import org.objectweb.asm.Opcodes.ATHROW
import org.objectweb.asm.Opcodes.INVOKESPECIAL
import org.objectweb.asm.Opcodes.INVOKESTATIC
import org.objectweb.asm.Opcodes.RETURN
import org.objectweb.asm.tree.ClassNode
import org.objectweb.asm.tree.InsnList
import org.objectweb.asm.tree.InsnNode
import org.objectweb.asm.tree.MethodInsnNode
import org.objectweb.asm.tree.MethodNode
import org.objectweb.asm.tree.VarInsnNode
import java.io.PrintWriter
import javax.xml.parsers.SAXParserFactory
/**
* Represents a class transformer for application optimization
*
* @author neighbWang
*/
@AutoService(ClassTransformer::class)
class WebViewTransformer : ClassTransformer {
private lateinit var logger: PrintWriter
private val applications = mutableSetOf<String>()
override fun onPreTransform(context: TransformContext) {
val parser = SAXParserFactory.newInstance().newSAXParser()
context.artifacts.get(ArtifactManager.MERGED_MANIFESTS).forEach { manifest ->
val handler = ComponentHandler()
parser.parse(manifest, handler)
applications.addAll(handler.applications)
}
this.logger = context.reportsDir.file(Build.ARTIFACT).file(context.name).file("report.txt").touch().printWriter()
}
override fun onPostTransform(context: TransformContext) {
this.logger.close()
}
override fun transform(context: TransformContext, klass: ClassNode): ClassNode {
if (!this.applications.contains(klass.className)) {
return klass
}
val method = klass.methods?.find {
"${it.name}${it.desc}" == "onCreate()V"
} ?: klass.defaultOnCreate()
method.instructions?.let { insn ->
insn.findAll(RETURN, ATHROW).forEach { ret ->
insn.insertBefore(ret, VarInsnNode(ALOAD, 0))
insn.insertBefore(ret, MethodInsnNode(INVOKESTATIC, SHADOW_WEBVIEW, "preloadWebView", "(Landroid/app/Application;)V", false))
logger.println(" + $SHADOW_WEBVIEW.preloadWebView(Landroid/app/Application;)V before @${if (ret.opcode == ATHROW) "athrow" else "return"}: ${klass.name}.${method.name}${method.desc} ")
}
}
return klass
}
}
private fun ClassNode.defaultOnCreate(): MethodNode = MethodNode(ACC_PUBLIC, "onCreate", "()V", null, null).apply {
maxStack = 1
instructions.add(InsnList().apply {
add(VarInsnNode(ALOAD, 0))
add(MethodInsnNode(INVOKESPECIAL, superName, name, desc, false))
add(InsnNode(RETURN))
})
methods?.add(this)
}
private const val SHADOW_WEBVIEW = "com/didiglobal/booster/instrument/ShadowWebView"
\ No newline at end of file
package com.didiglobal.booster.transform.webview
import com.android.build.gradle.api.BaseVariant
import com.didiglobal.booster.gradle.scope
import com.didiglobal.booster.task.spi.VariantProcessor
import com.google.auto.service.AutoService
/**
* @author neighbWang
*/
@AutoService(VariantProcessor::class)
class WebViewVariantProcessor : VariantProcessor {
override fun process(variant: BaseVariant) {
variant.scope.globalScope.project.dependencies.add(
"implementation",
"${Build.GROUP}:booster-android-instrument-webview:${Build.VERSION}"
)
}
}
\ No newline at end of file
......@@ -5,6 +5,7 @@ include ':booster-android-instrument-media-player'
include ':booster-android-instrument-shared-preferences'
include ':booster-android-instrument-thread'
include ':booster-android-instrument-toast'
include ':booster-android-instrument-webview'
include ':booster-android-gradle-api'
include ':booster-android-gradle-v3_0'
include ':booster-android-gradle-v3_2'
......@@ -28,4 +29,5 @@ include ':booster-transform-toast'
include ':booster-transform-usage'
include ':booster-transform-util'
include ':booster-kotlinx'
include ':booster-transform-webview'
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册