Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Navigation Library inflator throws ClassNotFoundException for data class

In the Navigation Library version alpha09+ (using alpha11) I am experiencing a ClassNotFoundException for one of my data classes which I defined as an argType in my navigation graph.

app:argType="com.package.app.data.model.user.User.Full"

This class does exist. When downgrading back to alpha08, the issue does not appear to happen.

This is the full stacktrace:

2019-01-28 10:30:32.028 6970-6970/com.package.app.debug E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.package.app.debug, PID: 6970
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.package.app.debug/com.package.app.ui.MainActivity}: android.view.InflateException: Binary XML file line #53: Binary XML file line #53: Error inflating class fragment
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
    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)
 Caused by: android.view.InflateException: Binary XML file line #53: Binary XML file line #53: Error inflating class fragment
 Caused by: android.view.InflateException: Binary XML file line #53: Error inflating class fragment
 Caused by: java.lang.RuntimeException: Exception inflating com.package.app.debug:navigation/navigation_main line 376
    at androidx.navigation.NavInflater.inflate(NavInflater.java:89)
    at androidx.navigation.NavController.setGraph(NavController.java:424)
    at androidx.navigation.NavController.setGraph(NavController.java:406)
    at androidx.navigation.fragment.NavHostFragment.onCreate(NavHostFragment.java:226)
    at androidx.fragment.app.Fragment.performCreate(Fragment.java:2414)
    at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1418)
    at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1684)
    at androidx.fragment.app.FragmentManagerImpl.addFragment(FragmentManager.java:1930)
    at androidx.fragment.app.FragmentManagerImpl.onCreateView(FragmentManager.java:3745)
    at androidx.fragment.app.FragmentController.onCreateView(FragmentController.java:120)
    at androidx.fragment.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:405)
    at androidx.fragment.app.FragmentActivity.onCreateView(FragmentActivity.java:387)
    at co.lokalise.android.sdk.core.LokaliseLayoutInflater$PrivateWrapperFactory2.onCreateView(LokaliseLayoutInflater.java:362)
    at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:186)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:780)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:863)
    at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:866)
    at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
    at co.lokalise.android.sdk.core.LokaliseLayoutInflater.inflate(LokaliseLayoutInflater.java:84)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
    at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:469)
    at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:140)
    at com.package.app.ui.MainActivity.onCreate(MainActivity.kt:75)
    at android.app.Activity.performCreate(Activity.java:7136)
    at android.app.Activity.performCreate(Activity.java:7127)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
2019-01-28 10:30:32.031 6970-6970/com.package.app.debug E/AndroidRuntime:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
    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)
 Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: com.package.app.data.model.user.User.Full
    at androidx.navigation.NavType.fromArgType(NavType.java:180)
    at androidx.navigation.NavInflater.inflateArgument(NavInflater.java:181)
    at androidx.navigation.NavInflater.inflateArgumentForDestination(NavInflater.java:145)
    at androidx.navigation.NavInflater.inflate(NavInflater.java:120)
    at androidx.navigation.NavInflater.inflate(NavInflater.java:131)
    at androidx.navigation.NavInflater.inflate(NavInflater.java:80)
        ... 41 more
 Caused by: java.lang.ClassNotFoundException: com.package.app.data.model.user.User.Full
    at java.lang.Class.classForName(Native Method)
    at java.lang.Class.forName(Class.java:453)
    at java.lang.Class.forName(Class.java:378)
    at androidx.navigation.NavType.fromArgType(NavType.java:168)
        ... 46 more
 Caused by: java.lang.ClassNotFoundException: Didn't find class "com.package.app.data.model.user.User.Full" on path: DexPathList[[zip file "/system/framework/org.apache.http.legacy.boot.jar", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/base.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_dependencies_apk.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_resources_apk.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_slice_0_apk.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_slice_1_apk.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_slice_2_apk.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_slice_3_apk.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_slice_4_apk.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_slice_5_apk.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_slice_6_apk.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_slice_7_apk.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_slice_8_apk.apk", zip file "/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_slice_9_apk.apk"],nativeLibraryDirectories=[/data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/lib/x86, /system/lib]]
    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
        ... 50 more
    Suppressed: java.io.IOException: No original dex files found for dex location /data/app/com.package.app.debug-7IobagfWCqi3XccTjnUgwg==/split_lib_resources_apk.apk
    at dalvik.system.DexFile.openDexFileNative(Native Method)
    at dalvik.system.DexFile.openDexFile(DexFile.java:354)
    at dalvik.system.DexFile.<init>(DexFile.java:101)
    at dalvik.system.DexFile.<init>(DexFile.java:75)
    at dalvik.system.DexPathList.loadDexFile(DexPathList.java:394)
    at dalvik.system.DexPathList.makeDexElements(DexPathList.java:354)
    at dalvik.system.DexPathList.<init>(DexPathList.java:164)
2019-01-28 10:30:32.031 6970-6970/com.package.app.debug E/AndroidRuntime:     at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:74)
    at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:65)
    at dalvik.system.PathClassLoader.<init>(PathClassLoader.java:64)
    at com.android.internal.os.ClassLoaderFactory.createClassLoader(ClassLoaderFactory.java:73)
    at com.android.internal.os.ClassLoaderFactory.createClassLoader(ClassLoaderFactory.java:88)
    at android.app.ApplicationLoaders.getClassLoader(ApplicationLoaders.java:74)
    at android.app.ApplicationLoaders.getClassLoader(ApplicationLoaders.java:40)
    at android.app.LoadedApk.createOrUpdateClassLoaderLocked(LoadedApk.java:727)
    at android.app.LoadedApk.getClassLoader(LoadedApk.java:810)
    at android.app.LoadedApk.getResources(LoadedApk.java:1032)
    at android.app.ContextImpl.createAppContext(ContextImpl.java:2345)
    at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5749)
    at android.app.ActivityThread.access$1100(ActivityThread.java:199)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1650)
            ... 6 more

I have updated the Navigation Library component from alpha08 to alpha11. When they released alpha09, I also updated and had this same issue and thought it was a bug, so I waited. Now, the issue still persists and I can't seem to be able to figure out want went wrong.

I have already disabled ProGuard for debugging, as well as minify and have enabled Multidex to see if this would help.

    debug {
        minifyEnabled false
        useProguard false
        versionNameSuffix '-DEBUG'
        applicationIdSuffix '.debug'
    }

The class has also been added to the proguard-rules, to see if that would work.

-keep class com.package.app.data.model.** { *; } 

As far as I'm concerned, this should work? Android Studio also generates the XML for me exactly like this.

Thanks in advance.

like image 765
Bjarn Bronsveld Avatar asked Jan 28 '19 09:01

Bjarn Bronsveld


2 Answers

After all, it was a known bug in Android Studio.

Since the release of 1.0.0-alpha09, something changed in the way they handled inner classes.

If a parcelable is an inner class, it has to be written like: com.domain.app.User$Full where Full is the parcelized object.

If you want to read more about this, check out this answer on Google's Issue Tracker: https://issuetracker.google.com/u/2/issues/123614632#comment4

like image 124
Bjarn Bronsveld Avatar answered Nov 03 '22 01:11

Bjarn Bronsveld


Just faced problem similar to this issue and I got realized I didn't set up any proguard rules. Here's additional information that might be helpful.

The following codes are found in navigation component version 2.2.0-rc02.

// NavType.java
try {
    String className;
    if (type.startsWith(".") && packageName != null) {
        className = packageName + type;
    } else {
        className = type;
    }

    if (type.endsWith("[]")) {
        className = className.substring(0, className.length() - 2);
        Class<?> clazz = Class.forName(className);
        if (Parcelable.class.isAssignableFrom(clazz)) {
            return new ParcelableArrayType(clazz);
        } else if (Serializable.class.isAssignableFrom(clazz)) {
            return new SerializableArrayType(clazz);
        }
    } else {
        Class<?> clazz = Class.forName(className);
        if (Parcelable.class.isAssignableFrom(clazz)) {
            return new ParcelableType(clazz);
        } else if (Enum.class.isAssignableFrom(clazz)) {
            return new EnumType(clazz);
        } else if (Serializable.class.isAssignableFrom(clazz)) {
            return new SerializableType(clazz);
        }
    }
    throw new IllegalArgumentException(className + " is not Serializable or "
            + "Parcelable.");
} catch (ClassNotFoundException e) {
    throw new RuntimeException(e);
}

You can see it looks for classes using Class.forName(String) method. So keeping their names is enough.

# Instead of -keep
-keepnames class com.package.app.data.model.** { *; }

And if packageName is provided, you can omit package name from value of argType attribute, but sadly it won't work if you use some application id suffixes depending on build variants. (So do not omit package name from argType)

like image 26
Tura Avatar answered Nov 02 '22 23:11

Tura