介绍

项目需要接入一个第三方的 AAR 格式 SDK,由于使用的 Unity 5.3.8f2 不支持 AAR 格式 SDK,因此只能使用 Jar 格式接入。 因此尝试将 aar 中的 jar 文件提取出来,然后使用 Android Studio 与桥接文件编译成桥接 jar 使用。 将 aar 中的所有 jar 文件与桥接 jar 文件都放到 Unity 项目中 Assets/Plugins/Android/libs 打包。

但是在真机上运行时,报错:java.lang.NoClassDefFoundError: com.sdk.ui.fragments.RequestPermissionFragment

环境

  • Unity 5.3.8f2
  • Android Studio 3.6.3

问题日志

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
 539  1029 I ActivityManager: Start proc 2304:com.test.example/u0a64 for activity com.test.example/.MainActivity
2304  2304 I art     : Late-enabling JIT
2304  2304 W art     : Unexpected CPU variant for X86 using defaults: x86
2304  2304 I art     : JIT created with code_cache_capacity=2MB compile_threshold=1000
2304  2304 I Zygote  : fake Product info com.test.example not matched any pattern
2304  2304 D Activity: on create, cpu abi: x86, brand: Android
2304  2304 W Unity   : Failed to get permission info for android.permission.SYSTEM_OVERLAY_WINDOW, manifest likely missing custom permission declaration
2304  2304 W Unity   : Permission android.permission.SYSTEM_OVERLAY_WINDOW ignored
2304  2304 W Unity   : Failed to get permission info for com.android.launcher.permission.READ_SETTINGS, manifest likely missing custom permission declaration
2304  2304 W Unity   : Permission com.android.launcher.permission.READ_SETTINGS ignored
2304  2304 I art     : Rejecting re-init on previously-failed class java.lang.Class<com.sdk.ui.HFragment>
2304  2304 I art     : Rejecting re-init on previously-failed class java.lang.Class<com.sdk.ui.HFragment>
2304  2304 I art     : Rejecting re-init on previously-failed class java.lang.Class<com.sdk.ui.fragments.RequestPermissionFragment>
2304  2304 I art     : Rejecting re-init on previously-failed class java.lang.Class<com.sdk.ui.fragments.RequestPermissionFragment>
2304  2304 I art     : Rejecting re-init on previously-failed class java.lang.Class<com.sdk.ui.HFragmentActivity>
2304  2304 I art     : Rejecting re-init on previously-failed class java.lang.Class<com.sdk.ui.HFragmentActivity>
2304  2304 I art     : Rejecting re-init on previously-failed class java.lang.Class<com.sdk.ui.SDKFragmentActivity>
2304  2304 I art     : Rejecting re-init on previously-failed class java.lang.Class<com.sdk.ui.SDKFragmentActivity>
2304  2304 I art     : Rejecting re-init on previously-failed class java.lang.Class<com.sdk.ui.CommonWebActivity>
2304  2304 I art     : Rejecting re-init on previously-failed class java.lang.Class<com.sdk.ui.CommonWebActivity>
2304  2304 W Module$KernelHolder$1: Compiler lib init failed.
2304  2304 W art     : Method processed more than once: org.json.JSONObject com.sdk.engine.SDKPlatform.parseConfig(android.content.Context)
2304  2304 W SDKPlatform: on Android 6.0 , try request permission.
2304  2304 I art     : Rejecting re-init on previously-failed class java.lang.Class<com.sdk.ui.fragments.RequestPermissionFragment>
2304  2304 D AndroidRuntime: Shutting down VM
2304  2304 E AndroidRuntime: FATAL EXCEPTION: main
2304  2304 E AndroidRuntime: Process: com.test.example, PID: 2304
2304  2304 E AndroidRuntime: java.lang.Error: FATAL EXCEPTION [main]
2304  2304 E AndroidRuntime: Unity version     : 5.3.8f1
2304  2304 E AndroidRuntime: Device model      : Netease MuMu
2304  2304 E AndroidRuntime: Device fingerprint: OnePlus/OnePlus2/OnePlus2:6.0.1/MMB29M/1447841200:user/release-keys
2304  2304 E AndroidRuntime:
2304  2304 E AndroidRuntime: Caused by: java.lang.NoClassDefFoundError: com.sdk.ui.fragments.RequestPermissionFragment
2304  2304 E AndroidRuntime:     at com.sdk.engine.SDKPlatform.init(SDKPlatform.java:69)
2304  2304 E AndroidRuntime:     at com.test.example.MainActivity.onCreate(MainActivity.java:53)
2304  2304 E AndroidRuntime:     at android.app.Activity.performCreate(Activity.java:6279)
2304  2304 E AndroidRuntime:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
2304  2304 E AndroidRuntime:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2396)
2304  2304 E AndroidRuntime:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2503)
2304  2304 E AndroidRuntime:     at android.app.ActivityThread.-wrap11(ActivityThread.java)
2304  2304 E AndroidRuntime:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1353)
2304  2304 E AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:102)
2304  2304 E AndroidRuntime:     at android.os.Looper.loop(Looper.java:148)
2304  2304 E AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5539)
2304  2304 E AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method)
2304  2304 E AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:745)
2304  2304 E AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:635)
 539   573 D ActivityManager: Nemu don't show crash dialog of ProcessRecord{512695c 2304:com.test.example/u0a64}
2304  2304 I Process : Sending signal. PID: 2304 SIG: 9
 539   554 I ActivityManager: Process com.test.example (pid 2304) has died
 539   554 D ActivityManager: cleanUpApplicationRecord -- 2304

问题分析

阶段一

一开始只注意到了 java.lang.NoClassDefFoundError 错误,因此搜索得到的结果都不是相关的

由于使用 Android Studio 分析打包出来的 APK 时可以看到 classes.dex 中存在 com.sdk.ui.fragments.RequestPermissionFragment 代码。

另外在分析时也同时排除了 MultiDex 问题,因为 classes.dex 中的方法数量并未超过 65535。

阶段二

NoClassDefFoundError 一般是属于 Link Error,主要是由于打包之后缺失文件导致的,例如 new 一个对象。

这篇文章提到了缺失文件的问题,仔细查看上面的日志可以发现 art 报的一些问题:

1
I art     : Rejecting re-init on previously-failed class java.lang.Class<com.sdk.ui.fragments.RequestPermissionFragment>

也就是说这些类在加载时依赖项不存在导致初始化失败,进而引起了下面的报错。

修复

向上游 SDK 提供商索要了 Eclipse 版本的 SDK,内部包含所有的依赖库,放进 Unity 中打包测试通过。