Android Studio添加Assets文件夹后Navigation报R包不存在
问题现象
Android Studio项目新增Assets文件夹后编译失败,报错出自Navigation组件自动生成代码:
error: package R does not exist "return new ActionOnlyNavDirections(R.id.action_newAlarmFragment_to_homeFragment);"
对应自动生成的Directions类代码如下:
import androidx.annotation.NonNull; import androidx.navigation.ActionOnlyNavDirections; import androidx.navigation.NavDirections; public class SetNewAlarmFragmentDirections { private SetNewAlarmFragmentDirections() { } @NonNull public static NavDirections actionNewAlarmFragmentToHomeFragment() { return new ActionOnlyNavDirections(R.id.action_newAlarmFragment_to_homeFragment); } }
已尝试的排查操作:
- 执行Clean Project、Rebuild Project
- 执行Invalidate caches and restart
- 手动排查各文件R类导入语句,未发现异常
关联代码片段
SetNewAlarmFragment实现
import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.CompoundButton import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import androidx.navigation.Navigation import com.pleavinseven.alarmclockproject.alarmmanager.AlarmManager import com.pleavinseven.alarmclockproject.data.model.Alarm import com.pleavinseven.alarmclockproject.data.viewmodel.AlarmViewModel import com.pleavinseven.alarmclockproject.databinding.FragmentSetNewAlarmBinding import com.pleavinseven.alarmclockproject.util.TimePickerUtil import java.util.* class SetNewAlarmFragment : Fragment() { private val timePickerUtil = TimePickerUtil() lateinit var binding: FragmentSetNewAlarmBinding private lateinit var alarmViewModel: AlarmViewModel override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { binding = FragmentSetNewAlarmBinding.inflate(inflater, container, false) binding.fragmentCreateAlarmRecurring.setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener { _, isChecked -> if (isChecked) { binding.fragmentCreateAlarmRecurring.visibility = View.VISIBLE } else { binding.fragmentCreateAlarmRecurring.visibility = View.GONE } }) alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] binding.fragmentBtnSetAlarm.setOnClickListener(View.OnClickListener { _ -> scheduleAlarm() Navigation.findNavController(requireView()) .navigate(com.pleavinseven.alarmclockproject.R.id.action_newAlarmFragment_to_homeFragment) }) return binding.root }
导航配置nav_graph.xml
?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/alarm_nav" app:startDestination="@id/homeFragment"> <fragment android:id="@+id/homeFragment" android:name="com.pleavinseven.alarmclockproject.fragments.HomeFragment" android:label="fragment_home" tools:layout="@layout/fragment_home" > <action android:id="@+id/action_homeFragment_to_newAlarmFragment" app:destination="@id/newAlarmFragment" /> <action android:id="@+id/action_homeFragment_to_updateFragment" app:destination="@id/updateFragment" /> </fragment> <fragment android:id="@+id/newAlarmFragment" android:name="com.pleavinseven.alarmclockproject.fragments.SetNewAlarmFragment" android:label="NewAlarmFragment" > <action android:id="@+id/action_newAlarmFragment_to_homeFragment" app:destination="@id/homeFragment" /> </fragment> <fragment android:id="@+id/updateFragment" android:name="com.pleavinseven.alarmclockproject.fragments.UpdateFragment" android:label="UpdateFragment" > <action android:id="@+id/action_updateFragment_to_homeFragment" app:destination="@id/homeFragment" /> <argument android:name="currentAlarm" app:argType="com.pleavinseven.alarmclockproject.data.model.Alarm" /> </fragment>
排查解决步骤
按优先级从高到低逐一排查:
- 修正导航XML语法错误
贴出的nav xml第一行缺失左尖括号,正确开头应为<?xml version="1.0" encoding="utf-8"?>,当前写法会直接导致AAPT2资源编译失败,R类无法正常生成,所有依赖R类的代码(包括Safe Args自动生成的Directions类)都会报找不到R的错误。先补全这个尖括号,再重新编译。 - 确认Assets文件夹路径正确
新增Assets文件夹时如果放错位置,会打断资源编译流程:标准Assets路径必须是对应模块的src/main/assets,不能放在模块根目录、res目录下,也不能和java/kotlin代码目录混放。如果路径放错,移动到正确位置后重新编译即可。 - 修复非传递R类兼容问题
如果项目gradle.properties中开启了android.nonTransitiveRClass=true,且Navigation组件版本低于2.4.0,会触发Safe Args插件的已知bug:自动生成的Directions类不会自动导入项目包名的R类,直接调用R就会报不存在。解决方法二选一:- 把Navigation相关依赖(包括safe-args插件)升级到2.4.0及以上稳定版
- 临时关闭非传递R类配置验证,即把
android.nonTransitiveRClass改为false
- 排查资源编译前置错误
执行命令行编译./gradlew clean assembleDebug,查看编译日志最开头的错误,不要看最后抛出的R不存在错误——R不存在永远是连锁结果,前面一定有更早的资源编译失败原因,比如资源命名不合法(含大写、特殊字符)、资源冲突、XML布局语法错误等,修好最前置的资源错误,R类就会正常生成。 - 核对Safe Args插件配置
确认项目级和模块级的Safe Args插件配置匹配:- 项目级build.gradle中要添加对应版本的safe-args依赖
- Kotlin项目模块级要应用
androidx.navigation.safeargs.kotlin插件,Java项目应用androidx.navigation.safeargs插件,插件版本要和引入的navigation-fragment、navigation-ui依赖版本完全一致,版本不匹配也会导致自动生成代码异常。
内容的提问来源于stack exchange,提问作者Joe Pleavin
相关产品推荐
相关产品推荐

