I am developing new app and implemented shared preferences in my appModule.kt but when I run project I am getting following errors
Task :app:hiltJavaCompileDebug C:\Users\Yodgorbek\RunTrackerApp\app\build\generated\hilt\component_sources\debug\com\example\runtrackerapp\BaseApplication_HiltComponents.java:136: error: [Dagger/Nullable] android.content.SharedPreferences is not nullable, but is being provided by @Singleton @Provides @org.jetbrains.annotations.Nullable android.content.SharedPreferences com.example.runtrackerapp.di.AppModule.provideSharedPreferences(@dagger.hilt.android.qualifiers.ApplicationContext android.content.Context) public abstract static class SingletonC implements BaseApplication_GeneratedInjector, ^ android.content.SharedPreferences is injected at com.example.runtrackerapp.di.AppModule.provideWeight(sharedPref) java.lang.Float is injected at com.example.runtrackerapp.ui.fragments.TrackingFragment.setWeight(<set-?>) com.example.runtrackerapp.ui.fragments.TrackingFragment is injected at com.example.runtrackerapp.ui.fragments.TrackingFragment_GeneratedInjector.injectTrackingFragment(com.example.runtrackerapp.ui.fragments.TrackingFragment) [com.example.runtrackerapp.BaseApplication_HiltComponents.SingletonC ? com.example.runtrackerapp.BaseApplication_HiltComponents.ActivityRetainedC ? com.example.runtrackerapp.BaseApplication_HiltComponents.ActivityC ? com.example.runtrackerapp.BaseApplication_HiltComponents.FragmentC] C:\Users\Yodgorbek\RunTrackerApp\app\build\generated\hilt\component_sources\debug\com\example\runtrackerapp\BaseApplication_HiltComponents.java:136: error: [Dagger/Nullable] android.content.SharedPreferences is not nullable, but is being provided by @Singleton @Provides @org.jetbrains.annotations.Nullable android.content.SharedPreferences com.example.runtrackerapp.di.AppModule.provideSharedPreferences(@dagger.hilt.android.qualifiers.ApplicationContext android.content.Context) public abstract static class SingletonC implements BaseApplication_GeneratedInjector, ^ android.content.SharedPreferences is injected at com.example.runtrackerapp.ui.fragments.SetupFragment.sharedPref com.example.runtrackerapp.ui.fragments.SetupFragment is injected at com.example.runtrackerapp.ui.fragments.SetupFragment_GeneratedInjector.injectSetupFragment(com.example.runtrackerapp.ui.fragments.SetupFragment) [com.example.runtrackerapp.BaseApplication_HiltComponents.SingletonC ? com.example.runtrackerapp.BaseApplication_HiltComponents.ActivityRetainedC ? com.example.runtrackerapp.BaseApplication_HiltComponents.ActivityC ? com.example.runtrackerapp.BaseApplication_HiltComponents.FragmentC] C:\Users\Yodgorbek\RunTrackerApp\app\build\generated\hilt\component_sources\debug\com\example\runtrackerapp\BaseApplication_HiltComponents.java:136: error: [Dagger/Nullable] android.content.SharedPreferences is not nullable, but is being provided by @Singleton @Provides @org.jetbrains.annotations.Nullable android.content.SharedPreferences com.example.runtrackerapp.di.AppModule.provideSharedPreferences(@dagger.hilt.android.qualifiers.ApplicationContext android.content.Context) public abstract static class SingletonC implements BaseApplication_GeneratedInjector, ^ android.content.SharedPreferences is injected at com.example.runtrackerapp.di.AppModule.provideFirstTimeToggle(sharedPref) java.lang.Boolean is injected at com.example.runtrackerapp.ui.fragments.SetupFragment.setFirstAppOpen(<set-?>) com.example.runtrackerapp.ui.fragments.SetupFragment is injected at com.example.runtrackerapp.ui.fragments.SetupFragment_GeneratedInjector.injectSetupFragment(com.example.runtrackerapp.ui.fragments.SetupFragment) [com.example.runtrackerapp.BaseApplication_HiltComponents.SingletonC ? com.example.runtrackerapp.BaseApplication_HiltComponents.ActivityRetainedC ? com.example.runtrackerapp.BaseApplication_HiltComponents.ActivityC ? com.example.runtrackerapp.BaseApplication_HiltComponents.FragmentC] 3 errors
below my appModule.kt
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Singleton
@Provides
fun provideRunningDatabase(
@ApplicationContext app: Context
) = Room.databaseBuilder(
app,
RunningDatabase::class.java,
RUNNING_DATABASE_NAME
).build()
@Singleton
@Provides
fun provideRunDao(db: RunningDatabase) = db.getRunDao()
@Singleton
@Provides
fun provideSharedPreferences(@ApplicationContext app: Context): SharedPreferences? {
val sharedPreferences = app.getSharedPreferences(SHARED_PREFERENCES_NAME, MODE_PRIVATE)
return sharedPreferences
}
@Singleton
@Provides
fun provideName(sharedPref: SharedPreferences) = sharedPref.getString(KEY_NAME, "") ?: ""
@Singleton
@Provides
fun provideWeight(sharedPref: SharedPreferences) = sharedPref.getFloat(KEY_WEIGHT, 80f)
@Singleton
@Provides
fun provideFirstTimeToggle(sharedPref: SharedPreferences) =
sharedPref.getBoolean(KEY_FIRST_TIME_TOGGLE, true)
}
below SetupFragment.kt
@AndroidEntryPoint
class SetupFragment : Fragment() {
private var _binding: FragmentSetupBinding? = null
private val binding get() = _binding!!
@Inject
lateinit var sharedPref: SharedPreferences
@set:Inject
var isFirstAppOpen = true
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// inflate the layout and bind to the _binding
_binding = FragmentSetupBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if(!isFirstAppOpen){
val navOptions = NavOptions.Builder()
.setPopUpTo(R.id.setupFragment, true)
.build()
findNavController().navigate(
R.id.action_setupFragment_to_runFragment,
savedInstanceState,
navOptions)
}
binding.tvContinue.setOnClickListener {
val success = writePersonalDataToSharedPref()
if (success){
findNavController().navigate(R.id.action_setupFragment_to_runFragment)
}else{
Snackbar.make(requireView(), "Please enter all the fields", Snackbar.LENGTH_SHORT).show()
}
}
}
private fun writePersonalDataToSharedPref(): Boolean {
val name = binding.etName.text.toString()
val weight = binding.etWeight.text.toString()
if(name.isEmpty() || weight.isEmpty()) {
return false
}
sharedPref.edit()
.putString(KEY_NAME, name)
.putFloat(KEY_WEIGHT, weight.toFloat())
.putBoolean(KEY_FIRST_TIME_TOGGLE, false)
.apply()
val toolbarText = "Let's go, $name!"
(requireActivity() as ActivityMainBinding).tvToolbarTitle.text = toolbarText
return true
}
}
below TrackingFragment.kt
@AndroidEntryPoint
class TrackingFragment : Fragment(R.layout.fragment_tracking) {
private val viewModel: MainViewModel by viewModels()
private var isTracking = false
private var pathPoints = mutableListOf<Polyline>()
private var map: GoogleMap? = null
private var curTimeInMillis = 0L
private var _binding: FragmentTrackingBinding? = null
private val binding get() = _binding!!
private var menu: Menu? = null
@set:Inject
var weight = 80f
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
setHasOptionsMenu(true)
_binding = FragmentTrackingBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.mapView.onCreate(savedInstanceState)
binding.btnToggleRun.setOnClickListener {
toggleRun()
}
binding.btnFinishRun.setOnClickListener {
zoomToSeeWholeTrack()
endRunAndSaveToDb()
}
binding.mapView.getMapAsync {
map = it
addAllPolylines()
}
subscribeToObservers()
}
private fun subscribeToObservers() {
TrackingService.isTracking.observe(viewLifecycleOwner, Observer {
updateTracking(it)
})
TrackingService.pathPoints.observe(viewLifecycleOwner, Observer {
pathPoints = it
addLatestPolyline()
moveCameraToUser()
})
TrackingService.timeRunInMillis.observe(viewLifecycleOwner, Observer {
curTimeInMillis = it
val formattedTime = TrackingUtility.getFormattedStopWatchTime(curTimeInMillis, true)
binding.tvTimer.text = formattedTime
})
}
private fun toggleRun() {
if(isTracking) {
menu?.getItem(0)?.isVisible = true
sendCommandToService(ACTION_PAUSE_SERVICE)
} else {
sendCommandToService(ACTION_START_OR_RESUME_SERVICE)
}
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.toolbar_tracking_menu, menu)
this.menu = menu
}
override fun onPrepareOptionsMenu(menu: Menu) {
super.onPrepareOptionsMenu(menu)
if(curTimeInMillis > 0L) {
this.menu?.getItem(0)?.isVisible = true
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when(item.itemId) {
R.id.miCancelTracking -> {
showCancelTrackingDialog()
}
}
return super.onOptionsItemSelected(item)
}
private fun showCancelTrackingDialog() {
val dialog = MaterialAlertDialogBuilder(requireContext(), R.style.AlertDialogTheme)
.setTitle("Cancel the Run?")
.setMessage("Are you sure to cancel the current run and delete all its data?")
.setIcon(R.drawable.ic_delete)
.setPositiveButton("Yes") { _, _ ->
stopRun()
}
.setNegativeButton("No") { dialogInterface, _ ->
dialogInterface.cancel()
}
.create()
dialog.show()
}
private fun stopRun() {
sendCommandToService(ACTION_STOP_SERVICE)
findNavController().navigate(R.id.action_trackingFragment_to_runFragment)
}
private fun updateTracking(isTracking: Boolean) {
this.isTracking = isTracking
if(!isTracking) {
binding.btnToggleRun.text = "Start"
binding.btnFinishRun.visibility = View.VISIBLE
} else {
binding.btnToggleRun.text = "Stop"
menu?.getItem(0)?.isVisible = true
binding.btnFinishRun.visibility = View.GONE
}
}
private fun moveCameraToUser() {
if(pathPoints.isNotEmpty() && pathPoints.last().isNotEmpty()) {
map?.animateCamera(
CameraUpdateFactory.newLatLngZoom(
pathPoints.last().last(),
MAP_ZOOM
)
)
}
}
private fun zoomToSeeWholeTrack(){
val bounds = LatLngBounds.builder()
for(polyline in pathPoints){
for(pos in polyline){
bounds.include(pos)
}
}
map?.moveCamera(
CameraUpdateFactory.newLatLngBounds(
bounds.build(),
binding.mapView.width,
binding.mapView.height,
(binding.mapView.height * 0.05f).toInt()
)
)
}
private fun endRunAndSaveToDb(){
map?.snapshot { bmp ->
var distanceInMeters = 0
for (polyline in pathPoints){
distanceInMeters = TrackingUtility.calculatePolylineLength(polyline).toInt()
}
val avgSpeed = round((distanceInMeters / 1000f) / (curTimeInMillis / 1000f / 60 / 60) * 10) / 10f
val dataTimestamp = Calendar.getInstance().timeInMillis
val caloriesBurned = ((distanceInMeters / 1000f) * weight).toInt()
val run = Run(bmp,dataTimestamp, avgSpeed,distanceInMeters, curTimeInMillis, caloriesBurned)
viewModel.insertRun(run)
Snackbar.make(
requireActivity().findViewById(R.id.rootView),
"Run saved successfully",
Snackbar.LENGTH_LONG
).show()
stopRun()
}
}
private fun addAllPolylines() {
for(polyline in pathPoints) {
val polylineOptions = PolylineOptions()
.color(POLYLINE_COLOR)
.width(POLYLINE_WIDTH)
.addAll(polyline)
map?.addPolyline(polylineOptions)
}
}
private fun addLatestPolyline() {
if(pathPoints.isNotEmpty() && pathPoints.last().size > 1) {
val preLastLatLng = pathPoints.last()[pathPoints.last().size - 2]
val lastLatLng = pathPoints.last().last()
val polylineOptions = PolylineOptions()
.color(POLYLINE_COLOR)
.width(POLYLINE_WIDTH)
.add(preLastLatLng)
.add(lastLatLng)
map?.addPolyline(polylineOptions)
}
}
private fun sendCommandToService(action: String) =
Intent(requireContext(), TrackingService::class.java).also {
it.action = action
requireContext().startService(it)
}
override fun onResume() {
super.onResume()
binding.mapView?.onResume()
}
override fun onStart() {
super.onStart()
binding.mapView?.onStart()
}
override fun onStop() {
super.onStop()
binding.mapView?.onStop()
}
override fun onPause() {
super.onPause()
binding.mapView?.onPause()
}
override fun onLowMemory() {
super.onLowMemory()
binding.mapView?.onLowMemory()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
binding.mapView?.onSaveInstanceState(outState)
}
}
I want to know where I am making mistake I have followed all stackoverflow answer it did not solve my issue
CodePudding user response:
A provider should not be nullable in your case provideSharedPreferences
..
Remove Nullble from return type.
@Singleton
@Provides
fun provideSharedPreferences(@ApplicationContext app: Context): SharedPreferences {
val sharedPreferences = app.getSharedPreferences(SHARED_PREFERENCES_NAME, MODE_PRIVATE)
return sharedPreferences
}