Closed timbotimbo closed 7 months ago
Thanks for your usual high quality bug report!
I've just pushed your workaround to a new branch bug/issue15 with a conditional check so it only runs the reflection if it's <Android 9. I don't have any Android 8 devices to test this with, would appreciate if you could check this fixes the issue (I've also updated the dependencies to point to local paths, so you should just be able to run the example project in the android sub-package)
The issue15 branch fixes the crash on my Android 7 device, but actually breaks on Android >= 9.
Android <9: Unity can't access the hidePreservedContent function and crashes.
Android > 8: Unity does manage to call the internal hidePreservedContent function.
Ideally you would want to do conditional compilation like possible in C#, but is seems like kotlin doesn't support this.
#if android < 9
fun hidePreservedContent() { ... }
#endif
I've also seen someone on the flutter_unity_widget discord having freezing issues on resume (like in my video), that were resolved once he upgraded from 2022.3.16 to 2022.3.20.
This sounds like it is caused by the same issue except that his app didn't crash.
He got the issue on an Android 8 phone and Android 11 emulator.
So there might be more devices affected in a different way, but I haven't been able to reproduce that yet.
Thanks for the update - I found an old Motorola with Android 5.1 and I can now reproduce the issue, and I see what you mean about it breaking on Android > 8.
As far as I know conditional compilation based on Android SDK isn't possible because at compile time you don't know the version of Android, it has to be a runtime check.
So it looks like the options are:
For 2, I took a copy of /Applications/Unity/Hub/Editor/2022.3.20f1/PlaybackEngines/AndroidPlayer/Variations/mono/Development/Classes/classes.jar, unzipped, and opened in Android Studio (it decompiles class files). The decompiled version of the function in UnityPlayer.class
is very simple, it is just this:
private void hidePreservedContent() {
c var1;
var1 = new c.<init>(this);
this.runOnUiThread(var1);
}
I checked Unity 2022.3.9, this function does not exist. It does exist in 2022.3.13 and 2022.3.20, and is the same in both.
The only problem is I can't figure out what c
might refer to. Something that you create, pass UnityPlayer instance to it, and run it. If anyone who is better than me at reading decompiled code can figure out what this is, we can probably just replicate the function and avoid using reflection. On the other hand, it may make the package more brittle to changes in future versions of Unity (i.e. if this function changes), so maybe refection is the better choice anyway?
I feel like replicating the internals is just looking for trouble. I wouldn't be surprised if it breaks again without even a changelog mention in the next Unity release.
A third option would be to make people use >= 2022.3.19 as it seems to be fixed there. But given that there is no bugfix documented anywhere, this might just be an accidental fix that breaks again in the future.
On balance I think it's best to go with your third option. I've just published version 1.0.4 with these details in the README. Thanks for your help!
Description
I'm reposting this issue because it affects this plugin too.
On some Unity versions, android devices on Android 8 or lower will immediately crash when Unity is started.
Breaking change
I tested multiple Unity versions to find the exact version that breaks this.
The crash starts at Unity 2021.3.31 and 2022.3.10.
Both these versions have this entry in the changelog, that seems like the culprit.
As of 2022.3.19 this crash no longer happens, but there is nothing mentioned in the Unity changelog.
It's your choice to either add a workaround that might become redundant or tell people to upgrade to 2022.3.19+
Reproduction
Workaround
For affected versions, you can avoid the crash by defining the missing function and calling the private function using reflection.
This fixes the crash on Android <= 8 and doesn't change any behavior on higher android versions.
I haven't benchmarked this, but it might introduce a some milliseconds delay on Android 9+ as you add a reflection call that isn't otherwise needed.
Versions
❌ indicates a crash.
Unity: 2022.3.0 ✔
2022.3.9 ✔
2022.3.10 ❌
2022.3.14 ❌ 2022.3.15 ❌ 2022.3.18 ❌ 2022.3.19 ✔ 2022.3.20 ✔
Android: Android 6 ❌
Android 7.1.2 ❌
Android 8 ❌ (reported) Android 9 ✔ Android 13 ✔
Devices: This seems to happen on any device on Android <= 8.
Logs
Log Unity 2022.3.18, Android 7
``` E/AndroidRuntime( 5807): FATAL EXCEPTION: UnityMain E/AndroidRuntime( 5807): Process: com.learntoflutter.flutter_embed_unity_example, PID: 5807 E/AndroidRuntime( 5807): java.lang.Error: FATAL EXCEPTION [UnityMain] E/AndroidRuntime( 5807): Unity version : 2022.3.18f1 E/AndroidRuntime( 5807): Device model : Wileyfox Wileyfox Swift E/AndroidRuntime( 5807): Device fingerprint: Wileyfox/Swift/crackling:7.1.2/N2G48B/eeea277114:user/release-keys E/AndroidRuntime( 5807): CPU supported ABI : [arm64-v8a, armeabi-v7a, armeabi] E/AndroidRuntime( 5807): Build Type : Release E/AndroidRuntime( 5807): Scripting Backend : IL2CPP E/AndroidRuntime( 5807): Libs loaded from : lib/arm64 E/AndroidRuntime( 5807): Strip Engine Code : true E/AndroidRuntime( 5807): E/AndroidRuntime( 5807): Caused by: java.lang.NoSuchMethodError: no non-static method "Lcom/learntoflutter/flutter_embed_unity_android/unity/UnityPlayerSingleton;.hidePreservedContent()V" E/AndroidRuntime( 5807): at com.unity3d.player.UnityPlayer.nativeRender(Native Method) E/AndroidRuntime( 5807): at com.unity3d.player.UnityPlayer.-$$Nest$mnativeRender(Unknown Source) E/AndroidRuntime( 5807): at com.unity3d.player.UnityPlayer$F$a.handleMessage(Unknown Source) E/AndroidRuntime( 5807): at android.os.Handler.dispatchMessage(Handler.java:98) E/AndroidRuntime( 5807): at android.os.Looper.loop(Looper.java:154) E/AndroidRuntime( 5807): at com.unity3d.player.UnityPlayer$F.run(Unknown Source) ```