androidandroid-jetpackandroid-architecture-navigationandroid-jetpack-navigationdynamic-feature-module

Resources$NotFoundException with include-dynamic navigation graph


I have a dynamic feature module with it's own nested navigation graph. I also have a dynamic feature module that's just a single fragment. If you have a dynamic feature module with it's own navigation graph, I understand you need to use the include-dynamic tag. When I build the app and deploy the app to the Play Store for internal testing, the dynamic modules download correctly. However If I and building/running locally - the app crashes when I try and navigate to the dynamic feature module that contains the navigation graph. I thought that everything was bundled when running locally? Is there something I'm missing?

The error I get is android.content.res.Resources$NotFoundException: com.xyz.app_name.two:navigation/two_navigation

main_navigation_graph

<!-- this works locally. module does not contain a nav graph -->
<fragment
    android:id="@+id/OneFragment"
    android:name="com.xyz.app_name.one.OneFragment"
    android:label="{nickname}"
    app:moduleName="one"
    tools:layout="@layout/one_fragment">
    <argument
        android:name="nickname"
        app:argType="string" />
</fragment>

<!-- this doesn't work locally -->
<include-dynamic
    android:id="@+id/two_graph"
    app:graphPackage="com.xyz.app_name.two"
    app:graphResName="two_navigation"
    app:moduleName="two" />

feature_two_graph

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@id/two_graph"
    app:moduleName="two"
    app:startDestination="@id/twoFragment">

    <fragment
        android:id="@+id/twoFragment"
        android:name="com.xyz.app_name.two.TwoFragment"
        android:label="{nickname}"
        tools:layout="@layout/two_fragment">
        <argument
            android:name="nickname"
            app:argType="string" />
        <action
            android:id="@+id/action_twoFragment_to_dialogFragment"
            app:destination="@id/dialogFragment" />
    </fragment>

    <dialog
        android:id="@+id/dialogFragment"
        android:name="com.xyz.app_name.two.ui.DialogFragment"
        android:label="bottom_sheet"
        tools:layout="@layout/bottom_sheet" />

</navigation>

Solution

  • I had the same problem.

    When trying to add a dynamic-feature graph as destination, using include-dynamic as follow:

    <include-dynamic
        android:id="@+id/nestedMyfeatureGraph"
        app:graphPackage="com.mycompany.myapp.mydynamicfeature"
        app:graphResName="nav_graph_feature"
        app:moduleName="mydynamicfeature"
        />
    

    one should keep in mind that app:graphPackage is supposed to reference the dynamic-feature's applicationId (I know, it's confusing). If you have any custom gradle script adding suffix to applicationId or stuff like that, then referencing the graph will fail.

    It probably only worked for you on playstore because I guess your script only adds suffix for non-prodRelease build types, which is a common pattern.

    So, to fix the problem I had to replace

        app:graphPackage="com.mycompany.myapp.mydynamicfeature"
    

    with

        app:graphPackage="${applicationId}.mydynamicfeature"