hotwired / turbo-android

Android framework for making Turbo native apps
MIT License
408 stars 51 forks source link

Crash with API level 28 and below #240

Closed kiskoza closed 1 year ago

kiskoza commented 1 year ago

Hi. I was trying to run the demo with an emulator, but it was crashing over and over.

I opened up logcat and got this stack trace ``` Rejecting re-init on previously-failed class java.lang.Class: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/webkit/WebViewRenderProcessClient; at android.content.pm.PackageInfo androidx.webkit.WebViewCompat.getCurrentWebViewPackage(android.content.Context) (WebViewCompat.java:353) at java.lang.String dev.hotwire.turbo.views.TurboWebView.getPackageName() (TurboWebView.kt:38) at void dev.hotwire.turbo.session.TurboSession.initializeWebView() (TurboSession.kt:539) at void dev.hotwire.turbo.session.TurboSession.(java.lang.String, androidx.appcompat.app.AppCompatActivity, dev.hotwire.turbo.views.TurboWebView) (TurboSession.kt:89) at void dev.hotwire.turbo.session.TurboSessionNavHostFragment.createNewSession$turbo_debug() (TurboSessionNavHostFragment.kt:33) at void dev.hotwire.turbo.session.TurboSessionNavHostFragment.onCreate(android.os.Bundle) (TurboSessionNavHostFragment.kt:27) at void androidx.fragment.app.Fragment.performCreate(android.os.Bundle) (Fragment.java:2949) at void androidx.fragment.app.FragmentStateManager.create() (FragmentStateManager.java:475) at void androidx.fragment.app.FragmentStateManager.moveToExpectedState() (FragmentStateManager.java:278) at void androidx.fragment.app.FragmentManager.executeOpsTogether(java.util.ArrayList, java.util.ArrayList, int, int) (FragmentManager.java:2189) at void androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(java.util.ArrayList, java.util.ArrayList) (FragmentManager.java:2106) at void androidx.fragment.app.FragmentManager.execSingleAction(androidx.fragment.app.FragmentManager$OpGenerator, boolean) (FragmentManager.java:1971) at void androidx.fragment.app.BackStackRecord.commitNowAllowingStateLoss() (BackStackRecord.java:311) at void androidx.fragment.app.FragmentContainerView.(android.content.Context, android.util.AttributeSet, androidx.fragment.app.FragmentManager) (FragmentContainerView.java:176) at android.view.View androidx.fragment.app.FragmentLayoutInflaterFactory.onCreateView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet) (FragmentLayoutInflaterFactory.java:52) at android.view.View androidx.fragment.app.FragmentController.onCreateView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet) (FragmentController.java:135) at android.view.View androidx.fragment.app.FragmentActivity.dispatchFragmentsOnCreateView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet) (FragmentActivity.java:319) at android.view.View androidx.fragment.app.FragmentActivity.onCreateView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet) (FragmentActivity.java:298) at android.view.View android.view.LayoutInflater.createViewFromTag(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet, boolean) (LayoutInflater.java:780) at android.view.View android.view.LayoutInflater.createViewFromTag(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet) (LayoutInflater.java:730) at void android.view.LayoutInflater.rInflate(org.xmlpull.v1.XmlPullParser, android.view.View, android.content.Context, android.util.AttributeSet, boolean) (LayoutInflater.java:863) at void android.view.LayoutInflater.rInflateChildren(org.xmlpull.v1.XmlPullParser, android.view.View, android.util.AttributeSet, boolean) (LayoutInflater.java:824) at android.view.View android.view.LayoutInflater.inflate(org.xmlpull.v1.XmlPullParser, android.view.ViewGroup, boolean) (LayoutInflater.java:515) at android.view.View android.view.LayoutInflater.inflate(int, android.view.ViewGroup, boolean) (LayoutInflater.java:423) at android.view.View android.view.LayoutInflater.inflate(int, android.view.ViewGroup) (LayoutInflater.java:374) at void androidx.appcompat.app.AppCompatDelegateImpl.setContentView(int) (AppCompatDelegateImpl.java:696) at void androidx.appcompat.app.AppCompatActivity.setContentView(int) (AppCompatActivity.java:170) at void dev.hotwire.turbo.demo.main.MainActivity.onCreate(android.os.Bundle) (MainActivity.kt:14) at void android.app.Activity.performCreate(android.os.Bundle, android.os.PersistableBundle) (Activity.java:7136) at void android.app.Activity.performCreate(android.os.Bundle) (Activity.java:7127) at void android.app.Instrumentation.callActivityOnCreate(android.app.Activity, android.os.Bundle) (Instrumentation.java:1271) at android.app.Activity android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent) (ActivityThread.java:2893) at android.app.Activity android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.app.servertransaction.PendingTransactionActions, android.content.Intent) (ActivityThread.java:3048) at void android.app.servertransaction.LaunchActivityItem.execute(android.app.ClientTransactionHandler, android.os.IBinder, android.app.servertransaction.PendingTransactionActions) (LaunchActivityItem.java:78) at void android.app.servertransaction.TransactionExecutor.executeCallbacks(android.app.servertransaction.ClientTransaction) (TransactionExecutor.java:108) at void android.app.servertransaction.TransactionExecutor.execute(android.app.servertransaction.ClientTransaction) (TransactionExecutor.java:68) at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1808) at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:106) at void android.os.Looper.loop() (Looper.java:193) at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6669) at java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) (Method.java:-2) at void com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run() (RuntimeInit.java:493) at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:858) Caused by: java.lang.ClassNotFoundException: Didn't find class "android.webkit.WebViewRenderProcessClient" on path: DexPathList[[zip file "/data/app/dev.hotwire.turbo.demo-lJxUdEOq4Y35e9bT7pwTmQ==/base.apk"],nativeLibraryDirectories=[/data/app/dev.hotwire.turbo.demo-lJxUdEOq4Y35e9bT7pwTmQ==/lib/x86, /system/lib]] at java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:134) at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String, boolean) (ClassLoader.java:379) at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312) at android.content.pm.PackageInfo androidx.webkit.WebViewCompat.getCurrentWebViewPackage(android.content.Context) (WebViewCompat.java:353) at java.lang.String dev.hotwire.turbo.views.TurboWebView.getPackageName() (TurboWebView.kt:38) at void dev.hotwire.turbo.session.TurboSession.initializeWebView() (TurboSession.kt:539) at void dev.hotwire.turbo.session.TurboSession.(java.lang.String, androidx.appcompat.app.AppCompatActivity, dev.hotwire.turbo.views.TurboWebView) (TurboSession.kt:89) at void dev.hotwire.turbo.session.TurboSessionNavHostFragment.createNewSession$turbo_debug() (TurboSessionNavHostFragment.kt:33) at void dev.hotwire.turbo.session.TurboSessionNavHostFragment.onCreate(android.os.Bundle) (TurboSessionNavHostFragment.kt:27) at void androidx.fragment.app.Fragment.performCreate(android.os.Bundle) (Fragment.java:2949) at void androidx.fragment.app.FragmentStateManager.create() (FragmentStateManager.java:475) at void androidx.fragment.app.FragmentStateManager.moveToExpectedState() (FragmentStateManager.java:278) at void androidx.fragment.app.FragmentManager.executeOpsTogether(java.util.ArrayList, java.util.ArrayList, int, int) (FragmentManager.java:2189) at void androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(java.util.ArrayList, java.util.ArrayList) (FragmentManager.java:2106) at void androidx.fragment.app.FragmentManager.execSingleAction(androidx.fragment.app.FragmentManager$OpGenerator, boolean) (FragmentManager.java:1971) at void androidx.fragment.app.BackStackRecord.commitNowAllowingStateLoss() (BackStackRecord.java:311) at void androidx.fragment.app.FragmentContainerView.(android.content.Context, android.util.AttributeSet, androidx.fragment.app.FragmentManager) (FragmentContainerView.java:176) at android.view.View androidx.fragment.app.FragmentLayoutInflaterFactory.onCreateView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet) (FragmentLayoutInflaterFactory.java:52) at android.view.View androidx.fragment.app.FragmentController.onCreateView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet) (FragmentController.java:135) at android.view.View androidx.fragment.app.FragmentActivity.dispatchFragmentsOnCreateView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet) (FragmentActivity.java:319) at android.view.View androidx.fragment.app.FragmentActivity.onCreateView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet) (FragmentActivity.java:298) at android.view.View android.view.LayoutInflater.createViewFromTag(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet, boolean) (LayoutInflater.java:780) at android.view.View android.view.LayoutInflater.createViewFromTag(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet) (LayoutInflater.java:730) at void android.view.LayoutInflater.rInflate(org.xmlpull.v1.XmlPullParser, android.view.View, android.content.Context, android.util.AttributeSet, boolean) (LayoutInflater.java:863) at void android.view.LayoutInflater.rInflateChildren(org.xmlpull.v1.XmlPullParser, android.view.View, android.util.AttributeSet, boolean) (LayoutInflater.java:824) at android.view.View android.view.LayoutInflater.inflate(org.xmlpull.v1.XmlPullParser, android.view.ViewGroup, boolean) (LayoutInflater.java:515) at android.view.View android.view.LayoutInflater.inflate(int, android.view.ViewGroup, boolean) (LayoutInflater.java:423) at android.view.View android.view.LayoutInflater.inflate(int, android.view.ViewGroup) (LayoutInflater.java:374) at void androidx.appcompat.app.AppCompatDelegateImpl.setContentView(int) (AppCompatDelegateImpl.java:696) at void androidx.appcompat.app.AppCompatActivity.setContentView(int) (AppCompatActivity.java:170) at void dev.hotwire.turbo.demo.main.MainActivity.onCreate(android.os.Bundle) (MainActivity.kt:14) at void android.app.Activity.performCreate(android.os.Bundle, android.os.PersistableBundle) (Activity.java:7136) at void android.app.Activity.performCreate(android.os.Bundle) (Activity.java:7127) at void android.app.Instrumentation.callActivityOnCreate(android.app.Activity, android.os.Bundle) (Instrumentation.java:1271) at android.app.Activity android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent) (ActivityThread.java:2893) at android.app.Activity android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.app.servertransaction.PendingTransactionActions, android.content.Intent) (ActivityThread.java:3048) at void android.app.servertransaction.LaunchActivityItem.execute(android.app.ClientTransactionHandler, android.os.IBinder, android.app.servertransaction.PendingTransactionActions) (LaunchActivityItem.java:78) at void android.app.servertransaction.TransactionExecutor.executeCallbacks(android.app.servertransaction.ClientTransaction) (TransactionExecutor.java:108) at void android.app.servertransaction.TransactionExecutor.execute(android.app.servertransaction.ClientTransaction) (TransactionExecutor.java:68) at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1808) at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:106) at void android.os.Looper.loop() (Looper.java:193) at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6669) at java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) (Method.java:-2) at void com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run() (RuntimeInit.java:493) at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:858) ```

Based on the error messages above I found a reference page which says the missing class was introduced in API level 29. I checked my emulator and it was running on API 28, which is allowed by the both the package's and the demo's gradle file. When I switched over to API level 29, it went smoothly.

Unfortunately I'm not too familiar with android development, so the best I can do is move the minSdkVersions up to 29, but I hope there's a better solution than dropping support for older phones.


System details ``` > git status HEAD detached at 7.0.0-rc12 nothing to commit, working tree clean > gradle --version ------------------------------------------------------------ Gradle 6.5 ------------------------------------------------------------ Build time: 2020-06-02 20:46:21 UTC Revision: a27f41e4ae5e8a41ab9b19f8dd6d86d7b384dad4 Kotlin: 1.3.72 Groovy: 2.5.11 Ant: Apache Ant(TM) version 1.10.7 compiled on September 1 2019 JVM: 1.8.0_312 (Temurin 25.312-b07) OS: Linux 5.4.0-40-generic amd64 > avdmanager list target id: 2 or "android-28" Name: Android API 28 Type: Platform API level: 28 Revision: 6 ---------- id: 3 or "android-29" Name: Android API 29 Type: Platform API level: 29 Revision: 5 ```
weverwijk commented 1 year ago

We have the same issue. Users would like to use an Samsung Galaxy 8. This is not possible now.

kiskoza commented 1 year ago

Hi. I think I found the solution and it has nothing to do with the error I described above. I can still see the mentioned stack trace with logcat, but it's not the one causing the crash.

The real one was this one:

2022-09-05 19:40:43.426 4237-4237/dev.hotwire.turbo.demo E/AndroidRuntime: FATAL EXCEPTION: main
    Process: dev.hotwire.turbo.demo, PID: 4237
    java.lang.IllegalArgumentException: reasonPhrase can't be empty.
        at android.webkit.WebResourceResponse.setStatusCodeAndReasonPhrase(WebResourceResponse.java:139)
        at android.webkit.WebResourceResponse.<init>(WebResourceResponse.java:77)
        at xl.a(PG:292)
        at afG.handleMessage(PG:67)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

While I was searching for the meaning of this error trace, I found a chromium bug, which was fixed around 2019. I updated my Chrome on my emulator and the problem went away (as described here)

Sorry for the false alarm, I'm closing this off