Reputation: 4327
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
Upvotes: 154
Views: 75938
Reputation: 76669
With multiple flavors and build-types configured, this works differently.
Because it generates directions for all of them and therefore this will result in duplicate classes, when using build/generated/source/navigation-args
, which is only the main directory. I've wrote a Groovy function, which parses the current task's flavor and build-type and returns the proper path. When only adding the relevant sub-directory, there won't be any duplicate classes.
String generatedNavArgs () {
String task_requests = "${getGradle().getStartParameter().getTaskRequests().toString()}"
String path = 'build/generated/source/navigation-args'
String buildType = ""
String flavor = ""
if (task_requests.contains('Debug')) {buildType = 'debug'}
else if (task_requests.contains('Staging')) {buildType = 'staging'}
else if (task_requests.contains('Release')) {buildType = 'release'}
if (task_requests.contains('Flavor1')) {flavor = 'flavor1'}
else if (task_requests.contains('Flavor2')) {flavor = 'flavor2'}
else if (task_requests.contains('Flavor3')) {flavor = 'flavor3'}
if (buildType != null && flavor != null) {
File src = file("${path}/${flavor}/${buildType}")
if (src.exists() && src.isDirectory()) {
println "> navigation-args added to sourceSet main: ${src.path}"
return src.path
} else {
println "> navigation-args are not present: ${src.path}"
}
}
return null
}
To be added in the same way:
sourceSets {
main {
java.srcDirs = [ 'src/main/java', generatedNavArgs() ]
}
...
}
Upvotes: 1
Reputation: 1496
if you are facing issues with unresolved references to NavGraphDirections, adding this directory to your source sets can help resolve those issues. Make sure to sync your project after making this change to ensure that it takes effect. Make sure you have applied the Safe Args plugin in your app-level build.gradle file.
Kotlin DSL:
plugins {
id("androidx.navigation.safeargs.kotlin")
}
sourceSets {
getByName("main") {
java.srcDirs("build/generated/source/navigation-args")
}
}
Groovy DSL:
plugins {
id 'androidx.navigation.safeargs.kotlin'
}
sourceSets {
main {
java {
srcDirs += 'build/generated/source/navigation-args'
}
}
}
Yes, adding the build/generated/source/navigation-args directory to your source sets is necessary for your project to recognize the generated NavGraphDirections class.
This directory contains the generated code by the Safe Args plugin, including the NavGraphDirections class which provides type-safe access to navigation actions. By adding this directory to your source sets, you ensure that this generated code is included in the compilation process of your project.
Also Add Module Level Code:
buildscript {
repositories {
google()
}
dependencies {
def nav_version = "2.7.7"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
}
}
Upvotes: 0
Reputation: 1714
Configuration for gradle.kts
plugins {
id("androidx.navigation.safeargs") version "2.7.4" apply false
}
plugins {
id("androidx.navigation.safeargs.kotlin")
}
Upvotes: 6
Reputation: 779
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'
}
}
}
Upvotes: 56
Reputation: 461
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/'
}
}
}
}
Upvotes: 0
Reputation: 451
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")
}
}
Upvotes: 24
Reputation: 131
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">
Upvotes: 3
Reputation: 51
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
Upvotes: 5
Reputation: 10059
app->build.gradle:
Inside the plugins, I have added the below line to fix that issue:
plugins {
id "androidx.navigation.safeargs.kotlin"
}
Upvotes: 7
Reputation: 11688
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!
Upvotes: 1
Reputation: 66
I just forgot to rebuild my project after cleaning it :)
Also dont forget these two steps:
"android.arch.navigation:navigation-safe-args-gradle-plugin:$version_navigation"
apply plugin: 'kotlin-kapt'
apply plugin: 'androidx.navigation.safeargs'
Upvotes: 1
Reputation: 433
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
Upvotes: 0
Reputation: 4494
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 withactions
.Step 5: Clean & Rebuild your project.
Upvotes: 5
Reputation: 1439
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"
Upvotes: 2
Reputation: 925
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
Upvotes: 2
Reputation: 395
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>
Upvotes: 2
Reputation: 498
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!
Upvotes: 2
Reputation: 1280
Following two steps works for me:
Android studio 4.0 Kotlin 1.3.72
Upvotes: 5
Reputation: 5740
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
Upvotes: 2
Reputation: 22212
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
Upvotes: 3
Reputation: 161
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"
Upvotes: 13
Reputation: 2641
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!
Upvotes: 21
Reputation: 71
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>
Upvotes: 7
Reputation: 1111
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.
Upvotes: 89
Reputation: 5502
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
Upvotes: 13
Reputation: 395
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
Upvotes: 2
Reputation: 2665
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)
}
Upvotes: 3
Reputation: 4375
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"
Upvotes: 105