148

I use navigation library and safeargs for passing data. I define argument to fragment like that.

<fragment
        android:id="@+id/otherFragment"
        android:name="com.asd.navigate.OtherFragment"
        android:label="OtherFragment">
        <argument
            android:name="screenTitle"
            android:defaultValue="0"
            app:type="string" />
    </fragment>

OtherFragmentArgs generated, I can use it but OtherFragmentDirection class doesnt generate when I click "make project". Is that bug or I have to do something different.

Thnx for advice.

buildscript {
    ...
    dependencies {
       ...
        classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0-alpha01"

    }
}

build.gradle

apply plugin: "androidx.navigation.safeargs"

MainActivity.kt

enter image description here

6155031
  • 4,171
  • 6
  • 27
  • 56

28 Answers28

100

I forgot to apply plugin in app.gradle file, just add this line

apply plugin: "androidx.navigation.safeargs.kotlin"

or this line if you are using java

apply plugin: "androidx.navigation.safeargs"
Sanjeev
  • 4,255
  • 3
  • 28
  • 37
  • 16
    also, don't forget to add the `classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.0"` in the project-level `build.gradle` file, too – Eric Nov 14 '20 at 19:28
  • 1
    This pointed me to the solution. I had to include this plugin in the module's `build.gradle.kts` file, in my multi-module project. – peter.o Jan 25 '21 at 18:20
  • 1
    Very very thank you :) –  Nov 19 '21 at 20:02
  • @VahitKeskin You are very very welcome :) – Sanjeev Dec 24 '21 at 18:02
88

Look for the class of the fragment which is the source of navigation. If you define navigation from FragmentA to FragmentB, you will find FragmentADirections class with the actions you defined (in nav_graph.xml) in it.

Then, to generate direction class ( Also argument class) you need to go Project level gradle then click the build command. Here I attached a screenshot to give a clear understanding.

enter image description here

Gk Mohammad Emon
  • 6,084
  • 3
  • 42
  • 42
shmulik.r
  • 1,101
  • 9
  • 5
  • 9
    Additionally, I have to re-sync my project for it to show up. – Joshua King Oct 21 '19 at 16:40
  • 1
    even though I did all of the suggested solutions here before coming to SO, nothing worked, I even did invalidate cache/restart, still didn't work. This answer is the only one i did not know of or applied, but it still didn't directly work. It actually gave me a build error, but i think it triggered sth new. I then did a clean>rebuild again, and it finally worked. – Ace May 17 '20 at 14:26
  • Invalidate cache and restart does not work by itself, must clean and rebuild. – apsommer Oct 21 '20 at 02:02
52

I faced a similar issue working with android studio 4.2 preview.

The issue was that the IDE somehow was not picking the source folders where the generated direction classes where being placed by the plugin. So adding the following to my app build.gradle file resolved the issue for me.

sourceSets {
    main {
        java {
            srcDirs += 'build/generated/source/navigation-args'
        }
    }
}
Sunderam Dubey
  • 1
  • 11
  • 20
  • 40
Christian
  • 739
  • 6
  • 10
20

As Christian wrote, adding source set to app gradle file helped. The problem occurs in Android Studio 4.1 and 4.2 for me. In Kotlin DSL:

android {
    ....
    sourceSets {
        getByName("main").java.srcDirs("build/generated/source/navigation-args")
    }
}
Zdenek Sima
  • 311
  • 2
  • 6
18

If all the answers above didn't work for you and you are still having a problem with the directions class not being generated. Make sure you are looking for the right directions class.

For example, we have to pass arguments from FragmentA to FragmentB.
In the navigation graph file, we have to add the <argument/> tag under FragmentB's tag. This way, we will get two generated classes FragmentBArgs and FragmentADirections. As you can see, it is the FragmentA's name who got used for the directions class created, not FragmentB.

So, keep in mind that unlike what this question's user is looking for, the directions class generated will get the class name of the action starter fragment appended with the word "Directions". Not the destination fragment's class name (argument's owner).

Here is what the documentation says:

A class is created for each destination where an action originates. The name of this class is the name of the originating destination, appended with the word "Directions".

A class is created for the receiving destination. The name of this class is the name of the destination, appended with the word "Args".

Also, adding the argument tag under the action tag will not generate a directions class. It's used to give a different default value for the destination fragment's argument.

Hope this helps!

Rami Jemli
  • 2,550
  • 18
  • 31
  • 1
    Thank you for this. Even though I had the problem that my *Args class was not generated, in the end I was adding my tag under origin fragment instead of the destination fragment. – Chapz Feb 02 '21 at 15:46
13

If you already added the dependencies > classpath and apply plugin but changes aren't applied, be sure to Clean and Built the project in order changes are applied.

In Android Studio:

  • Build tab > Clean project
  • Build tab > ReBuild project
Alexandre B.
  • 5,387
  • 2
  • 17
  • 40
13

We can fix this issue by adding the below codes in gradle and rebuilding the app. In the project gradle add below code.

classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0"

In app gradle add below code

apply plugin: "androidx.navigation.safeargs"
Fabi
  • 161
  • 1
  • 6
  • 1
    You'd better use `classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"` since you use AndroidX. – Micer Jun 20 '20 at 16:06
7

For me, I realized that I also needed to put the same arguments into the receiver fragment in navi_graph.xml as well in order for Arg class to be generated(already have directions). For example:

<fragment android:id="@+id/receiver_fragment" ...>

    <argument android:name="arg_from_sender_fragment".../>

    <argument android:name="arg2_from_sender_fragment".../>

</fragment>
Leak15
  • 71
  • 2
  • 2
5

Following two steps works for me:

  1. Clean project.
  2. Rebuild project

Android studio 4.0 Kotlin 1.3.72

Yogesh Nikam Patil
  • 1,192
  • 13
  • 18
  • When I had this problem cleaning and rebuilding didn't work. What eventually solved the problem was just changing one value in the `navigation.xml`, Clean and Build, then change the value back, Clean and Rebuild and it worked. Example. Do this for any value in the xml. Doesn't matter `app:popUpToInclusive="true"` -> `app:popUpToInclusive="false"` Clean and Rebuild `app:popUpToInclusive="false"` -> `app:popUpToInclusive="true"` Clean and Rebuild, Problem Gone. – Banane42 May 02 '22 at 15:17
5

app->build.gradle:

Inside the plugins, I have added the below line to fix that issue:

plugins {
    id "androidx.navigation.safeargs.kotlin"
}
Stephen
  • 9,899
  • 16
  • 90
  • 137
5

All solutions didn't work for me and I had all synced in build.gradle. Only way I could've find directions and args was by changing from Android to Project. Open app -> package -> build -> generated -> source -> navigation-args. And you'll get fragment directions and args. Here is screenshot, hope it works for you guys!

fragment directions and args

enter image description here

Ticherhaz FreePalestine
  • 2,738
  • 4
  • 20
  • 46
clone_fg
  • 51
  • 1
  • 1
4

Follow these steps:

Step 1: Add dependencies

def nav_version = "2.3.2"

implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"

Step 2: In your app-level build.gradle make sure you have below plugins added.

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-kapt'
    id 'kotlin-android-extensions'
    id 'androidx.navigation.safeargs.kotlin'
}

Step 3: Add this in project_level build.gradle inside dependencies section :

classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.2"

Step 4: In your nav_graph.xml make sure to connect one fragment to another with actions.

Step 5: Clean & Rebuild your project.

Sumit Shukla
  • 4,116
  • 5
  • 38
  • 57
3

Also make sure to use an up to date version. Had the problem, that I had an 1.X version.

// Navigation
implementation "androidx.navigation:navigation-fragment-ktx:2.2.1"
implementation "androidx.navigation:navigation-ui-ktx:2.2.1"

And the args correctely in the nav.xml:

<fragment
    android:id="@+id/categoryFragment"
    android:name="com...CategoryFragment"
    android:label="CategoryFragment"
    tools:layout="@layout/fragment_category">
    <action
        android:id="@+id/action_categoryFragment_to_ProductFragment" // /!\
        app:destination="@id/productFragment"
        <argument
            android:name="products"
            android:defaultValue=""
            app:argType="string" />
    </action>
</fragment>

Code:

override fun onItemClicked(category: Category) {
     val action = CategoryFragmentDirections.actionCategoryToProductFragment(products = "myString") // /!\
     view?.findNavController()?.navigate(action)
}
Javatar
  • 2,518
  • 1
  • 31
  • 43
  • 1
    Fyi: Also had to add: `kotlinOptions { jvmTarget = JavaVersion.VERSION_1_8.toString() }` to build.gradle – Javatar Mar 13 '20 at 15:01
3

If none of the other answers worked for you and you are using multiple NavGraphs, make sure that your NavGraph id's in xml are different.

<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/nav_graph">
Yusuf Isaacs
  • 131
  • 1
  • 1
  • 5
2

In your app/module level add the following dependency :

    def nav_version = "2.3.0-alpha04"  //your nav_version defined 

    implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"

all the answers are correct too. just felt that I should add this info. It worked for me

Tonui Nicholus
  • 395
  • 2
  • 8
2

In my case, the problem was that I was using the same fragment with the same id in 2 navigation graphs.

Android Studio didn’t recognize the actions of one of the navigation graphs.

So the solution for me was to change the id of one of the navigation graphs, rebuild, change again the id and rebuild again.

After that everything worked again

Jorge Casariego
  • 21,948
  • 6
  • 90
  • 97
2

I followed all instructions to the letter and noticed the Directions classes were being generated, but would not compile when called in code. This happened while using Android Studio 4.1 and 4.2 Preview.

After a few hours, I decided to try downgrading to 4.0 Stable. All issues are now gone, I can call the FragmentDirections and it compiles.

I added a bug in the issue tracker: https://issuetracker.google.com/issues/158777967

Sean Blahovici
  • 5,350
  • 4
  • 28
  • 38
  • 1
    You just saved me a few hours! I had exactly the same issue, downgraded to stable and boom, Directions classes are generated! Thanks for sharing this! – Micer Jun 20 '20 at 16:15
2

If anybody's having trouble with auto-generated classes with SafeArgs, check your AndroidStudio version. I was using 4.1 beta (at this moment) and when downgraded to 4.0 it works perfectly. Definitely do try that. Cheers!

Lheonair
  • 468
  • 5
  • 14
2

Took a bit to figure out but you need both action and arguments in your nav xml file to generate both.

<fragment
    android:id="@+id/nav_someId"
    android:name=".CategoriesFragment"
    android:label="@string/someName"
    tools:layout="@layout/fragment_categories">
    <argument
        android:name="@string/category"
        android:defaultValue="0"
        app:argType="string" />
    <action
        android:id="@+id/startCategoriesFragment"
        app:destination="@+id/categoriesFragment">
        <argument
            android:name="@string/category"
            android:defaultValue="0"
            app:argType="string" />
    </action>
</fragment>
  • 1
    What do you mean ? action and arg in same fragment tag? doesn't make sense. The argument should be in destination and action should be in the action originating fragment tag – Antroid Sep 26 '20 at 23:01
2

In my case, the missing part was firstly in the build.gradle.kts

buildscript {
repositories {
    google()
}
dependencies {
    def nav_version = "X.X.X" // Use the latest version
    classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
}

}

and then, I had to add the plugin in app and navigation modules (I usually separate navigation in a different one):

apply plugin: "androidx.navigation.safeargs.kotlin"

Clean -> Build But still had to add manually the path to the action

import yourpackage.FragmentDirections.Companion.actionFirstFragmentToSecondFragment
1

I just forgot to rebuild my project after cleaning it :)

Also dont forget these two steps:

  1. Add safe-args dependency to project Gradle file
"android.arch.navigation:navigation-safe-args-gradle-plugin:$version_navigation"
  1. Add safeargs plugin to app Gradle file // Adding the apply plugin statement for safeargs
apply plugin: 'kotlin-kapt'
apply plugin: 'androidx.navigation.safeargs'
1

For some reason (I'm still learning details of the gradle files in Android) the above plugin lines didn't work. But this did. Add this line inside the plugin section of your build.gradle (app).

id ("androidx.navigation.safeargs")

No colon, no equals. And of course sync, rebuild, etc. This is slightly different from other answers. But details count in programming!

SMBiggs
  • 11,034
  • 6
  • 68
  • 83
1

Apply the plugin in the build.gradle (module level)

apply plugin: "androidx.navigation.safeargs.kotlin"

Add the dependencies in the build.gradle (Project Level)

classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.1.0-rc01"

This would solve the problem.

Boken
  • 4,825
  • 10
  • 32
  • 42
Ramya Bm
  • 27
  • 2
0

the problem may be with your apply plugin thing please check if you are using java then add:

apply plugin: "androidx.navigation.safeargs"

and for kotlin use this:

apply plugin: "androidx.navigation.safeargs.kotlin"
Asad
  • 1,241
  • 3
  • 19
  • 32
0

In my case I manually added the arguments... in the wrong place ‍♂️

Select the destination in your navigation graph and click the "+" button next to "Arguments". Add the relevant info and you should be able to see the generated SafeArgs with by navArgs().

Here's a helpful guide with pictures. https://medium.com/androiddevelopers/navigating-with-safeargs-bf26c17b1269

Victor Ude
  • 415
  • 4
  • 13
0

In my case, instead of control-dragging from Fragment A to B, I did B to A and thus they were not being generated in the correct Fragment class, rookie mistake! So check this too guys!

0

When you update some actions or arguments on the nav graph. You need to Build > Rebuild Project to see this changes applied

DavidUps
  • 366
  • 3
  • 9
0

UPDATE

if you are using Kotlin add this plugin to the app build.gradle level:

plugins {
    ...
    id "androidx.navigation.safeargs.kotlin"
}

and in the build.gradle project level add this plugin:

 plugins {
        ...
         id 'com.google.dagger.hilt.android' version '2.42' apply false
    }

if you are missing generated safe args classes add this to tell gradle to add the generated classes under the main folder in the kotlin file:

android {
...
    sourceSets {
        main {
            kotlin {
                srcDirs += 'build/generated/source/navigation-args/'
            }
        }
    }
}
Mado
  • 329
  • 3
  • 16