Android Instant Apps:将现有的multidex应用程序迁移到基础/功能模块?

时间:2017-05-28 17:39:07

标签: android android-studio-3.0 android-instant-apps

我正在将现有的多dex应用程序迁移到Instant应用程序中,并将我的应用程序转换为推荐的project structure

有一堆相关的编译问题已经成功解决,但是在尝试运行可安装的“应用程序”模块时,我遇到了如下所示的堆栈跟踪错误。

我怀疑这是因为我现在的baseFeature模块(之前的多dex应用程序)与即时应用程序架构不兼容。

任何有关处理此问题的最佳方法的线索?如果有人能够指出现有的multidex应用程序将如何移植到新的即时应用程序架构,那将会非常棒:)

堆栈追踪:

Error converting bytecode to dex:
Cause: InvokeDynamic not supported
com.android.dx.cf.iface.ParseException: InvokeDynamic not supported
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:593)
    at java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:677)
    at java.util.concurrent.ForkJoinTask.join(ForkJoinTask.java:720)
    at com.android.ide.common.internal.WaitableExecutor.waitForTasksWithQuickFail(WaitableExecutor.java:146)
    at com.android.builder.dexing.DexArchiveBuilder.processOutputs(DexArchiveBuilder.java:110)
    at com.android.builder.dexing.DexArchiveBuilder.convert(DexArchiveBuilder.java:91)
    at com.android.build.gradle.internal.transforms.DexArchiveBuilderTransformCallable.lambda$cacheMissAction$0(DexArchiveBuilderTransformCallable.java:236)
    at com.android.builder.utils.FileCache.lambda$createFile$1(FileCache.java:260)
    at com.android.builder.utils.FileCache.lambda$null$5(FileCache.java:443)
    at com.android.builder.utils.SynchronizedFile.doActionWithSingleProcessLocking(SynchronizedFile.java:291)
    at com.android.builder.utils.SynchronizedFile.write(SynchronizedFile.java:234)
    at com.android.builder.utils.FileCache.lambda$queryCacheEntry$6(FileCache.java:415)
    at com.android.builder.utils.SynchronizedFile.doActionWithSingleProcessLocking(SynchronizedFile.java:291)
    at com.android.builder.utils.SynchronizedFile.read(SynchronizedFile.java:217)
    at com.android.builder.utils.FileCache.queryCacheEntry(FileCache.java:391)
    at com.android.builder.utils.FileCache.createFile(FileCache.java:273)
    at com.android.build.gradle.internal.transforms.DexArchiveBuilderTransformCallable.getFromCacheAndCreateIfMissing(DexArchiveBuilderTransformCallable.java:185)
    at com.android.build.gradle.internal.transforms.DexArchiveBuilderTransformCallable.call(DexArchiveBuilderTransformCallable.java:147)
    at com.android.build.gradle.internal.transforms.DexArchiveBuilderTransformCallable.call(DexArchiveBuilderTransformCallable.java:53)
    at java.util.concurrent.ForkJoinTask$AdaptedCallable.exec(ForkJoinTask.java:1424)
    at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
    at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
    at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
    at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Caused by: com.android.dx.cf.iface.ParseException: InvokeDynamic not supported
    at com.android.dx.cf.cst.ConstantPoolParser.determineOffsets(ConstantPoolParser.java:226)
    at com.android.dx.cf.cst.ConstantPoolParser.parse(ConstantPoolParser.java:132)
    at com.android.dx.cf.cst.ConstantPoolParser.parseIfNecessary(ConstantPoolParser.java:124)
    at com.android.dx.cf.cst.ConstantPoolParser.getPool(ConstantPoolParser.java:115)
    at com.android.dx.cf.direct.DirectClassFile.parse0(DirectClassFile.java:491)
    at com.android.dx.cf.direct.DirectClassFile.parse(DirectClassFile.java:406)
    at com.android.dx.cf.direct.DirectClassFile.parseToInterfacesIfNecessary(DirectClassFile.java:388)
    at com.android.dx.cf.direct.DirectClassFile.getMagic(DirectClassFile.java:251)
    at com.android.builder.dexing.DexArchiveBuilderCallable.parseClass(DexArchiveBuilderCallable.java:86)
    at com.android.builder.dexing.DexArchiveBuilderCallable.call(DexArchiveBuilderCallable.java:70)
    at com.android.builder.dexing.DexArchiveBuilderCallable.call(DexArchiveBuilderCallable.java:43)
    ... 5 more
...while preparsing cst 0032 at offset 000000f1
...while parsing RangeDialogFragment.class

Execution failed for task ':installapp:transformClassesWithDexBuilderForDebug'.
    com.android.build.api.transform.TransformException:  java.lang.RuntimeException: java.lang.RuntimeException:  java.util.concurrent.ExecutionException:  java.util.concurrent.ExecutionException:  com.android.builder.utils.FileCache$FileCreatorException:  
    com.android.builder.dexing.DexArchiveBuilder$DexBuilderException: Unable to convert input to dex archive.

1 个答案:

答案 0 :(得分:1)

功能模块目前不支持multidex,因此每个功能模块应使用单个dex。

此问题没有通用解决方案,但我可以提出一些建议。

  1. 尝试将UI代码从基本功能模块移动到另一个功能模块。 Android支持库对方法计数的影响最大,因此将支持库从基本功能移动到ui-feature模块应该会有所帮助。
  2. Play Services是影响方法计数的另一个主要库。如果可以,请不要添加整个播放服务sdk,而是使用它的子集。
  3. 使用Apk Analyzer或DexCount精确定位使用最多方法的库,并尝试将它们移动到单独的功能模块中。
  4. Proguard的。缩小应该能够删除未使用的方法并帮助您将基本模块放在单个dex中。然而,Proguard目前在即时应用方面存在很大问题。您需要为每个模块创建额外的proguard规则。