Tencent / tinker

Tinker is a hot-fix solution library for Android, it supports dex, library and resources update without reinstall apk.
Other
17.13k stars 3.33k forks source link

dex方法超过65536无法正常使用tinker #1458

Open flk123 opened 4 years ago

flk123 commented 4 years ago
异常类型:编译异常
tinker版本:1.9.14.7
gradle版本:3.2.1
是否使用热更新SDK:Tinker
系统:Win 7

主dex方法超过65536编译版本时出现Cannot fit requested classes in the main-dex file (# methods: 66478 > 65536)
修改成以下配置:
android.enableD8.desugaring=false
android.useDexArchive=false

更新gradle时出现异常
No signature of method: com.android.build.gradle.internal.scope.BuildArtifactsHolder$FinalBuildableArtifact.getSingleFile() is applicable for argument types: () values: []

最后确定是 keepDexApply = true导致的
然后我把keepDexApply = false,编译成功

但是在执行生成补丁任务时出现异常
Check for loader classes in dex: classes.dex
Collect class descriptors in classes.dex
Check for loader classes in dex: classes2.dex
Collect class descriptors in classes2.dex
Check for loader classes in dex: classes3.dex
Collect class descriptors in classes3.dex
Check if loader classes in classes.dex refer to any classes that is not in loader class patterns.
FATAL: method 'getExceptionCauseString:LL' in loader class 'Lcom/tencent/tinker/loader/shareutil/ShareTinkerInternals;' refers to method 'printStackTrace:VLL' in class 'Lcom/google/devtools/build/android/desugar/runtime/ThrowableExtension;' which is not in loader class, this may cause crash when patch is loaded.
FATAL: method 'checkComplete:ZLLL' in loader class 'Lcom/tencent/tinker/loader/TinkerArkHotLoader;' refers to method 'printStackTrace:VL' in class 'Lcom/google/devtools/build/android/desugar/runtime/ThrowableExtension;' which is not in loader class, this may cause crash when patch is loaded.
FATAL: method '<clinit>:V' in loader class 'Lcom/tencent/tinker/loader/hotplug/handler/AMSInterceptHandler;' refers to method 'printStackTrace:VL' in class 'Lcom/google/devtools/build/android/desugar/runtime/ThrowableExtension;' which is not in loader class, this may cause crash when patch is loaded.
FATAL: method 'fixIntentClassLoader:VLL' in loader class 'Lcom/tencent/tinker/loader/shareutil/ShareIntentUtil;' refers to method 'printStackTrace:VL' in class 'Lcom/google/devtools/build/android/desugar/runtime/ThrowableExtension;' which is not in loader class, this may cause crash when patch is loaded.

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:tinkerPatchRelease'.
> com.tencent.tinker.build.util.TinkerPatchException: There are fatal reasons that cause Tinker interrupt patch generating procedure, see logs above.

我看过两个apk,里面主dex包是有这个类和方法的,现在不知道怎么解决了,有没有大佬帮忙以下。
pxc0215 commented 3 years ago

tinker 新版本规则造成的,我用的解决方法:在 gradle 中加入以下代码:

  tasks.whenTaskAdded { task ->
        android.applicationVariants.all { variant ->
            if (task.name == "tinkerProcess${variant.name.capitalize()}MultidexKeep") {
                task.finalizedBy "fixTinkerDexKeepProguardFor${variant.name.capitalize()}"
            }
        }
    }

    android.applicationVariants.all { variant ->
        Task fixTinkerDexKeepProguard = task("fixTinkerDexKeepProguardFor${variant.name.capitalize()}")
        fixTinkerDexKeepProguard.doLast {
            def tinkerMultidexKeepTask = project.tasks.findByName("tinkerProcess${variant.name.capitalize()}MultidexKeep")
            def multiDexKeepProguardFile = file(tinkerMultidexKeepTask.multiDexKeepProguard)
            def lines = []
            // 记录从某条规则开始,后面需要跳过几行
            def skipLines = 0
            multiDexKeepProguardFile.text.eachLine { line ->
                if (line.contains("-keep class com.tencent.tinker.entry.TinkerApplicationInlineFence")) {
                    skipLines = 2
                } else if (skipLines > 0) {
                    skipLines--
                } else {
                    lines.add(line)
                }
            }

            FileWriter fr = new FileWriter(multiDexKeepProguardFile, false)
            try {
                for (String line : lines) {
                    fr.write(line)
                    fr.write("\n")
                }
            } finally {
                fr.close()
            }
        }
    }
XcJKing commented 3 years ago

tinker 新版本规则造成的,我用的解决方法:在 gradle 中加入以下代码:

  tasks.whenTaskAdded { task ->
        android.applicationVariants.all { variant ->
            if (task.name == "tinkerProcess${variant.name.capitalize()}MultidexKeep") {
                task.finalizedBy "fixTinkerDexKeepProguardFor${variant.name.capitalize()}"
            }
        }
    }

    android.applicationVariants.all { variant ->
        Task fixTinkerDexKeepProguard = task("fixTinkerDexKeepProguardFor${variant.name.capitalize()}")
        fixTinkerDexKeepProguard.doLast {
            def tinkerMultidexKeepTask = project.tasks.findByName("tinkerProcess${variant.name.capitalize()}MultidexKeep")
            def multiDexKeepProguardFile = file(tinkerMultidexKeepTask.multiDexKeepProguard)
            def lines = []
            // 记录从某条规则开始,后面需要跳过几行
            def skipLines = 0
            multiDexKeepProguardFile.text.eachLine { line ->
                if (line.contains("-keep class com.tencent.tinker.entry.TinkerApplicationInlineFence")) {
                    skipLines = 2
                } else if (skipLines > 0) {
                    skipLines--
                } else {
                    lines.add(line)
                }
            }

            FileWriter fr = new FileWriter(multiDexKeepProguardFile, false)
            try {
                for (String line : lines) {
                    fr.write(line)
                    fr.write("\n")
                }
            } finally {
                fr.close()
            }
        }
    }

有没有测试过?会不会影响热修复?

pxc0215 commented 3 years ago

tinker 新版本规则造成的,我用的解决方法:在 gradle 中加入以下代码:

  tasks.whenTaskAdded { task ->
        android.applicationVariants.all { variant ->
            if (task.name == "tinkerProcess${variant.name.capitalize()}MultidexKeep") {
                task.finalizedBy "fixTinkerDexKeepProguardFor${variant.name.capitalize()}"
            }
        }
    }

    android.applicationVariants.all { variant ->
        Task fixTinkerDexKeepProguard = task("fixTinkerDexKeepProguardFor${variant.name.capitalize()}")
        fixTinkerDexKeepProguard.doLast {
            def tinkerMultidexKeepTask = project.tasks.findByName("tinkerProcess${variant.name.capitalize()}MultidexKeep")
            def multiDexKeepProguardFile = file(tinkerMultidexKeepTask.multiDexKeepProguard)
            def lines = []
            // 记录从某条规则开始,后面需要跳过几行
            def skipLines = 0
            multiDexKeepProguardFile.text.eachLine { line ->
                if (line.contains("-keep class com.tencent.tinker.entry.TinkerApplicationInlineFence")) {
                    skipLines = 2
                } else if (skipLines > 0) {
                    skipLines--
                } else {
                    lines.add(line)
                }
            }

            FileWriter fr = new FileWriter(multiDexKeepProguardFile, false)
            try {
                for (String line : lines) {
                    fr.write(line)
                    fr.write("\n")
                }
            } finally {
                fr.close()
            }
        }
    }

有没有测试过?会不会影响热修复?

在 Android 5.0 及以上手机上试过,是可以的;5.0 以下不行,启动会崩溃!可以通过将 MultiDex.install 搞到 Tinker 初始化前面解决。