From e8cbf23f3bea6fbb67ca5bb20b458c70ae82b6fc Mon Sep 17 00:00:00 2001 From: qiyi Date: Thu, 7 Dec 2017 21:58:14 +0800 Subject: [PATCH 01/13] add arouter-auto-register plug-in: Automatically registration routers,providers and interceptors by generating bytecode. --- .../android/arouter/core/LogisticsCenter.java | 126 +++++++++++++---- arouter-auto-register/build.gradle | 15 ++ .../RouterRegisterCodeGenerator.groovy | 132 ++++++++++++++++++ .../register/RouterRegisterPlugin.groovy | 34 +++++ .../register/RouterRegisterSetting.groovy | 58 ++++++++ .../register/RouterRegisterTransform.groovy | 124 ++++++++++++++++ .../android/register/RouterScanUtil.groovy | 90 ++++++++++++ .../arouter-auto-register.properties | 1 + settings.gradle | 3 +- 9 files changed, 555 insertions(+), 28 deletions(-) create mode 100644 arouter-auto-register/build.gradle create mode 100644 arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterCodeGenerator.groovy create mode 100644 arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterPlugin.groovy create mode 100644 arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterSetting.groovy create mode 100644 arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterTransform.groovy create mode 100644 arouter-auto-register/src/main/groovy/com/billy/android/register/RouterScanUtil.groovy create mode 100644 arouter-auto-register/src/main/resources/META-INF/gradle-plugins/arouter-auto-register.properties diff --git a/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java b/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java index ae020424..85115d9d 100644 --- a/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java +++ b/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java @@ -52,6 +52,71 @@ public class LogisticsCenter { private static Context mContext; static ThreadPoolExecutor executor; + private static boolean registerByPlugin; + + /** + * arouter-auto-register plugin will generate code inside this method + * call this method to register all Routers, Interceptors and Providers + * @author billy.qi Contact me. + * @since 2017-12-06 + */ + private static void loadRouterMap() { + registerByPlugin = false; + //auto generate register code by gradle plugin: arouter-auto-register + // looks like below: + // registerRouteRoot(new ARouter..Root..modulejava()); + // registerRouteRoot(new ARouter..Root..modulekotlin()); + } + + /** + * method for arouter-auto-register plugin to register Routers + * @param routeRoot IRouteRoot implementation class in the package: com.alibaba.android.arouter.core.routers + * @author billy.qi Contact me. + * @since 2017-12-06 + */ + private static void registerRouteRoot(IRouteRoot routeRoot) { + markRegisteredByPlugin(); + if (routeRoot != null) { + routeRoot.loadInto(Warehouse.groupsIndex); + } + } + + /** + * method for arouter-auto-register plugin to register Interceptors + * @param interceptorGroup IInterceptorGroup implementation class in the package: com.alibaba.android.arouter.core.routers + * @author billy.qi Contact me. + * @since 2017-12-06 + */ + private static void registerInterceptor(IInterceptorGroup interceptorGroup) { + markRegisteredByPlugin(); + if (interceptorGroup != null) { + interceptorGroup.loadInto(Warehouse.interceptorsIndex); + } + } + + /** + * method for arouter-auto-register plugin to register Providers + * @param providerGroup IProviderGroup implementation class in the package: com.alibaba.android.arouter.core.routers + * @author billy.qi Contact me. + * @since 2017-12-06 + */ + private static void registerProvider(IProviderGroup providerGroup) { + markRegisteredByPlugin(); + if (providerGroup != null) { + providerGroup.loadInto(Warehouse.providersIndex); + } + } + + /** + * mark already registered by arouter-auto-register plugin + * @author billy.qi Contact me. + * @since 2017-12-06 + */ + private static void markRegisteredByPlugin() { + if (!registerByPlugin) { + registerByPlugin = true; + } + } /** * LogisticsCenter init, load all metas in memory. Demand initialization @@ -62,36 +127,43 @@ public synchronized static void init(Context context, ThreadPoolExecutor tpe) th try { long startInit = System.currentTimeMillis(); - Set routerMap; - - // It will rebuild router map every times when debuggable. - if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) { - logger.info(TAG, "Run with debug mode or new install, rebuild router map."); - // These class was generate by arouter-compiler. - routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE); - if (!routerMap.isEmpty()) { - context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).edit().putStringSet(AROUTER_SP_KEY_MAP, routerMap).apply(); + //billy.qi modified at 2017-12-06 + //load by plugin first + loadRouterMap(); + if (registerByPlugin) { + logger.info(TAG, "Load router map by arouter-auto-register plugin."); + } else { + Set routerMap; + + // It will rebuild router map every times when debuggable. + if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) { + logger.info(TAG, "Run with debug mode or new install, rebuild router map."); + // These class was generate by arouter-compiler. + routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE); + if (!routerMap.isEmpty()) { + context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).edit().putStringSet(AROUTER_SP_KEY_MAP, routerMap).apply(); + } + + PackageUtils.updateVersion(context); // Save new version name when router map update finish. + } else { + logger.info(TAG, "Load router map from cache."); + routerMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet())); } - PackageUtils.updateVersion(context); // Save new version name when router map update finish. - } else { - logger.info(TAG, "Load router map from cache."); - routerMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet())); - } + logger.info(TAG, "Find router map finished, map size = " + routerMap.size() + ", cost " + (System.currentTimeMillis() - startInit) + " ms."); + startInit = System.currentTimeMillis(); - logger.info(TAG, "Find router map finished, map size = " + routerMap.size() + ", cost " + (System.currentTimeMillis() - startInit) + " ms."); - startInit = System.currentTimeMillis(); - - for (String className : routerMap) { - if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) { - // This one of root elements, load root. - ((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex); - } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) { - // Load interceptorMeta - ((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex); - } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) { - // Load providerIndex - ((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex); + for (String className : routerMap) { + if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) { + // This one of root elements, load root. + ((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex); + } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) { + // Load interceptorMeta + ((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex); + } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) { + // Load providerIndex + ((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex); + } } } diff --git a/arouter-auto-register/build.gradle b/arouter-auto-register/build.gradle new file mode 100644 index 00000000..a14d6b39 --- /dev/null +++ b/arouter-auto-register/build.gradle @@ -0,0 +1,15 @@ +apply plugin: 'groovy' + +dependencies { + compile gradleApi() + compile localGroovy() +} + +repositories { + mavenCentral() +} +dependencies { + compile 'com.android.tools.build:gradle:2.2.0' +} + + diff --git a/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterCodeGenerator.groovy b/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterCodeGenerator.groovy new file mode 100644 index 00000000..da15da41 --- /dev/null +++ b/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterCodeGenerator.groovy @@ -0,0 +1,132 @@ +package com.billy.android.register + +import org.apache.commons.io.IOUtils +import org.objectweb.asm.* + +import java.util.jar.JarEntry +import java.util.jar.JarFile +import java.util.jar.JarOutputStream +import java.util.zip.ZipEntry +/** + * generate register code into LogisticsCenter.class + * @author billy.qi email: qiyilike@163.com + */ +class RouterRegisterCodeGenerator { + RouterRegisterSetting extension + + private RouterRegisterCodeGenerator(RouterRegisterSetting extension) { + this.extension = extension + } + + static void insertInitCodeTo(RouterRegisterSetting registerSetting) { + if (registerSetting != null && !registerSetting.classList.isEmpty()) { + RouterRegisterCodeGenerator processor = new RouterRegisterCodeGenerator(registerSetting) + File file = RouterRegisterTransform.fileContainsInitClass + if (file.getName().endsWith('.jar')) + processor.insertInitCodeIntoJarFile(file) + } + } + + /** + * generate code into jar file + * @param jarFile the jar file which contains LogisticsCenter.class + * @return + */ + private File insertInitCodeIntoJarFile(File jarFile) { + if (jarFile) { + def optJar = new File(jarFile.getParent(), jarFile.name + ".opt") + if (optJar.exists()) + optJar.delete() + def file = new JarFile(jarFile) + Enumeration enumeration = file.entries() + JarOutputStream jarOutputStream = new JarOutputStream(new FileOutputStream(optJar)) + + while (enumeration.hasMoreElements()) { + JarEntry jarEntry = (JarEntry) enumeration.nextElement() + String entryName = jarEntry.getName() + ZipEntry zipEntry = new ZipEntry(entryName) + InputStream inputStream = file.getInputStream(jarEntry) + jarOutputStream.putNextEntry(zipEntry) + if (RouterRegisterSetting.GENERATE_TO_CLASS_FILE_NAME == entryName) { + println('codeInsertToClassName:' + entryName) + def bytes = referHackWhenInit(inputStream) + jarOutputStream.write(bytes) + } else { + jarOutputStream.write(IOUtils.toByteArray(inputStream)) + } + inputStream.close() + jarOutputStream.closeEntry() + } + jarOutputStream.close() + file.close() + + if (jarFile.exists()) { + jarFile.delete() + } + optJar.renameTo(jarFile) + } + return jarFile + } + + //refer hack class when object init + private byte[] referHackWhenInit(InputStream inputStream) { + ClassReader cr = new ClassReader(inputStream) + ClassWriter cw = new ClassWriter(cr, 0) + ClassVisitor cv = new MyClassVisitor(Opcodes.ASM5, cw) + cr.accept(cv, ClassReader.EXPAND_FRAMES) + return cw.toByteArray() + } + + class MyClassVisitor extends ClassVisitor { + + MyClassVisitor(int api, ClassVisitor cv) { + super(api, cv) + } + + void visit(int version, int access, String name, String signature, + String superName, String[] interfaces) { + super.visit(version, access, name, signature, superName, interfaces) + } + @Override + MethodVisitor visitMethod(int access, String name, String desc, + String signature, String[] exceptions) { + MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions) + //generate code into this method + if (name == RouterRegisterSetting.GENERATE_TO_METHOD_NAME) { + mv = new MyMethodVisitor(Opcodes.ASM5, mv) + } + return mv + } + } + + class MyMethodVisitor extends MethodVisitor { + + MyMethodVisitor(int api, MethodVisitor mv) { + super(api, mv) + } + + @Override + void visitInsn(int opcode) { + //generate code before return + if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)) { + extension.classList.each { name -> + //new a object for the specified class + mv.visitTypeInsn(Opcodes.NEW, name) + mv.visitInsn(Opcodes.DUP) + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, name, "", "()V", false) + // generate invoke register method into LogisticsCenter.loadRouterMap() + mv.visitMethodInsn(Opcodes.INVOKESTATIC + , RouterRegisterSetting.GENERATE_TO_CLASS_NAME + , extension.registerMethodName + , "(L${extension.interfaceName};)V" + , false) + } + } + super.visitInsn(opcode) + } + @Override + void visitMaxs(int maxStack, int maxLocals) { + super.visitMaxs(maxStack + 4, maxLocals) + } + } +} \ No newline at end of file diff --git a/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterPlugin.groovy b/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterPlugin.groovy new file mode 100644 index 00000000..aa0c93c4 --- /dev/null +++ b/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterPlugin.groovy @@ -0,0 +1,34 @@ +package com.billy.android.register + +import com.android.build.gradle.AppExtension +import com.android.build.gradle.AppPlugin +import org.gradle.api.Plugin +import org.gradle.api.Project +/** + * Simple version of AutoRegister plugin for ARouter + * @author billy.qi email: qiyilike@163.com + * @since 17/12/06 15:35 + */ +public class RouterRegisterPlugin implements Plugin { + + @Override + public void apply(Project project) { + def isApp = project.plugins.hasPlugin(AppPlugin) + //only application module needs this plugin to generate register code + if (isApp) { + println 'project(' + project.name + ') apply arouter-auto-register plugin' + def android = project.extensions.getByType(AppExtension) + def transformImpl = new RouterRegisterTransform(project) + + //init arouter-auto-register settings + ArrayList list = new ArrayList<>(3) + list.add(new RouterRegisterSetting('IRouteRoot', 'registerRouteRoot')) + list.add(new RouterRegisterSetting('IInterceptorGroup', 'registerInterceptor')) + list.add(new RouterRegisterSetting('IProviderGroup', 'registerProvider')) + RouterRegisterTransform.registerList = list + //register this plugin + android.registerTransform(transformImpl) + } + } + +} diff --git a/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterSetting.groovy b/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterSetting.groovy new file mode 100644 index 00000000..0c5a7fb5 --- /dev/null +++ b/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterSetting.groovy @@ -0,0 +1,58 @@ +package com.billy.android.register +/** + * register setting + * @author billy.qi email: qiyilike@163.com + * @since 17/3/28 11:48 + */ +class RouterRegisterSetting { + /** + * The register code is generated into this class + */ + static final String GENERATE_TO_CLASS_NAME = 'com/alibaba/android/arouter/core/LogisticsCenter' + /** + * you know. this is the class file(or entry in jar file) name + */ + static final String GENERATE_TO_CLASS_FILE_NAME = GENERATE_TO_CLASS_NAME + '.class' + /** + * The register code is generated into this method + */ + static final String GENERATE_TO_METHOD_NAME = 'loadRouterMap' + /** + * The package name of the class generated by the annotationProcessor + */ + static final String ROUTER_CLASS_PACKAGE_NAME = 'com/alibaba/android/arouter/routes/' + /** + * The package name of the interfaces + */ + private static final INTERFACE_PACKAGE_NAME = 'com/alibaba/android/arouter/facade/template/' + /** + * scan for classes which implements this interface + */ + String interfaceName = '' + /** + * register method name in class: {@link #GENERATE_TO_CLASS_NAME} + * for {@link #interfaceName} + */ + String registerMethodName = '' + + /** + * jar file which contains class: {@link #GENERATE_TO_CLASS_NAME} + */ + File fileContainsInitClass + /** + * scan result for {@link #interfaceName} + * class names in this list + */ + ArrayList classList = new ArrayList<>() + + /** + * constructor for arouter-auto-register settings + * @param interfaceName interface to scan + * @param registerMethod method to generate code into + */ + RouterRegisterSetting(String interfaceName, String registerMethod){ + this.interfaceName = INTERFACE_PACKAGE_NAME + interfaceName + this.registerMethodName = registerMethod + } + +} \ No newline at end of file diff --git a/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterTransform.groovy b/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterTransform.groovy new file mode 100644 index 00000000..240af065 --- /dev/null +++ b/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterTransform.groovy @@ -0,0 +1,124 @@ +package com.billy.android.register + +import com.android.build.api.transform.* +import com.android.build.gradle.internal.pipeline.TransformManager +import org.apache.commons.codec.digest.DigestUtils +import org.apache.commons.io.FileUtils +import org.gradle.api.Project + +/** + * transform api + *

+ * 1. Scan all classes to find which classes implement the specified interface + * 2. Generate register code into class file: {@link RouterRegisterSetting#GENERATE_TO_CLASS_FILE_NAME} + * @author billy.qi email: qiyilike@163.com + * @since 17/3/21 11:48 + */ +class RouterRegisterTransform extends Transform { + + Project project + static ArrayList registerList + static File fileContainsInitClass; + + RouterRegisterTransform(Project project) { + this.project = project + } + + /** + * name of this transform + * @return + */ + @Override + String getName() { + return "arouter-auto-register" + } + + @Override + Set getInputTypes() { + return TransformManager.CONTENT_CLASS + } + + /** + * The plugin will scan all classes in the project + * @return + */ + @Override + Set getScopes() { + return TransformManager.SCOPE_FULL_PROJECT + } + + @Override + boolean isIncremental() { + return false + } + + + @Override + void transform(Context context, Collection inputs + , Collection referencedInputs + , TransformOutputProvider outputProvider + , boolean isIncremental) throws IOException, TransformException, InterruptedException { + println("\n\n============================ start arouter-auto-register ============================\n") + long time = System.currentTimeMillis() + inputs.each { TransformInput input -> + + // scan all jars + input.jarInputs.each { JarInput jarInput -> + String destName = jarInput.name + // rename jar files + def hexName = DigestUtils.md5Hex(jarInput.file.absolutePath) + if (destName.endsWith(".jar")) { + destName = destName.substring(0, destName.length() - 4) + } + // input file + File src = jarInput.file + // output file + File dest = outputProvider.getContentLocation(destName + "_" + hexName, jarInput.contentTypes, jarInput.scopes, Format.JAR) + + //scan jar file to find classes + if (RouterScanUtil.shouldProcessPreDexJar(src.absolutePath)) { + RouterScanUtil.scanJar(src, dest) + } + FileUtils.copyFile(src, dest) + + } + // scan class files + input.directoryInputs.each { DirectoryInput directoryInput -> + File dest = outputProvider.getContentLocation(directoryInput.name, directoryInput.contentTypes, directoryInput.scopes, Format.DIRECTORY) + String root = directoryInput.file.absolutePath + if (!root.endsWith(File.separator)) + root += File.separator + directoryInput.file.eachFileRecurse { File file -> + def path = file.absolutePath.replace(root, '') + if(file.isFile() && RouterScanUtil.shouldProcessClass(path)){ + RouterScanUtil.scanClass(file) + } + } + + // copy to dest + FileUtils.copyDirectory(directoryInput.file, dest) + } + } + def scanFinishTime = System.currentTimeMillis() + println(">>>>>> register scan all class cost time: " + (scanFinishTime - time) + " ms") + + if (fileContainsInitClass) { + registerList.each { ext -> + println("\ninsert register code to file:" + fileContainsInitClass.absolutePath) + if (ext.classList.isEmpty()) { + project.logger.error("No class implements found for interface:" + ext.interfaceName) + } else { + ext.classList.each { + println(it) + } + RouterRegisterCodeGenerator.insertInitCodeTo(ext) + } + } + } + def finishTime = System.currentTimeMillis() + println("\n>>>>>> register insert code cost time: " + (finishTime - scanFinishTime) + " ms") + println(">>>>>> register cost time: " + (finishTime - time) + " ms") + println("\n============================ finish arouter-auto-register ============================\n\n") + } + +} diff --git a/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterScanUtil.groovy b/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterScanUtil.groovy new file mode 100644 index 00000000..32ce55a5 --- /dev/null +++ b/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterScanUtil.groovy @@ -0,0 +1,90 @@ +package com.billy.android.register + +import org.objectweb.asm.ClassReader +import org.objectweb.asm.ClassVisitor +import org.objectweb.asm.ClassWriter +import org.objectweb.asm.Opcodes + +import java.util.jar.JarEntry +import java.util.jar.JarFile + +/** + * Scan all class in the package: com/alibaba/android/arouter/ + * find out all routers,interceptors and providers + * @author billy.qi email: qiyilike@163.com + * @since 17/3/20 11:48 + */ +class RouterScanUtil { + + /** + * scan jar file + * @param jarFile All jar files that are compiled into apk + * @param destFile dest file after this transform + */ + static void scanJar(File jarFile, File destFile) { + if (jarFile) { + def file = new JarFile(jarFile) + Enumeration enumeration = file.entries() + while (enumeration.hasMoreElements()) { + JarEntry jarEntry = (JarEntry) enumeration.nextElement() + String entryName = jarEntry.getName() + if (entryName.startsWith(RouterRegisterSetting.ROUTER_CLASS_PACKAGE_NAME)) { + InputStream inputStream = file.getInputStream(jarEntry) + scanClass(inputStream) + inputStream.close() + } else if (RouterRegisterSetting.GENERATE_TO_CLASS_FILE_NAME == entryName) { + // mark this jar file contains LogisticsCenter.class + // After the scan is complete, we will generate register code into this file + RouterRegisterTransform.fileContainsInitClass = destFile + } + } + file.close() + } + } + + static boolean shouldProcessPreDexJar(String path) { + return path.endsWith("classes.jar") && !path.contains("com.android.support") && !path.contains("/android/m2repository") + } + + static boolean shouldProcessClass(String entryName) { + return entryName != null && entryName.startsWith(RouterRegisterSetting.ROUTER_CLASS_PACKAGE_NAME) + } + + /** + * scan class file + * @param class file + */ + static void scanClass(File file) { + scanClass(new FileInputStream(file)) + } + + static void scanClass(InputStream inputStream) { + ClassReader cr = new ClassReader(inputStream) + ClassWriter cw = new ClassWriter(cr, 0) + ScanClassVisitor cv = new ScanClassVisitor(Opcodes.ASM5, cw) + cr.accept(cv, ClassReader.EXPAND_FRAMES) + inputStream.close() + } + + static class ScanClassVisitor extends ClassVisitor { + + ScanClassVisitor(int api, ClassVisitor cv) { + super(api, cv) + } + + void visit(int version, int access, String name, String signature, + String superName, String[] interfaces) { + super.visit(version, access, name, signature, superName, interfaces) + RouterRegisterTransform.registerList.each { ext -> + if (ext.interfaceName && interfaces != null) { + interfaces.each { itName -> + if (itName == ext.interfaceName) { + ext.classList.add(name) + } + } + } + } + } + } + +} \ No newline at end of file diff --git a/arouter-auto-register/src/main/resources/META-INF/gradle-plugins/arouter-auto-register.properties b/arouter-auto-register/src/main/resources/META-INF/gradle-plugins/arouter-auto-register.properties new file mode 100644 index 00000000..04b95043 --- /dev/null +++ b/arouter-auto-register/src/main/resources/META-INF/gradle-plugins/arouter-auto-register.properties @@ -0,0 +1 @@ +implementation-class=com.billy.android.register.RouterRegisterPlugin \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 22f175b2..3121753f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,4 +3,5 @@ include ':arouter-api' include ':arouter-compiler' include ':arouter-annotation' include ':module-java' -include ':module-kotlin' \ No newline at end of file +include ':module-kotlin' +include ':arouter-auto-register' \ No newline at end of file From 10bed9d3bf752010f61a741901fd9c44049b1ee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AD=A3=E7=BA=AC?= Date: Mon, 18 Dec 2017 16:00:57 +0800 Subject: [PATCH 02/13] Add deploy shell and rename plugin name. --- app/build.gradle | 1 + arouter-auto-register/build.gradle | 15 ------ .../register/RouterRegisterPlugin.groovy | 34 ------------- .../arouter-auto-register.properties | 1 - arouter-register/build.gradle | 21 ++++++++ .../core/RegisterCodeGenerator.groovy | 32 ++++++------ .../register/core/RegisterTransform.groovy | 50 ++++++++++--------- .../register/launch/PluginLaunch.groovy | 40 +++++++++++++++ .../arouter/register/utils/Logger.groovy | 36 +++++++++++++ .../arouter/register/utils/ScanSetting.groovy | 7 +-- .../arouter/register/utils/ScanUtil.groovy | 15 +++--- .../com.alibaba.arouter.properties | 1 + build.gradle | 4 +- gradle.properties | 1 + settings.gradle | 2 +- 15 files changed, 161 insertions(+), 99 deletions(-) delete mode 100644 arouter-auto-register/build.gradle delete mode 100644 arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterPlugin.groovy delete mode 100644 arouter-auto-register/src/main/resources/META-INF/gradle-plugins/arouter-auto-register.properties create mode 100644 arouter-register/build.gradle rename arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterCodeGenerator.groovy => arouter-register/src/main/groovy/com/alibaba/android/arouter/register/core/RegisterCodeGenerator.groovy (81%) rename arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterTransform.groovy => arouter-register/src/main/groovy/com/alibaba/android/arouter/register/core/RegisterTransform.groovy (66%) create mode 100644 arouter-register/src/main/groovy/com/alibaba/android/arouter/register/launch/PluginLaunch.groovy create mode 100644 arouter-register/src/main/groovy/com/alibaba/android/arouter/register/utils/Logger.groovy rename arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterSetting.groovy => arouter-register/src/main/groovy/com/alibaba/android/arouter/register/utils/ScanSetting.groovy (89%) rename arouter-auto-register/src/main/groovy/com/billy/android/register/RouterScanUtil.groovy => arouter-register/src/main/groovy/com/alibaba/android/arouter/register/utils/ScanUtil.groovy (83%) create mode 100644 arouter-register/src/main/resources/META-INF/gradle-plugins/com.alibaba.arouter.properties diff --git a/app/build.gradle b/app/build.gradle index 8b0d6121..3e559278 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,4 +1,5 @@ apply plugin: 'com.android.application' +apply plugin: 'com.alibaba.arouter' android { compileSdkVersion Integer.parseInt(COMPILE_SDK_VERSION) diff --git a/arouter-auto-register/build.gradle b/arouter-auto-register/build.gradle deleted file mode 100644 index a14d6b39..00000000 --- a/arouter-auto-register/build.gradle +++ /dev/null @@ -1,15 +0,0 @@ -apply plugin: 'groovy' - -dependencies { - compile gradleApi() - compile localGroovy() -} - -repositories { - mavenCentral() -} -dependencies { - compile 'com.android.tools.build:gradle:2.2.0' -} - - diff --git a/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterPlugin.groovy b/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterPlugin.groovy deleted file mode 100644 index aa0c93c4..00000000 --- a/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterPlugin.groovy +++ /dev/null @@ -1,34 +0,0 @@ -package com.billy.android.register - -import com.android.build.gradle.AppExtension -import com.android.build.gradle.AppPlugin -import org.gradle.api.Plugin -import org.gradle.api.Project -/** - * Simple version of AutoRegister plugin for ARouter - * @author billy.qi email: qiyilike@163.com - * @since 17/12/06 15:35 - */ -public class RouterRegisterPlugin implements Plugin { - - @Override - public void apply(Project project) { - def isApp = project.plugins.hasPlugin(AppPlugin) - //only application module needs this plugin to generate register code - if (isApp) { - println 'project(' + project.name + ') apply arouter-auto-register plugin' - def android = project.extensions.getByType(AppExtension) - def transformImpl = new RouterRegisterTransform(project) - - //init arouter-auto-register settings - ArrayList list = new ArrayList<>(3) - list.add(new RouterRegisterSetting('IRouteRoot', 'registerRouteRoot')) - list.add(new RouterRegisterSetting('IInterceptorGroup', 'registerInterceptor')) - list.add(new RouterRegisterSetting('IProviderGroup', 'registerProvider')) - RouterRegisterTransform.registerList = list - //register this plugin - android.registerTransform(transformImpl) - } - } - -} diff --git a/arouter-auto-register/src/main/resources/META-INF/gradle-plugins/arouter-auto-register.properties b/arouter-auto-register/src/main/resources/META-INF/gradle-plugins/arouter-auto-register.properties deleted file mode 100644 index 04b95043..00000000 --- a/arouter-auto-register/src/main/resources/META-INF/gradle-plugins/arouter-auto-register.properties +++ /dev/null @@ -1 +0,0 @@ -implementation-class=com.billy.android.register.RouterRegisterPlugin \ No newline at end of file diff --git a/arouter-register/build.gradle b/arouter-register/build.gradle new file mode 100644 index 00000000..34f82ae8 --- /dev/null +++ b/arouter-register/build.gradle @@ -0,0 +1,21 @@ +apply plugin: 'groovy' + +ext { + bintrayName = 'arouter-register' + artifact = bintrayName + libraryName = 'ARouter register gradle plugin' + libraryDescription = 'A gradle plugin used for arouter route map register' + libraryVersion = arouter_register_version +} + +dependencies { + compile gradleApi() + compile localGroovy() +} + +dependencies { + compile 'com.android.tools.build:gradle:2.1.3' +} + +apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle' +apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/bintrayv1.gradle' \ No newline at end of file diff --git a/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterCodeGenerator.groovy b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/core/RegisterCodeGenerator.groovy similarity index 81% rename from arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterCodeGenerator.groovy rename to arouter-register/src/main/groovy/com/alibaba/android/arouter/register/core/RegisterCodeGenerator.groovy index da15da41..33f8c103 100644 --- a/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterCodeGenerator.groovy +++ b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/core/RegisterCodeGenerator.groovy @@ -1,5 +1,7 @@ -package com.billy.android.register +package com.alibaba.android.arouter.register.core +import com.alibaba.android.arouter.register.utils.Logger +import com.alibaba.android.arouter.register.utils.ScanSetting import org.apache.commons.io.IOUtils import org.objectweb.asm.* @@ -11,17 +13,17 @@ import java.util.zip.ZipEntry * generate register code into LogisticsCenter.class * @author billy.qi email: qiyilike@163.com */ -class RouterRegisterCodeGenerator { - RouterRegisterSetting extension +class RegisterCodeGenerator { + ScanSetting extension - private RouterRegisterCodeGenerator(RouterRegisterSetting extension) { + private RegisterCodeGenerator(ScanSetting extension) { this.extension = extension } - static void insertInitCodeTo(RouterRegisterSetting registerSetting) { + static void insertInitCodeTo(ScanSetting registerSetting) { if (registerSetting != null && !registerSetting.classList.isEmpty()) { - RouterRegisterCodeGenerator processor = new RouterRegisterCodeGenerator(registerSetting) - File file = RouterRegisterTransform.fileContainsInitClass + RegisterCodeGenerator processor = new RegisterCodeGenerator(registerSetting) + File file = RegisterTransform.fileContainsInitClass if (file.getName().endsWith('.jar')) processor.insertInitCodeIntoJarFile(file) } @@ -47,8 +49,10 @@ class RouterRegisterCodeGenerator { ZipEntry zipEntry = new ZipEntry(entryName) InputStream inputStream = file.getInputStream(jarEntry) jarOutputStream.putNextEntry(zipEntry) - if (RouterRegisterSetting.GENERATE_TO_CLASS_FILE_NAME == entryName) { - println('codeInsertToClassName:' + entryName) + if (ScanSetting.GENERATE_TO_CLASS_FILE_NAME == entryName) { + + Logger.i('Insert init code to class >> ' + entryName) + def bytes = referHackWhenInit(inputStream) jarOutputStream.write(bytes) } else { @@ -92,16 +96,16 @@ class RouterRegisterCodeGenerator { String signature, String[] exceptions) { MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions) //generate code into this method - if (name == RouterRegisterSetting.GENERATE_TO_METHOD_NAME) { - mv = new MyMethodVisitor(Opcodes.ASM5, mv) + if (name == ScanSetting.GENERATE_TO_METHOD_NAME) { + mv = new RouteMethodVisitor(Opcodes.ASM5, mv) } return mv } } - class MyMethodVisitor extends MethodVisitor { + class RouteMethodVisitor extends MethodVisitor { - MyMethodVisitor(int api, MethodVisitor mv) { + RouteMethodVisitor(int api, MethodVisitor mv) { super(api, mv) } @@ -116,7 +120,7 @@ class RouterRegisterCodeGenerator { mv.visitMethodInsn(Opcodes.INVOKESPECIAL, name, "", "()V", false) // generate invoke register method into LogisticsCenter.loadRouterMap() mv.visitMethodInsn(Opcodes.INVOKESTATIC - , RouterRegisterSetting.GENERATE_TO_CLASS_NAME + , ScanSetting.GENERATE_TO_CLASS_NAME , extension.registerMethodName , "(L${extension.interfaceName};)V" , false) diff --git a/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterTransform.groovy b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/core/RegisterTransform.groovy similarity index 66% rename from arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterTransform.groovy rename to arouter-register/src/main/groovy/com/alibaba/android/arouter/register/core/RegisterTransform.groovy index 240af065..4d2a9680 100644 --- a/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterTransform.groovy +++ b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/core/RegisterTransform.groovy @@ -1,5 +1,8 @@ -package com.billy.android.register +package com.alibaba.android.arouter.register.core +import com.alibaba.android.arouter.register.utils.Logger +import com.alibaba.android.arouter.register.utils.ScanSetting +import com.alibaba.android.arouter.register.utils.ScanUtil import com.android.build.api.transform.* import com.android.build.gradle.internal.pipeline.TransformManager import org.apache.commons.codec.digest.DigestUtils @@ -10,17 +13,17 @@ import org.gradle.api.Project * transform api *

* 1. Scan all classes to find which classes implement the specified interface - * 2. Generate register code into class file: {@link RouterRegisterSetting#GENERATE_TO_CLASS_FILE_NAME} + * 2. Generate register code into class file: {@link ScanSetting#GENERATE_TO_CLASS_FILE_NAME} * @author billy.qi email: qiyilike@163.com * @since 17/3/21 11:48 */ -class RouterRegisterTransform extends Transform { +class RegisterTransform extends Transform { Project project - static ArrayList registerList + static ArrayList registerList static File fileContainsInitClass; - RouterRegisterTransform(Project project) { + RegisterTransform(Project project) { this.project = project } @@ -30,7 +33,7 @@ class RouterRegisterTransform extends Transform { */ @Override String getName() { - return "arouter-auto-register" + return ScanSetting.PLUGIN_NAME } @Override @@ -58,8 +61,11 @@ class RouterRegisterTransform extends Transform { , Collection referencedInputs , TransformOutputProvider outputProvider , boolean isIncremental) throws IOException, TransformException, InterruptedException { - println("\n\n============================ start arouter-auto-register ============================\n") - long time = System.currentTimeMillis() + + Logger.i('Start scan register info in jar file.') + + long startTime = System.currentTimeMillis() + inputs.each { TransformInput input -> // scan all jars @@ -76,8 +82,8 @@ class RouterRegisterTransform extends Transform { File dest = outputProvider.getContentLocation(destName + "_" + hexName, jarInput.contentTypes, jarInput.scopes, Format.JAR) //scan jar file to find classes - if (RouterScanUtil.shouldProcessPreDexJar(src.absolutePath)) { - RouterScanUtil.scanJar(src, dest) + if (ScanUtil.shouldProcessPreDexJar(src.absolutePath)) { + ScanUtil.scanJar(src, dest) } FileUtils.copyFile(src, dest) @@ -90,8 +96,8 @@ class RouterRegisterTransform extends Transform { root += File.separator directoryInput.file.eachFileRecurse { File file -> def path = file.absolutePath.replace(root, '') - if(file.isFile() && RouterScanUtil.shouldProcessClass(path)){ - RouterScanUtil.scanClass(file) + if(file.isFile() && ScanUtil.shouldProcessClass(path)){ + ScanUtil.scanClass(file) } } @@ -99,26 +105,24 @@ class RouterRegisterTransform extends Transform { FileUtils.copyDirectory(directoryInput.file, dest) } } - def scanFinishTime = System.currentTimeMillis() - println(">>>>>> register scan all class cost time: " + (scanFinishTime - time) + " ms") + + Logger.i('Scan finish, current cost time ' + (System.currentTimeMillis() - startTime) + "ms") if (fileContainsInitClass) { registerList.each { ext -> - println("\ninsert register code to file:" + fileContainsInitClass.absolutePath) + Logger.i('Insert register code to file ' + fileContainsInitClass.absolutePath) + if (ext.classList.isEmpty()) { - project.logger.error("No class implements found for interface:" + ext.interfaceName) + Logger.e("No class implements found for interface:" + ext.interfaceName) } else { ext.classList.each { - println(it) + Logger.i(it) } - RouterRegisterCodeGenerator.insertInitCodeTo(ext) + RegisterCodeGenerator.insertInitCodeTo(ext) } } } - def finishTime = System.currentTimeMillis() - println("\n>>>>>> register insert code cost time: " + (finishTime - scanFinishTime) + " ms") - println(">>>>>> register cost time: " + (finishTime - time) + " ms") - println("\n============================ finish arouter-auto-register ============================\n\n") - } + Logger.i("Generate code finish, current cost time: " + (System.currentTimeMillis() - startTime) + "ms") + } } diff --git a/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/launch/PluginLaunch.groovy b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/launch/PluginLaunch.groovy new file mode 100644 index 00000000..401cccd9 --- /dev/null +++ b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/launch/PluginLaunch.groovy @@ -0,0 +1,40 @@ +package com.alibaba.android.arouter.register.launch + +import com.alibaba.android.arouter.register.utils.Logger +import com.android.build.gradle.AppExtension +import com.android.build.gradle.AppPlugin +import com.alibaba.android.arouter.register.utils.ScanSetting +import com.alibaba.android.arouter.register.core.RegisterTransform +import org.gradle.api.Plugin +import org.gradle.api.Project +/** + * Simple version of AutoRegister plugin for ARouter + * @author billy.qi email: qiyilike@163.com + * @since 17/12/06 15:35 + */ +public class PluginLaunch implements Plugin { + + @Override + public void apply(Project project) { + def isApp = project.plugins.hasPlugin(AppPlugin) + //only application module needs this plugin to generate register code + if (isApp) { + Logger.make(project) + + Logger.i('project(' + project.name + ') apply arouter-register plugin') + + def android = project.extensions.getByType(AppExtension) + def transformImpl = new RegisterTransform(project) + + //init arouter-auto-register settings + ArrayList list = new ArrayList<>(3) + list.add(new ScanSetting('IRouteRoot', 'registerRouteRoot')) + list.add(new ScanSetting('IInterceptorGroup', 'registerInterceptor')) + list.add(new ScanSetting('IProviderGroup', 'registerProvider')) + RegisterTransform.registerList = list + //register this plugin + android.registerTransform(transformImpl) + } + } + +} diff --git a/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/utils/Logger.groovy b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/utils/Logger.groovy new file mode 100644 index 00000000..79aae54d --- /dev/null +++ b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/utils/Logger.groovy @@ -0,0 +1,36 @@ +package com.alibaba.android.arouter.register.utils + +import org.gradle.api.Project + +/** + * Format log + * + * @author zhilong Contact me. + * @version 1.0 + * @since 2017/12/18 下午2:43 + */ +class Logger { + static org.gradle.api.logging.Logger logger + + static void make(Project project) { + logger = project.getLogger() + } + + static void i(String info) { + if (null != info && null != logger) { + logger.info("ARouter::Register >>> " + info) + } + } + + static void e(String error) { + if (null != error && null != logger) { + logger.error("ARouter::Register >>> " + error) + } + } + + static void w(String warning) { + if (null != warning && null != logger) { + logger.warn("ARouter::Register >>> " + warning) + } + } +} diff --git a/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterSetting.groovy b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/utils/ScanSetting.groovy similarity index 89% rename from arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterSetting.groovy rename to arouter-register/src/main/groovy/com/alibaba/android/arouter/register/utils/ScanSetting.groovy index 0c5a7fb5..2383e653 100644 --- a/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterRegisterSetting.groovy +++ b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/utils/ScanSetting.groovy @@ -1,10 +1,11 @@ -package com.billy.android.register +package com.alibaba.android.arouter.register.utils /** * register setting * @author billy.qi email: qiyilike@163.com * @since 17/3/28 11:48 */ -class RouterRegisterSetting { +class ScanSetting { + static final String PLUGIN_NAME = "com.alibaba.arouter" /** * The register code is generated into this class */ @@ -50,7 +51,7 @@ class RouterRegisterSetting { * @param interfaceName interface to scan * @param registerMethod method to generate code into */ - RouterRegisterSetting(String interfaceName, String registerMethod){ + ScanSetting(String interfaceName, String registerMethod){ this.interfaceName = INTERFACE_PACKAGE_NAME + interfaceName this.registerMethodName = registerMethod } diff --git a/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterScanUtil.groovy b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/utils/ScanUtil.groovy similarity index 83% rename from arouter-auto-register/src/main/groovy/com/billy/android/register/RouterScanUtil.groovy rename to arouter-register/src/main/groovy/com/alibaba/android/arouter/register/utils/ScanUtil.groovy index 32ce55a5..b2beb445 100644 --- a/arouter-auto-register/src/main/groovy/com/billy/android/register/RouterScanUtil.groovy +++ b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/utils/ScanUtil.groovy @@ -1,5 +1,6 @@ -package com.billy.android.register +package com.alibaba.android.arouter.register.utils +import com.alibaba.android.arouter.register.core.RegisterTransform import org.objectweb.asm.ClassReader import org.objectweb.asm.ClassVisitor import org.objectweb.asm.ClassWriter @@ -14,7 +15,7 @@ import java.util.jar.JarFile * @author billy.qi email: qiyilike@163.com * @since 17/3/20 11:48 */ -class RouterScanUtil { +class ScanUtil { /** * scan jar file @@ -28,14 +29,14 @@ class RouterScanUtil { while (enumeration.hasMoreElements()) { JarEntry jarEntry = (JarEntry) enumeration.nextElement() String entryName = jarEntry.getName() - if (entryName.startsWith(RouterRegisterSetting.ROUTER_CLASS_PACKAGE_NAME)) { + if (entryName.startsWith(ScanSetting.ROUTER_CLASS_PACKAGE_NAME)) { InputStream inputStream = file.getInputStream(jarEntry) scanClass(inputStream) inputStream.close() - } else if (RouterRegisterSetting.GENERATE_TO_CLASS_FILE_NAME == entryName) { + } else if (ScanSetting.GENERATE_TO_CLASS_FILE_NAME == entryName) { // mark this jar file contains LogisticsCenter.class // After the scan is complete, we will generate register code into this file - RouterRegisterTransform.fileContainsInitClass = destFile + RegisterTransform.fileContainsInitClass = destFile } } file.close() @@ -47,7 +48,7 @@ class RouterScanUtil { } static boolean shouldProcessClass(String entryName) { - return entryName != null && entryName.startsWith(RouterRegisterSetting.ROUTER_CLASS_PACKAGE_NAME) + return entryName != null && entryName.startsWith(ScanSetting.ROUTER_CLASS_PACKAGE_NAME) } /** @@ -75,7 +76,7 @@ class RouterScanUtil { void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { super.visit(version, access, name, signature, superName, interfaces) - RouterRegisterTransform.registerList.each { ext -> + RegisterTransform.registerList.each { ext -> if (ext.interfaceName && interfaces != null) { interfaces.each { itName -> if (itName == ext.interfaceName) { diff --git a/arouter-register/src/main/resources/META-INF/gradle-plugins/com.alibaba.arouter.properties b/arouter-register/src/main/resources/META-INF/gradle-plugins/com.alibaba.arouter.properties new file mode 100644 index 00000000..94fa66a6 --- /dev/null +++ b/arouter-register/src/main/resources/META-INF/gradle-plugins/com.alibaba.arouter.properties @@ -0,0 +1 @@ +implementation-class=com.alibaba.android.arouter.register.launch.PluginLaunch \ No newline at end of file diff --git a/build.gradle b/build.gradle index 4a4d5675..0186c06e 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,6 @@ buildscript { ext.kotlin_version = '1.1.3-2' + repositories { jcenter() } @@ -10,6 +11,7 @@ buildscript { classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.2' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath "com.alibaba:arouter-register:1.0.0" } } @@ -17,4 +19,4 @@ allprojects { repositories { jcenter() } -} +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index c2f0526e..e54bd6cd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -27,6 +27,7 @@ TARGET_SDK_VERSION=25 arouter_compiler_version=1.1.4 arouter_api_version=1.2.4 arouter_annotation_version=1.0.4 +arouter_register_version=1.0.0 bintrayRepo=maven publishedGroupId=com.alibaba diff --git a/settings.gradle b/settings.gradle index 3121753f..5334938e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,4 +4,4 @@ include ':arouter-compiler' include ':arouter-annotation' include ':module-java' include ':module-kotlin' -include ':arouter-auto-register' \ No newline at end of file +include ':arouter-register' \ No newline at end of file From f7ec4503a8cbdef33c1d0189683cb28b06fbae5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AD=A3=E7=BA=AC?= Date: Mon, 18 Dec 2017 17:15:33 +0800 Subject: [PATCH 03/13] Update version of arouter api. --- README.md | 25 ++++++++++++++++--- README_CN.md | 25 ++++++++++++++++--- .../register/launch/PluginLaunch.groovy | 2 +- build.gradle | 2 +- gradle.properties | 2 +- 5 files changed, 47 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 76393b12..d6c0eff7 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ #### 最新版本 -模块|arouter-api|arouter-compiler|arouter-annotation ----|---|---|--- -最新版本|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-api/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-api/_latestVersion)|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-compiler/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-compiler/_latestVersion)|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-annotation/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-annotation/_latestVersion) +模块|arouter-api|arouter-compiler|arouter-annotation|arouter-register +---|---|---|---|--- +最新版本|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-api/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-api/_latestVersion)|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-compiler/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-compiler/_latestVersion)|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-annotation/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-annotation/_latestVersion)|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-register/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-register/_latestVersion) #### Demo展示 @@ -31,6 +31,7 @@ 10. 支持多种方式配置转场动画 11. 支持获取Fragment 12. 完全支持Kotlin以及混编(配置见文末 其他#5) +13. **支持第三方 App 加固**(使用 arouter-register 实现自动注册) #### 二、典型应用 1. 从外部URL映射到内部页面,以及参数传递与解析 @@ -107,6 +108,24 @@ ARouter.getInstance().build("/test/1") -keep class * implements com.alibaba.android.arouter.facade.template.IProvider ``` +6. 使用 Gradle 插件实现路由表的自动加载 +```gradle +apply plugin: 'com.alibaba.arouter' + +buildscript { + repositories { + jcenter() + } + + dependencies { + classpath "com.alibaba:arouter-register:1.0.0" + } +} +``` +可选使用,通过 ARouter 提供的注册插件进行路由表的自动加载,默认通过扫描 dex 的方式 +进行加载通过 gradle 插件进行自动注册可以缩短初始化时间解决应用加固导致无法直接访问 +dex 文件,初始化失败的问题,需要注意的是,该插件必须搭配 api 1.3.0 使用! + #### 四、进阶用法 1. 通过URL跳转 ``` java diff --git a/README_CN.md b/README_CN.md index e423aca0..d15f919e 100644 --- a/README_CN.md +++ b/README_CN.md @@ -10,9 +10,9 @@ #### 最新版本 -模块|arouter-api|arouter-compiler|arouter-annotation ----|---|---|--- -最新版本|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-api/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-api/_latestVersion)|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-compiler/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-compiler/_latestVersion)|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-annotation/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-annotation/_latestVersion) +模块|arouter-api|arouter-compiler|arouter-annotation|arouter-register +---|---|---|---|--- +最新版本|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-api/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-api/_latestVersion)|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-compiler/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-compiler/_latestVersion)|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-annotation/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-annotation/_latestVersion)|[![Download](https://api.bintray.com/packages/zhi1ong/maven/arouter-register/images/download.svg)](https://bintray.com/zhi1ong/maven/arouter-register/_latestVersion) #### Demo展示 @@ -31,6 +31,7 @@ 10. 支持多种方式配置转场动画 11. 支持获取Fragment 12. 完全支持Kotlin以及混编(配置见文末 其他#5) +13. **支持第三方 App 加固**(使用 arouter-register 实现自动注册) #### 二、典型应用 1. 从外部URL映射到内部页面,以及参数传递与解析 @@ -107,6 +108,24 @@ ARouter.getInstance().build("/test/1") -keep class * implements com.alibaba.android.arouter.facade.template.IProvider ``` +6. 使用 Gradle 插件实现路由表的自动加载 +```gradle +apply plugin: 'com.alibaba.arouter' + +buildscript { + repositories { + jcenter() + } + + dependencies { + classpath "com.alibaba:arouter-register:1.0.0" + } +} +``` +可选使用,通过 ARouter 提供的注册插件进行路由表的自动加载,默认通过扫描 dex 的方式 +进行加载通过 gradle 插件进行自动注册可以缩短初始化时间解决应用加固导致无法直接访问 +dex 文件,初始化失败的问题,需要注意的是,该插件必须搭配 api 1.3.0 使用! + #### 四、进阶用法 1. 通过URL跳转 ``` java diff --git a/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/launch/PluginLaunch.groovy b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/launch/PluginLaunch.groovy index 401cccd9..75fa3e3c 100644 --- a/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/launch/PluginLaunch.groovy +++ b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/launch/PluginLaunch.groovy @@ -21,7 +21,7 @@ public class PluginLaunch implements Plugin { if (isApp) { Logger.make(project) - Logger.i('project(' + project.name + ') apply arouter-register plugin') + Logger.i('Project enable arouter-register plugin') def android = project.extensions.getByType(AppExtension) def transformImpl = new RegisterTransform(project) diff --git a/build.gradle b/build.gradle index 0186c06e..7566104b 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ buildscript { classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.2' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath "com.alibaba:arouter-register:1.0.0" + classpath 'com.alibaba:arouter-register:1.0.0' } } diff --git a/gradle.properties b/gradle.properties index e54bd6cd..131b0f37 100644 --- a/gradle.properties +++ b/gradle.properties @@ -25,7 +25,7 @@ MIN_SDK_VERSION=12 TARGET_SDK_VERSION=25 arouter_compiler_version=1.1.4 -arouter_api_version=1.2.4 +arouter_api_version=1.3.0 arouter_annotation_version=1.0.4 arouter_register_version=1.0.0 From e0d1f2b44ddb496f0c9b1edd5bfb0ebb37794187 Mon Sep 17 00:00:00 2001 From: leo Date: Fri, 22 Dec 2017 15:30:08 +0800 Subject: [PATCH 04/13] fix: postcard transition support 0 --- .../java/com/alibaba/android/arouter/facade/Postcard.java | 4 ++-- .../java/com/alibaba/android/arouter/launcher/_ARouter.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arouter-api/src/main/java/com/alibaba/android/arouter/facade/Postcard.java b/arouter-api/src/main/java/com/alibaba/android/arouter/facade/Postcard.java index 5a426a9a..b77e1b2a 100644 --- a/arouter-api/src/main/java/com/alibaba/android/arouter/facade/Postcard.java +++ b/arouter-api/src/main/java/com/alibaba/android/arouter/facade/Postcard.java @@ -43,8 +43,8 @@ public final class Postcard extends RouteMeta { // Animation private Bundle optionsCompat; // The transition animation of activity - private int enterAnim; - private int exitAnim; + private int enterAnim = -1; + private int exitAnim = -1; public Bundle getOptionsBundle() { return optionsCompat; diff --git a/arouter-api/src/main/java/com/alibaba/android/arouter/launcher/_ARouter.java b/arouter-api/src/main/java/com/alibaba/android/arouter/launcher/_ARouter.java index a6a433bf..107c6541 100644 --- a/arouter-api/src/main/java/com/alibaba/android/arouter/launcher/_ARouter.java +++ b/arouter-api/src/main/java/com/alibaba/android/arouter/launcher/_ARouter.java @@ -359,7 +359,7 @@ public void run() { ActivityCompat.startActivity(currentContext, intent, postcard.getOptionsBundle()); } - if ((0 != postcard.getEnterAnim() || 0 != postcard.getExitAnim()) && currentContext instanceof Activity) { // Old version. + if ((-1 != postcard.getEnterAnim() && -1 != postcard.getExitAnim()) && currentContext instanceof Activity) { // Old version. ((Activity) currentContext).overridePendingTransition(postcard.getEnterAnim(), postcard.getExitAnim()); } From 20c64941d674c0dafb93c350053aa32cae854dd7 Mon Sep 17 00:00:00 2001 From: qiyi Date: Tue, 26 Dec 2017 13:49:04 +0800 Subject: [PATCH 05/13] solve the main dex file size is too large --- .../android/arouter/core/LogisticsCenter.java | 25 +++++++++++++++++++ .../core/RegisterCodeGenerator.groovy | 10 +++----- .../register/launch/PluginLaunch.groovy | 6 ++--- .../arouter/register/utils/ScanSetting.groovy | 14 +++++------ 4 files changed, 38 insertions(+), 17 deletions(-) diff --git a/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java b/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java index 85115d9d..b2d202a1 100644 --- a/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java +++ b/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java @@ -68,6 +68,31 @@ private static void loadRouterMap() { // registerRouteRoot(new ARouter..Root..modulekotlin()); } + /** + * register by class name + * Sacrificing a bit of efficiency to solve + * the problem that the main dex file size is too large + * @author billy.qi Contact me. + * @param className class name + */ + private static void register(String className) { + if (!TextUtils.isEmpty(className)) { + try { + Class clazz = Class.forName(className); + Object obj = clazz.getConstructor().newInstance(); + if (obj instanceof IRouteRoot) { + registerRouteRoot((IRouteRoot) obj); + } else if (obj instanceof IProviderGroup) { + registerProvider((IProviderGroup) obj); + } else if (obj instanceof IInterceptorGroup) { + registerInterceptor((IInterceptorGroup) obj); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + /** * method for arouter-auto-register plugin to register Routers * @param routeRoot IRouteRoot implementation class in the package: com.alibaba.android.arouter.core.routers diff --git a/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/core/RegisterCodeGenerator.groovy b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/core/RegisterCodeGenerator.groovy index 33f8c103..efbeb4a0 100644 --- a/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/core/RegisterCodeGenerator.groovy +++ b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/core/RegisterCodeGenerator.groovy @@ -114,15 +114,13 @@ class RegisterCodeGenerator { //generate code before return if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)) { extension.classList.each { name -> - //new a object for the specified class - mv.visitTypeInsn(Opcodes.NEW, name) - mv.visitInsn(Opcodes.DUP) - mv.visitMethodInsn(Opcodes.INVOKESPECIAL, name, "", "()V", false) + name = name.replaceAll("/", ".") + mv.visitLdcInsn(name)//类名 // generate invoke register method into LogisticsCenter.loadRouterMap() mv.visitMethodInsn(Opcodes.INVOKESTATIC , ScanSetting.GENERATE_TO_CLASS_NAME - , extension.registerMethodName - , "(L${extension.interfaceName};)V" + , ScanSetting.REGISTER_METHOD_NAME + , "(Ljava/lang/String;)V" , false) } } diff --git a/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/launch/PluginLaunch.groovy b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/launch/PluginLaunch.groovy index 75fa3e3c..4ecf74c1 100644 --- a/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/launch/PluginLaunch.groovy +++ b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/launch/PluginLaunch.groovy @@ -28,9 +28,9 @@ public class PluginLaunch implements Plugin { //init arouter-auto-register settings ArrayList list = new ArrayList<>(3) - list.add(new ScanSetting('IRouteRoot', 'registerRouteRoot')) - list.add(new ScanSetting('IInterceptorGroup', 'registerInterceptor')) - list.add(new ScanSetting('IProviderGroup', 'registerProvider')) + list.add(new ScanSetting('IRouteRoot')) + list.add(new ScanSetting('IInterceptorGroup')) + list.add(new ScanSetting('IProviderGroup')) RegisterTransform.registerList = list //register this plugin android.registerTransform(transformImpl) diff --git a/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/utils/ScanSetting.groovy b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/utils/ScanSetting.groovy index 2383e653..12dcf394 100644 --- a/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/utils/ScanSetting.groovy +++ b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/utils/ScanSetting.groovy @@ -26,15 +26,15 @@ class ScanSetting { * The package name of the interfaces */ private static final INTERFACE_PACKAGE_NAME = 'com/alibaba/android/arouter/facade/template/' + /** - * scan for classes which implements this interface + * register method name in class: {@link #GENERATE_TO_CLASS_NAME} */ - String interfaceName = '' + static final String REGISTER_METHOD_NAME = 'register' /** - * register method name in class: {@link #GENERATE_TO_CLASS_NAME} - * for {@link #interfaceName} + * scan for classes which implements this interface */ - String registerMethodName = '' + String interfaceName = '' /** * jar file which contains class: {@link #GENERATE_TO_CLASS_NAME} @@ -49,11 +49,9 @@ class ScanSetting { /** * constructor for arouter-auto-register settings * @param interfaceName interface to scan - * @param registerMethod method to generate code into */ - ScanSetting(String interfaceName, String registerMethod){ + ScanSetting(String interfaceName){ this.interfaceName = INTERFACE_PACKAGE_NAME + interfaceName - this.registerMethodName = registerMethod } } \ No newline at end of file From c525a0e42618ae7c5ecf6a97b8e5b058f248ddde Mon Sep 17 00:00:00 2001 From: qiyi Date: Tue, 26 Dec 2017 17:27:46 +0800 Subject: [PATCH 06/13] add error log --- .../com/alibaba/android/arouter/core/LogisticsCenter.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java b/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java index b2d202a1..2572e15d 100644 --- a/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java +++ b/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java @@ -2,6 +2,7 @@ import android.content.Context; import android.net.Uri; +import android.util.Log; import com.alibaba.android.arouter.exception.HandlerException; import com.alibaba.android.arouter.exception.NoRouteFoundException; @@ -86,9 +87,12 @@ private static void register(String className) { registerProvider((IProviderGroup) obj); } else if (obj instanceof IInterceptorGroup) { registerInterceptor((IInterceptorGroup) obj); + } else { + logger.info(TAG, "register failed, class name: " + className + + " should implements one of IRouteRoot/IProviderGroup/IInterceptorGroup."); } } catch (Exception e) { - e.printStackTrace(); + Log.e("ARouter", "register class error:" + className, e); } } } From f348b7abea1e85eeade9987938deb571dc48923b Mon Sep 17 00:00:00 2001 From: qiyi Date: Tue, 26 Dec 2017 17:56:33 +0800 Subject: [PATCH 07/13] use logger --- .../java/com/alibaba/android/arouter/core/LogisticsCenter.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java b/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java index 2572e15d..2b21e43f 100644 --- a/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java +++ b/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java @@ -2,7 +2,6 @@ import android.content.Context; import android.net.Uri; -import android.util.Log; import com.alibaba.android.arouter.exception.HandlerException; import com.alibaba.android.arouter.exception.NoRouteFoundException; @@ -92,7 +91,7 @@ private static void register(String className) { + " should implements one of IRouteRoot/IProviderGroup/IInterceptorGroup."); } } catch (Exception e) { - Log.e("ARouter", "register class error:" + className, e); + logger.error(TAG,"register class error:" + className); } } } From ba45eb73dc4bb4938ba137093a3801862b290372 Mon Sep 17 00:00:00 2001 From: tanglie Date: Wed, 3 Jan 2018 10:44:12 +0800 Subject: [PATCH 08/13] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E6=8B=BC=E5=86=99?= =?UTF-8?q?=E5=92=8C=E8=AF=AD=E6=B3=95=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/arouter/core/LogisticsCenter.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java b/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java index 2b21e43f..3d7a3135 100644 --- a/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java +++ b/arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java @@ -39,9 +39,9 @@ import static com.alibaba.android.arouter.utils.Consts.TAG; /** - * LogisticsCenter contain all of the map. + * LogisticsCenter contains all of the map. *

- * 1. Create instance when it first used. + * 1. Creates instance when it is first used. * 2. Handler Multi-Module relationship map(*) * 3. Complex logic to solve duplicate group definition * @@ -166,13 +166,13 @@ public synchronized static void init(Context context, ThreadPoolExecutor tpe) th // It will rebuild router map every times when debuggable. if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) { logger.info(TAG, "Run with debug mode or new install, rebuild router map."); - // These class was generate by arouter-compiler. + // These class was generated by arouter-compiler. routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE); if (!routerMap.isEmpty()) { context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).edit().putStringSet(AROUTER_SP_KEY_MAP, routerMap).apply(); } - PackageUtils.updateVersion(context); // Save new version name when router map update finish. + PackageUtils.updateVersion(context); // Save new version name when router map update finishes. } else { logger.info(TAG, "Load router map from cache."); routerMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet())); @@ -228,7 +228,7 @@ public static Postcard buildProvider(String serviceName) { /** * Completion the postcard by route metas * - * @param postcard Incomplete postcard, should completion by this method. + * @param postcard Incomplete postcard, should complete by this method. */ public synchronized static void completion(Postcard postcard) { if (null == postcard) { @@ -290,7 +290,7 @@ public synchronized static void completion(Postcard postcard) { switch (routeMeta.getType()) { case PROVIDER: // if the route is provider, should find its instance - // Its provider, so it must be implememt IProvider + // Its provider, so it must implement IProvider Class providerMeta = (Class) routeMeta.getDestination(); IProvider instance = Warehouse.providers.get(providerMeta); if (null == instance) { // There's no instance of this provider @@ -367,4 +367,4 @@ private static void setValue(Postcard postcard, Integer typeDef, String key, Str public static void suspend() { Warehouse.clear(); } -} \ No newline at end of file +} From 16a4739924ed48c81ff754dd31e047ed3755df85 Mon Sep 17 00:00:00 2001 From: tanglie Date: Wed, 3 Jan 2018 20:19:12 +0800 Subject: [PATCH 09/13] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8B=BC=E5=86=99?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../arouter/compiler/processor/RouteProcessor.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/processor/RouteProcessor.java b/arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/processor/RouteProcessor.java index 9b7a7756..935c4edf 100644 --- a/arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/processor/RouteProcessor.java +++ b/arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/processor/RouteProcessor.java @@ -216,7 +216,7 @@ private void parseRoutes(Set routeElements) throws IOExceptio for (Element element : routeElements) { TypeMirror tm = element.asType(); Route route = element.getAnnotation(Route.class); - RouteMeta routeMete = null; + RouteMeta routeMeta = null; if (types.isSubtype(tm, type_Activity)) { // Activity logger.info(">>> Found activity route: " + tm.toString() + " <<<"); @@ -230,21 +230,21 @@ private void parseRoutes(Set routeElements) throws IOExceptio paramsType.put(StringUtils.isEmpty(paramConfig.name()) ? field.getSimpleName().toString() : paramConfig.name(), typeUtils.typeExchange(field)); } } - routeMete = new RouteMeta(route, element, RouteType.ACTIVITY, paramsType); + routeMeta = new RouteMeta(route, element, RouteType.ACTIVITY, paramsType); } else if (types.isSubtype(tm, iProvider)) { // IProvider logger.info(">>> Found provider route: " + tm.toString() + " <<<"); - routeMete = new RouteMeta(route, element, RouteType.PROVIDER, null); + routeMeta = new RouteMeta(route, element, RouteType.PROVIDER, null); } else if (types.isSubtype(tm, type_Service)) { // Service logger.info(">>> Found service route: " + tm.toString() + " <<<"); - routeMete = new RouteMeta(route, element, RouteType.parse(SERVICE), null); + routeMeta = new RouteMeta(route, element, RouteType.parse(SERVICE), null); } else if (types.isSubtype(tm, fragmentTm) || types.isSubtype(tm, fragmentTmV4)) { logger.info(">>> Found fragment route: " + tm.toString() + " <<<"); - routeMete = new RouteMeta(route, element, RouteType.parse(FRAGMENT), null); + routeMeta = new RouteMeta(route, element, RouteType.parse(FRAGMENT), null); } else { throw new RuntimeException("ARouter::Compiler >>> Found unsupported class type, type = [" + types.toString() + "]."); } - categories(routeMete); + categories(routeMeta); // if (StringUtils.isEmpty(moduleName)) { // Hasn't generate the module name. // moduleName = ModuleUtils.generateModuleName(element, logger); // } From 6d8eb79cc4ad3a2c84d6129a523a84af94cf0e4e Mon Sep 17 00:00:00 2001 From: qiyi Date: Tue, 9 Jan 2018 17:54:24 +0800 Subject: [PATCH 10/13] compat for java8 --- .../com/alibaba/android/arouter/register/utils/ScanUtil.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/utils/ScanUtil.groovy b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/utils/ScanUtil.groovy index b2beb445..838bbb04 100644 --- a/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/utils/ScanUtil.groovy +++ b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/utils/ScanUtil.groovy @@ -44,7 +44,7 @@ class ScanUtil { } static boolean shouldProcessPreDexJar(String path) { - return path.endsWith("classes.jar") && !path.contains("com.android.support") && !path.contains("/android/m2repository") + return !path.contains("com.android.support") && !path.contains("/android/m2repository") } static boolean shouldProcessClass(String entryName) { From dff918c79ade5766ebaa9392284bdb9d3cc82bed Mon Sep 17 00:00:00 2001 From: qiyi Date: Wed, 17 Jan 2018 23:50:37 +0800 Subject: [PATCH 11/13] compat for windows folder --- .../android/arouter/register/core/RegisterTransform.groovy | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/core/RegisterTransform.groovy b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/core/RegisterTransform.groovy index 4d2a9680..17f696eb 100644 --- a/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/core/RegisterTransform.groovy +++ b/arouter-register/src/main/groovy/com/alibaba/android/arouter/register/core/RegisterTransform.groovy @@ -65,6 +65,7 @@ class RegisterTransform extends Transform { Logger.i('Start scan register info in jar file.') long startTime = System.currentTimeMillis() + boolean leftSlash = File.separator == '/' inputs.each { TransformInput input -> @@ -96,6 +97,9 @@ class RegisterTransform extends Transform { root += File.separator directoryInput.file.eachFileRecurse { File file -> def path = file.absolutePath.replace(root, '') + if (!leftSlash) { + path = path.replaceAll("\\\\", "/") + } if(file.isFile() && ScanUtil.shouldProcessClass(path)){ ScanUtil.scanClass(file) } From 992ec00e87962e6babd7f3fac71817e6e7e279cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AD=A3=E7=BA=AC?= Date: Sun, 11 Mar 2018 15:55:43 +0800 Subject: [PATCH 12/13] Add contributions --- README.md | 24 ++++++++++++++++++------ README_CN.md | 12 ++++++++++++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d6c0eff7..f0fee8b4 100644 --- a/README.md +++ b/README.md @@ -527,14 +527,14 @@ dependencies { 首先,Kotlin中的字段是可以自动注入的,但是注入代码为了减少反射,使用的字段赋值的方式来注入的,Kotlin默认会生成set/get方法,并把属性设置为private 所以只要保证Kotlin中字段可见性不是private即可,简单解决可以在字段上添加 @JvmField - + 6. 通过URL跳转之后,在intent中拿不到参数如何解决? - + 需要注意的是,如果不使用自动注入,那么可以不写 `ARouter.getInstance().inject(this)`,但是需要取值的字段仍然需要标上 `@Autowired` 注解,因为 只有标上注解之后,ARouter才能知道以哪一种数据类型提取URL中的参数并放入Intent中,这样您才能在intent中获取到对应的参数 7. 新增页面之后,无法跳转? - + ARouter加载Dex中的映射文件会有一定耗时,所以ARouter会缓存映射文件,直到新版本升级(版本号或者versionCode变化),而如果是开发版本(ARouter.openDebug()), ARouter 每次启动都会重新加载映射文件,开发阶段一定要打开 Debug 功能 @@ -543,9 +543,21 @@ dependencies { 1. 沟通和交流 1. 交流群1 (已满,请加2群) - + ![qq](https://raw.githubusercontent.com/alibaba/ARouter/master/demo/arouter-qq-addr.png) 2. 交流群2 - - ![qq](https://raw.githubusercontent.com/alibaba/ARouter/master/demo/qq-qrcode-2.JPG) \ No newline at end of file + + ![qq](https://raw.githubusercontent.com/alibaba/ARouter/master/demo/qq-qrcode-2.JPG) + +#### 九、代码贡献 (排名不分先后,时间顺序) + +1. [imknown](https://github.com/alibaba/ARouter/commits?author=imknown) : 优化文档格式 + +2. [crazy1235](https://github.com/crazy1235) : 自动注入支持优先使用默认值 + +3. [luckybilly](https://github.com/luckybilly) : 通过 Transform API 实现路由表自动注册 + +4. [LinXiaoTao](https://github.com/LinXiaoTao) : postcard transition support 0 + +5. [tanglie1993](https://github.com/tanglie1993) : 修正拼写和语法错误 diff --git a/README_CN.md b/README_CN.md index d15f919e..045c13af 100644 --- a/README_CN.md +++ b/README_CN.md @@ -549,3 +549,15 @@ dependencies { 2. 交流群2 ![qq](https://raw.githubusercontent.com/alibaba/ARouter/master/demo/qq-qrcode-2.JPG) + +#### 九、代码贡献 (排名不分先后,时间顺序) + +1. [imknown](https://github.com/alibaba/ARouter/commits?author=imknown) : 优化文档格式 + +2. [crazy1235](https://github.com/crazy1235) : 自动注入支持优先使用默认值 + +3. [luckybilly](https://github.com/luckybilly) : 通过 Transform API 实现路由表自动注册 + +4. [LinXiaoTao](https://github.com/LinXiaoTao) : postcard transition support 0 + +5. [tanglie1993](https://github.com/tanglie1993) : 修正拼写和语法错误 From bf94979a74e8acb00f5fa8e890bfa01f834b3245 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AD=A3=E7=BA=AC?= Date: Sun, 11 Mar 2018 15:58:40 +0800 Subject: [PATCH 13/13] update demo. --- demo/qq-qrcode-2.JPG | Bin 101133 -> 29256 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/demo/qq-qrcode-2.JPG b/demo/qq-qrcode-2.JPG index 0b2f7b73074147f46198e9b224d9f2b7432a2e91..87c157cb73c572757ba30a2e8ac5d692299ef67a 100644 GIT binary patch literal 29256 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 z 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 N(9;btyO{sq1OR>nm5BfV