必须把客户端版本从ReactNative0.43版本升级到0.55版本;
必须把okhttp升级到最新的3.8.1版本
希望gradle从2.14.1升级从4.5.1版本;
升级ReactNative实际上和gradle没什么关系,关键在于:
reactnative 043版本依赖的okhttp是3.4.1版本; reactnative 055版本依赖的okhttp是3.8.1版本;;其中okio版本是:1.14.0;新增依赖org.conscrypt:conscrypt-openjdk-uber:1.1.4;
reactnative 043版本依赖的fresco是0.9.0版本;reactnative 055版本依赖的okhttp是1.5.0版本;而我们想用最新的1.11.0版本; 而1.11.0又不能应用在reactnative里边,有兼容性问题;
okhttp加入httpdns代码;fresco代码则进行了大量的改造;带来的问题是,合并代码的工作量和测试问题;
需要修改一些脚本,关键在于插件的兼容性,项目里使用了多个插件,anna,dilution,tinker,dexknife,aspectj,meetyoucost,blackhand等等; 需要解决兼容性问题;
从github合并完代码打包到内部仓库后,我们将okhttp升级到3.11.0,升级fresco到1.11.0;打包新的sdk版本;
从github合并完reactnative,打包到内部仓库;将reactnative从0.43升级到0.55,并依赖最新版本的sdk版本;
以上忽略合并细节和语法兼容性问题处理。至此,配置到主app上,我们迎来了第一个坑:
FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':app:transformClassesWithAnnaForZroTestDebug'. > SHA-256 digest error for org/conscrypt/NativeCrypto.class * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
编译时错误,我们查看了一下这个类,它是这样的:
/** * Provides the Java side of our JNI glue for OpenSSL. * <p> * Note: Many methods in this class take a reference to a Java object that holds a * native pointer in the form of a long in addition to the long itself and don't use * the Java object in the native implementation. This is to prevent the Java object * from becoming eligible for GC while the native method is executing. See * <a href="https://github.com/google/error-prone/blob/master/docs/bugpattern/UnsafeFinalization.md">this</a> * for more details. * * @hide */ @Internal public final class NativeCrypto {..}
是新版本的okhttp引入的一个库:compile “org.conscrypt:conscrypt-openjdk-uber:1.1.4”
其中这个类注解标明@Internal,标明内部类,不允许外部使用它,然后写了一大堆注释,总体感觉就是外部你不要用他,也不要修改他。 而我们的插桩库anan没有兼容这种情况,于是修改anna源码,新增-exclude { org/conscrypt/; },在transform的时候忽略该路径下了类即可;(不过后边我手动打了jar包,取代了aar依赖就没有这个问题了)
完了之后发现org.conscrypt:conscrypt-openjdk-uber里边的META-INFO有个x86的so库很大,过滤不掉,所以使用grep和zip -d命令删除它生成新的jar包
运行起来后,我们迎来了第二个坑,运行时闪退:
Process: com.melkana, PID: 11733 java.lang.NoSuchMethodError: No static method loadLibrary(Ljava/lang/String;)V in class Lcom/facebook/soloader/SoLoader; or its super classes (declaration of 'com.facebook.soloader.SoLoader' at com.facebook.react.bridge.ReactBridge.staticInit(ReactBridge.java:18) at com.facebook.react.bridge.NativeMap.(NativeMap.java:19)
意思就是在当前的reactnative使用的fresco里依赖的SoLoader里找不到这个这个方法,于是修改fresco源码,gradle.properites里的SOLOADER_VERSION降级,从0.5.1降级到0.4.1。 至此,客户端的ReactNative升级到0.54顺利解决(之后就是ReactNative JS端的升级)。
修改project/build.gradle:classpath ‘com.android.tools.build:gradle:3.0.1’
修改gradle/wrapper里的gradle-wrapper.properties里的distributionUrl为distributionUrl=https://services.gradle.org/distributions/gradle-4.5.1-all.zip
执行gradle clean assemlbeZroTestDebug生成apk;
* What went wrong: A problem occurred evaluating project ':app'. > Could not set unknown property 'enforceUniquePackageName' for object of type com.android.build.gradle.AppExtension. * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
enforceUniquePackageName 这个参数在插件3.0.1已经废弃,直接删除即可;在2.2.2如果没有这个参数可能会出现more than one library with package name ‘xxx’之类的错误;
FAILURE: Build failed with an exception. * What went wrong: A problem occurred configuring project ':app'. > All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com/r/tools/flavorDimensions-missing-error-message.html
意思是缺失flavor dimension ; 由于我们不需要更多的变种,所以在android.defaultConfig新增flavorDimensions “versionCode”即可,字符串可以随便填写;
FAILURE: Build failed with an exception. * Where: Build file '/Users/mu/MeiyouCode/PeriodProject/SeeyouClient/app/build.gradle' line: 473 * What went wrong: A problem occurred configuring project ':app'. > Failed to notify project evaluation listener. > Could not find method get() for arguments [0] on VariantOutput container of type org.gradle.api.internal.FactoryNamedDomainObjectContainer. > No such property: multiDex for class: com.android.build.gradle.internal.transforms.DexTransform * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
其中473行是长这样的:
472 android.applicationVariants.all { variant -> 473 variant.outputs.get(0).processManifest.doLast {
插件301版本不再提供方法,于是将其修改为:
android.applicationVariants.all { variant -> variant.outputs.all { output-> output.processManifest.doLast { ... } }
并且remove multiDexEnabled = true配置;301已默认配置;
FAILURE: Build failed with an exception. * Where: Build file '/Users/mu/MeiyouCode/PeriodProject/SeeyouClient/app/build.gradle' line: 473 * What went wrong: A problem occurred configuring project ':app'. > No such property: multiDex for class: com.android.build.gradle.internal.transforms.DexTransform * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
此错误是DexKnife插件造成的, 升级插件为:1.7.0.alpha版本即可
FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':app:javaPreCompileZroTestDebug'. > Annotation processors must be explicitly declared now. The following dependencies on the compile classpath are found to contain annotation processor. Please add them to the annotationProcessor configuration. - dagger-compiler-1.2.2.jar (com.squareup.dagger:dagger-compiler:1.2.2) - summer-compiler-2.0.6.jar (com.meiyou.framework:summer-compiler:2.0.6) - usopp-1.0.15.jar (com.meiyou:usopp:1.0.15) - auto-service-1.0-rc2.jar (com.google.auto.service:auto-service:1.0-rc2) Alternatively, set android.defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true to continue with previous behavior. Note that this option is deprecated and will be removed in the future. See https://developer.android.com/r/tools/annotation-processor-error-message.html for more details.
需要配置nanotationProecessor,在app/build.gradle新增如下代码即可:
annotationProcessor "com.meiyou.framework:summer-compiler:2.0.6" annotationProcessor "com.meiyou:usopp:1.0.15" annotationProcessor "com.google.auto.service:auto-service:1.0-rc2" annotationProcessor "com.tencent.tinker:tinker-android-anno:1.9.8"
并且在android.defaultConfig里加上javaCompileOptions { annotationProcessorOptions { includeCompileClasspath = true } }
FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':app:transformClassesWithDilutions-pluginForZroTestDebug'. > Unexpected scopes found in folder '/Users/mu/MeiyouCode/PeriodProject/SeeyouClient/app/build/intermediates/transforms/AspectTransform/zroTest/debug'. > > Required: SUB_PROJECTS. Found: EXTERNAL_LIBRARIES, PROJECT, SUB_PROJECTS FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':app:transformClassesWithAnnaForZroTestDebug'. > Unexpected scopes found in folder '/Users/mu/MeiyouCode/PeriodProject/SeeyouClient/app/build/intermediates/transforms/Dilutions-plugin/zroTest/debug'. Required: SUB_PROJECTS. Found: EXTERNAL_LIBRARIES, PROJECT, SUB_PROJECTS > >
意思是:我们在执行Dilution和Anna插件的时候,遇到一个scope不合法的问题;这是因为3.0.1修改了scope的定义。 scopes是transform 的作用域:
PROJECT 只处理当前项目 SUB_PROJECTS 只处理子项目 PROJECT_LOCAL_DEPS 只处理当前项目的本地依赖,例如jar, aar EXTERNAL_LIBRARIES 只处理外部的依赖库 PROVIDED_ONLY 只处理本地或远程以provided形式引入的依赖库
我们打开Dilution源码里的Scope方法改为:
@Override public Set<QualifiedContent.Scope> getScopes() { def name = QualifiedContent.Scope.PROJECT_LOCAL_DEPS.name() def deprecated = QualifiedContent.Scope.PROJECT_LOCAL_DEPS.getClass() .getField(name).getAnnotation(Deprecated.class) if (deprecated == null) { println "cannot find QualifiedContent.Scope.PROJECT_LOCAL_DEPS Deprecated.class " return Sets.immutableEnumSet(QualifiedContent.Scope.PROJECT , QualifiedContent.Scope.PROJECT_LOCAL_DEPS , QualifiedContent.Scope.EXTERNAL_LIBRARIES , QualifiedContent.Scope.SUB_PROJECTS , QualifiedContent.Scope.SUB_PROJECTS_LOCAL_DEPS) } else { println "find QualifiedContent.Scope.PROJECT_LOCAL_DEPS Deprecated.class " return Sets.immutableEnumSet(QualifiedContent.Scope.PROJECT , QualifiedContent.Scope.EXTERNAL_LIBRARIES , QualifiedContent.Scope.SUB_PROJECTS) } }
后续还涉及到aspectj升级问题; 以及dexknife的源码问题;
原理是遍历当前目录+解压zip包+grep搜索的,理论上一定是精确的,除非目录没覆盖掉,已经使用了很多次,可放心使用 目前仅支持aar依赖,如果要工程依赖,请自己配置搜索目录;
最近大家在7.1版本感受到了 运行时总会弹出“测试环境异常检测空指针”的错误。 这是因为做了一个功能对try catch进行拦截,可以支持异常类型配置,在anna_list.pro里配置的exceptions加入对应的exception类型就可以了 源码如下:
@Override public void visitTryCatchBlock(Label start, Label end, Label label, String exceptionTypeName) { if(exceptionTypeName!=null && isTargetException(exceptionTypeName) && label!=null){ //print(" ==>isTargetException"); ArrayList<String> exceptionList = matchedHandle.get(label); if(exceptionList == null) exceptionList = new ArrayList<>(); exceptionList.add(exceptionTypeName); matchedHandle.put(label, exceptionList); } super.visitTryCatchBlock(start, end, label, exceptionTypeName); } @Override public void visitLabel(Label label) { super.visitLabel(label); if(label!=null){ ArrayList<String> exceptionList = matchedHandle.get(label); if(exceptionList!=null){ Label matched = new Label(); Label end = new Label(); //捕获的是目标exception的实例才进行处理 final int N = exceptionList.size() - 1; if (N >= 1) { for (int i = 0; i < N; i++) { compareInstance(IFNE, exceptionList.get(i), matched); } } compareInstance(IFEQ, exceptionList.get(N), end); visitLabel(matched); dup(); //调用pushException方法 invokeStatic(Type.getObjectType("com/meetyou/anna/client/impl/AnnaManager") , new Method("handleException", "(Ljava/lang/Throwable;)V")); visitLabel(end); matchedHandle.remove(label); } } }