diff --git a/app/build.gradle b/app/build.gradle index 6832df7..3fa4cc2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,8 +10,8 @@ android { applicationId 'org.y20k.trackbook' minSdkVersion 25 targetSdkVersion 30 - versionCode 46 - versionName '2.0.9' + versionCode 47 + versionName '2.0.10' resConfigs "en", "da", "de", "fr", "hr", "id", "it", "ja", "nb-rNO", "nl", "pt-rBR", "sv", "tr", "zh-rCN" } @@ -52,17 +52,17 @@ android { dependencies { // Kotlin implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.8' - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9' // AndroidX implementation 'androidx.appcompat:appcompat:1.2.0' - implementation 'androidx.constraintlayout:constraintlayout:2.0.2' + implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'androidx.core:core-ktx:1.3.2' implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version" implementation "androidx.navigation:navigation-ui-ktx:$navigation_version" implementation 'androidx.preference:preference-ktx:1.1.1' - implementation 'com.google.android.material:material:1.2.0-rc01' + implementation 'com.google.android.material:material:1.2.1' // Gson implementation 'com.google.code.gson:gson:2.8.6' diff --git a/app/src/main/java/org/y20k/trackbook/MainActivity.kt b/app/src/main/java/org/y20k/trackbook/MainActivity.kt index 2e4c505..91bf4ee 100644 --- a/app/src/main/java/org/y20k/trackbook/MainActivity.kt +++ b/app/src/main/java/org/y20k/trackbook/MainActivity.kt @@ -77,12 +77,12 @@ class MainActivity : AppCompatActivity() { navHostFragment.navController.addOnDestinationChangedListener { _, destination, _ -> when (destination.id) { R.id.fragment_track -> { - runOnUiThread( Runnable() { - run(){ + runOnUiThread { + run { // mark menu item "Tracks" as checked - bottomNavigationView.menu.findItem(R.id.tracklist_fragment).setChecked(true) + bottomNavigationView.menu.findItem(R.id.tracklist_fragment).isChecked = true } - }) + } } else -> { // do nothing diff --git a/app/src/main/java/org/y20k/trackbook/SettingsFragment.kt b/app/src/main/java/org/y20k/trackbook/SettingsFragment.kt index 78b7403..7aac129 100644 --- a/app/src/main/java/org/y20k/trackbook/SettingsFragment.kt +++ b/app/src/main/java/org/y20k/trackbook/SettingsFragment.kt @@ -48,8 +48,8 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList // set the background color view.setBackgroundColor(resources.getColor(R.color.app_window_background, null)) // add padding - necessary because translucent status bar is used - val topPadding = UiHelper.getStatusBarHeight(activity as Context) - view.setPadding(0, topPadding.toInt(), 0, 0) + val topPadding: Int = UiHelper.getStatusBarHeight(activity as Context) + view.setPadding(0, topPadding, 0, 0) } @@ -88,7 +88,7 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList preferenceThemeSelection.setOnPreferenceChangeListener { preference, newValue -> if (preference is ListPreference) { val index: Int = preference.entryValues.indexOf(newValue) - preferenceThemeSelection.summary = "${getString(R.string.pref_theme_selection_summary)} ${preference.entries.get(index)}" + preferenceThemeSelection.summary = "${getString(R.string.pref_theme_selection_summary)} ${preference.entries[index]}" return@setOnPreferenceChangeListener true } else { return@setOnPreferenceChangeListener false diff --git a/app/src/main/java/org/y20k/trackbook/TrackFragment.kt b/app/src/main/java/org/y20k/trackbook/TrackFragment.kt index 524c067..230ee28 100644 --- a/app/src/main/java/org/y20k/trackbook/TrackFragment.kt +++ b/app/src/main/java/org/y20k/trackbook/TrackFragment.kt @@ -185,7 +185,7 @@ class TrackFragment : Fragment(), RenameTrackDialog.RenameTrackListener, YesNoDi try { startActivityForResult(intent, Keys.REQUEST_SAVE_GPX) } catch (e: Exception) { - LogHelper.e(TAG, "Unable to save GPX. ") + LogHelper.e(TAG, "Unable to save GPX.") Toast.makeText(activity as Context, R.string.toast_message_install_file_helper, Toast.LENGTH_LONG).show() } } diff --git a/app/src/main/java/org/y20k/trackbook/TrackerService.kt b/app/src/main/java/org/y20k/trackbook/TrackerService.kt index 6a945a1..7759fdc 100644 --- a/app/src/main/java/org/y20k/trackbook/TrackerService.kt +++ b/app/src/main/java/org/y20k/trackbook/TrackerService.kt @@ -48,7 +48,7 @@ import kotlin.coroutines.CoroutineContext /* * TrackerService class */ -class TrackerService(): Service(), CoroutineScope, SensorEventListener { +class TrackerService: Service(), CoroutineScope, SensorEventListener { /* Define log tag */ private val TAG: String = LogHelper.makeLogTag(TrackerService::class.java) @@ -210,7 +210,7 @@ class TrackerService(): Service(), CoroutineScope, SensorEventListener { // try to mark last waypoint as stopover if (track.wayPoints.size > 0) { val lastWayPointIndex = track.wayPoints.size - 1 - track.wayPoints.get(lastWayPointIndex).isStopOver = true + track.wayPoints[lastWayPointIndex].isStopOver = true } // set resumed flag resumed = true diff --git a/app/src/main/java/org/y20k/trackbook/TrackingToggleTileService.kt b/app/src/main/java/org/y20k/trackbook/TrackingToggleTileService.kt index 3234150..2e37dcf 100644 --- a/app/src/main/java/org/y20k/trackbook/TrackingToggleTileService.kt +++ b/app/src/main/java/org/y20k/trackbook/TrackingToggleTileService.kt @@ -31,7 +31,7 @@ import org.y20k.trackbook.helpers.PreferencesHelper /* * TrackingToggleTileService class */ -class TrackingToggleTileService(): TileService() { +class TrackingToggleTileService: TileService() { /* Define log tag */ private val TAG: String = LogHelper.makeLogTag(TrackingToggleTileService::class.java) diff --git a/app/src/main/java/org/y20k/trackbook/TracklistFragment.kt b/app/src/main/java/org/y20k/trackbook/TracklistFragment.kt index fa570d6..822cda4 100644 --- a/app/src/main/java/org/y20k/trackbook/TracklistFragment.kt +++ b/app/src/main/java/org/y20k/trackbook/TracklistFragment.kt @@ -24,6 +24,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.DefaultItemAnimator @@ -68,8 +69,8 @@ class TracklistFragment : Fragment(), TracklistAdapter.TracklistAdapterListener, tracklistOnboarding = rootView.findViewById(R.id.track_list_onboarding) // add padding - necessary because translucent status bar is used - val topPadding = UiHelper.getStatusBarHeight(activity as Context) - trackElementList.setPadding(0, topPadding.toInt(), 0, 0) + val topPadding: Int = UiHelper.getStatusBarHeight(activity as Context) + trackElementList.setPadding(0, topPadding, 0, 0) // set up recycler view trackElementList.layoutManager = CustomLinearLayoutManager(activity as Context) @@ -97,11 +98,12 @@ class TracklistFragment : Fragment(), TracklistAdapter.TracklistAdapterListener, /* Overrides onTrackElementTapped from TracklistElementAdapterListener */ override fun onTrackElementTapped(tracklistElement: TracklistElement) { - val bundle: Bundle = Bundle() - bundle.putString(Keys.ARG_TRACK_TITLE, tracklistElement.name) - bundle.putString(Keys.ARG_TRACK_FILE_URI, tracklistElement.trackUriString) - bundle.putString(Keys.ARG_GPX_FILE_URI, tracklistElement.gpxUriString) - bundle.putLong(Keys.ARG_TRACK_ID, TrackHelper.getTrackId(tracklistElement)) + val bundle: Bundle = bundleOf( + Keys.ARG_TRACK_TITLE to tracklistElement.name, + Keys.ARG_TRACK_FILE_URI to tracklistElement.trackUriString, + Keys.ARG_GPX_FILE_URI to tracklistElement.gpxUriString, + Keys.ARG_TRACK_ID to TrackHelper.getTrackId(tracklistElement) + ) findNavController().navigate(R.id.fragment_track, bundle) } diff --git a/app/src/main/java/org/y20k/trackbook/dialogs/ErrorDialog.kt b/app/src/main/java/org/y20k/trackbook/dialogs/ErrorDialog.kt index 48864c9..f0056b0 100644 --- a/app/src/main/java/org/y20k/trackbook/dialogs/ErrorDialog.kt +++ b/app/src/main/java/org/y20k/trackbook/dialogs/ErrorDialog.kt @@ -23,6 +23,8 @@ import android.text.method.ScrollingMovementMethod import android.view.LayoutInflater import android.view.View import android.widget.TextView +import androidx.core.view.isGone +import androidx.core.view.isVisible import com.google.android.material.dialog.MaterialAlertDialogBuilder import org.y20k.trackbook.R import org.y20k.trackbook.helpers.LogHelper @@ -56,25 +58,23 @@ object ErrorDialog { builder.setView(view) // set detail view - if (errorDetails.isNotEmpty()) { - // show details link - errorDetailsLinkView.visibility = View.VISIBLE + val detailsNotEmpty = errorDetails.isNotEmpty() + // show/hide details link depending on whether details are empty or not + errorDetailsLinkView.isVisible = detailsNotEmpty + if (detailsNotEmpty) { // allow scrolling on details view errorDetailsView.movementMethod = ScrollingMovementMethod() // show and hide details on click errorDetailsLinkView.setOnClickListener { when (errorDetailsView.visibility) { - View.GONE -> errorDetailsView.visibility = View.VISIBLE - View.VISIBLE -> errorDetailsView.visibility = View.GONE + View.GONE -> errorDetailsView.isVisible = true + View.VISIBLE -> errorDetailsView.isGone = true } } // set details text view errorDetailsView.text = errorDetails - } else { - // hide details link - errorDetailsLinkView.visibility = View.GONE } // set text views diff --git a/app/src/main/java/org/y20k/trackbook/dialogs/YesNoDialog.kt b/app/src/main/java/org/y20k/trackbook/dialogs/YesNoDialog.kt index 45c8c85..be693e5 100644 --- a/app/src/main/java/org/y20k/trackbook/dialogs/YesNoDialog.kt +++ b/app/src/main/java/org/y20k/trackbook/dialogs/YesNoDialog.kt @@ -84,7 +84,7 @@ class YesNoDialog (private var yesNoDialogListener: YesNoDialogListener) { } // handle outside-click as "no" - builder.setOnCancelListener(){ + builder.setOnCancelListener{ yesNoDialogListener.onYesNoDialog(type, false, payload, payloadString) } diff --git a/app/src/main/java/org/y20k/trackbook/helpers/DateTimeHelper.kt b/app/src/main/java/org/y20k/trackbook/helpers/DateTimeHelper.kt index 3cadcae..cfbc43c 100644 --- a/app/src/main/java/org/y20k/trackbook/helpers/DateTimeHelper.kt +++ b/app/src/main/java/org/y20k/trackbook/helpers/DateTimeHelper.kt @@ -34,7 +34,7 @@ object DateTimeHelper { /* Converts milliseconds to mm:ss or hh:mm:ss */ fun convertToReadableTime(context: Context, milliseconds: Long): String { - var timeString: String = String() + val timeString: String val hours: Long = TimeUnit.MILLISECONDS.toHours(milliseconds) val minutes: Long = TimeUnit.MILLISECONDS.toMinutes(milliseconds) % TimeUnit.HOURS.toMinutes(1) val seconds: Long = TimeUnit.MILLISECONDS.toSeconds(milliseconds) % TimeUnit.MINUTES.toSeconds(1) diff --git a/app/src/main/java/org/y20k/trackbook/helpers/FileHelper.kt b/app/src/main/java/org/y20k/trackbook/helpers/FileHelper.kt index 1258f80..a0dd186 100644 --- a/app/src/main/java/org/y20k/trackbook/helpers/FileHelper.kt +++ b/app/src/main/java/org/y20k/trackbook/helpers/FileHelper.kt @@ -35,6 +35,8 @@ import java.text.NumberFormat import java.util.* import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine +import kotlin.math.ln +import kotlin.math.pow /* @@ -259,13 +261,13 @@ object FileHelper { val jsonString: String = getTrackJsonString(track) if (jsonString.isNotBlank()) { // write track file - writeTextFile(jsonString, Uri.parse(track.trackUriString)) + writeTextFile(jsonString, track.trackUriString.toUri()) } if (saveGpxToo) { val gpxString: String = TrackHelper.createGpxString(track) if (gpxString.isNotBlank()) { // write GPX file - writeTextFile(gpxString, Uri.parse(track.gpxUriString)) + writeTextFile(gpxString, track.gpxUriString.toUri()) } } } @@ -401,13 +403,13 @@ object FileHelper { if (bytes < unit) return "$bytes B" // calculate exp - val exp: Int = (Math.log(bytes.toDouble()) / Math.log(unit.toDouble())).toInt() + val exp: Int = (ln(bytes.toDouble()) / ln(unit.toDouble())).toInt() // determine prefix symbol val prefix: String = ((if (si) "kMGTPE" else "KMGTPE")[exp - 1] + if (si) "" else "i") // calculate result and set number format - val result: Double = bytes / Math.pow(unit.toDouble(), exp.toDouble()) + val result: Double = bytes / unit.toDouble().pow(exp.toDouble()) val numberFormat = NumberFormat.getNumberInstance() numberFormat.maximumFractionDigits = 1 diff --git a/app/src/main/java/org/y20k/trackbook/helpers/PreferencesHelper.kt b/app/src/main/java/org/y20k/trackbook/helpers/PreferencesHelper.kt index 40bba24..1665f63 100644 --- a/app/src/main/java/org/y20k/trackbook/helpers/PreferencesHelper.kt +++ b/app/src/main/java/org/y20k/trackbook/helpers/PreferencesHelper.kt @@ -20,6 +20,7 @@ package org.y20k.trackbook.helpers import android.content.Context import android.location.Location import android.location.LocationManager +import androidx.core.content.edit import androidx.preference.PreferenceManager import org.y20k.trackbook.Keys import org.y20k.trackbook.extensions.getDouble @@ -48,10 +49,8 @@ object PreferencesHelper { fun saveZoomLevel(context: Context, zoomLevel: Double) { // get preferences val settings = PreferenceManager.getDefaultSharedPreferences(context) - val editor = settings.edit() // save zoom level - editor.putDouble(Keys.PREF_MAP_ZOOM_LEVEL, zoomLevel) - editor.apply() + settings.edit { putDouble(Keys.PREF_MAP_ZOOM_LEVEL, zoomLevel) } } @@ -68,10 +67,8 @@ object PreferencesHelper { fun saveTrackingState(context: Context, trackingState: Int) { // get preferences val settings = PreferenceManager.getDefaultSharedPreferences(context) - val editor = settings.edit() // save tracking state - editor.putInt(Keys.PREF_TRACKING_STATE, trackingState) - editor.apply() + settings.edit { putInt(Keys.PREF_TRACKING_STATE, trackingState) } } @@ -122,14 +119,14 @@ object PreferencesHelper { fun saveCurrentBestLocation(context: Context, currentBestLocation: Location) { // get preferences val settings = PreferenceManager.getDefaultSharedPreferences(context) - val editor = settings.edit() - // save location - editor.putDouble(Keys.PREF_CURRENT_BEST_LOCATION_LATITUDE, currentBestLocation.latitude) - editor.putDouble(Keys.PREF_CURRENT_BEST_LOCATION_LONGITUDE, currentBestLocation.longitude) - editor.putFloat(Keys.PREF_CURRENT_BEST_LOCATION_ACCURACY, currentBestLocation.accuracy) - editor.putDouble(Keys.PREF_CURRENT_BEST_LOCATION_ALTITUDE, currentBestLocation.altitude) - editor.putLong(Keys.PREF_CURRENT_BEST_LOCATION_TIME, currentBestLocation.time) - editor.apply() + settings.edit { + // save location + putDouble(Keys.PREF_CURRENT_BEST_LOCATION_LATITUDE, currentBestLocation.latitude) + putDouble(Keys.PREF_CURRENT_BEST_LOCATION_LONGITUDE, currentBestLocation.longitude) + putFloat(Keys.PREF_CURRENT_BEST_LOCATION_ACCURACY, currentBestLocation.accuracy) + putDouble(Keys.PREF_CURRENT_BEST_LOCATION_ALTITUDE, currentBestLocation.altitude) + putLong(Keys.PREF_CURRENT_BEST_LOCATION_TIME, currentBestLocation.time) + } } @@ -149,9 +146,7 @@ object PreferencesHelper { /* Saves state of housekeeping */ fun saveHouseKeepingNecessaryState(context: Context, state: Boolean = false) { val settings = PreferenceManager.getDefaultSharedPreferences(context) - val editor = settings.edit() - editor.putBoolean(Keys.PREF_ONE_TIME_HOUSEKEEPING_NECESSARY, state) - editor.apply() + settings.edit { putBoolean(Keys.PREF_ONE_TIME_HOUSEKEEPING_NECESSARY, state) } } } \ No newline at end of file diff --git a/app/src/main/java/org/y20k/trackbook/helpers/TrackHelper.kt b/app/src/main/java/org/y20k/trackbook/helpers/TrackHelper.kt index 5a30b86..5f12cac 100644 --- a/app/src/main/java/org/y20k/trackbook/helpers/TrackHelper.kt +++ b/app/src/main/java/org/y20k/trackbook/helpers/TrackHelper.kt @@ -181,11 +181,11 @@ object TrackHelper { /* Creates name for GPX file */ private fun createGpxName(track: Track): String { val gpxName = StringBuilder("") - gpxName.append("\t\n"); + gpxName.append("\t\n") gpxName.append("\t\t") gpxName.append("Trackbook Recording: ${track.name}") gpxName.append("\n") - gpxName.append("\t\n"); + gpxName.append("\t\n") return gpxName.toString() } diff --git a/app/src/main/java/org/y20k/trackbook/ui/MapFragmentLayoutHolder.kt b/app/src/main/java/org/y20k/trackbook/ui/MapFragmentLayoutHolder.kt index 1bbcb37..3b908f0 100644 --- a/app/src/main/java/org/y20k/trackbook/ui/MapFragmentLayoutHolder.kt +++ b/app/src/main/java/org/y20k/trackbook/ui/MapFragmentLayoutHolder.kt @@ -28,6 +28,8 @@ import android.view.View import android.view.ViewGroup import androidx.constraintlayout.widget.Group import androidx.core.content.ContextCompat +import androidx.core.view.isGone +import androidx.core.view.isVisible import com.google.android.material.floatingactionbutton.FloatingActionButton import com.google.android.material.snackbar.Snackbar import org.osmdroid.api.IMapController @@ -145,7 +147,7 @@ data class MapFragmentLayoutHolder(private var context: Context, private var mar /* Save current best location and state of map to shared preferences */ fun saveState(currentBestLocation: Location) { PreferencesHelper.saveCurrentBestLocation(context, currentBestLocation) - PreferencesHelper.saveZoomLevel(context, mapView.getZoomLevelDouble()) + PreferencesHelper.saveZoomLevel(context, mapView.zoomLevelDouble) // reset user interaction state userInteraction = false } @@ -176,11 +178,11 @@ data class MapFragmentLayoutHolder(private var context: Context, private var mar when (trackingState) { Keys.STATE_TRACKING_NOT -> { recordingButton.setImageResource(R.drawable.ic_fiber_manual_record_white_24dp) - recordingButtonSubMenu.visibility = View.GONE + recordingButtonSubMenu.isGone = true } Keys.STATE_TRACKING_ACTIVE -> { recordingButton.setImageResource(R.drawable.ic_fiber_manual_record_red_24dp) - recordingButtonSubMenu.visibility = View.GONE + recordingButtonSubMenu.isGone = true } Keys.STATE_TRACKING_STOPPED -> { recordingButton.setImageResource(R.drawable.ic_save_white_24dp) @@ -192,8 +194,8 @@ data class MapFragmentLayoutHolder(private var context: Context, private var mar /* Toggles visibility of recording button sub menu_bottom_navigation */ fun toggleRecordingButtonSubMenu() { when (recordingButtonSubMenu.visibility) { - View.VISIBLE -> recordingButtonSubMenu.visibility = View.GONE - else -> recordingButtonSubMenu.visibility = View.VISIBLE + View.VISIBLE -> recordingButtonSubMenu.isGone = true + else -> recordingButtonSubMenu.isVisible = true } } diff --git a/app/src/main/java/org/y20k/trackbook/ui/TrackFragmentLayoutHolder.kt b/app/src/main/java/org/y20k/trackbook/ui/TrackFragmentLayoutHolder.kt index ef30fdd..463723d 100644 --- a/app/src/main/java/org/y20k/trackbook/ui/TrackFragmentLayoutHolder.kt +++ b/app/src/main/java/org/y20k/trackbook/ui/TrackFragmentLayoutHolder.kt @@ -25,6 +25,8 @@ import android.view.ViewGroup import android.widget.ImageButton import android.widget.Toast import androidx.constraintlayout.widget.Group +import androidx.core.view.isGone +import androidx.core.view.isVisible import androidx.core.widget.NestedScrollView import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.textview.MaterialTextView @@ -210,12 +212,12 @@ data class TrackFragmentLayoutHolder(private var context: Context, private var m // show / hide recording pause if (track.recordingPaused != 0L) { - recordingPausedLabelView.visibility = View.VISIBLE - recordingPausedView.visibility = View.VISIBLE + recordingPausedLabelView.isVisible = true + recordingPausedView.isVisible = true recordingPausedView.text = DateTimeHelper.convertToReadableTime(context, track.recordingPaused) } else { - recordingPausedLabelView.visibility = View.GONE - recordingPausedView.visibility = View.GONE + recordingPausedLabelView.isGone = true + recordingPausedView.isGone = true } // inform user about possible accuracy issues with altitude measurements @@ -247,14 +249,14 @@ data class TrackFragmentLayoutHolder(private var context: Context, private var m when (newState) { BottomSheetBehavior.STATE_EXPANDED -> { statisticsSheet.background = context.getDrawable(R.drawable.shape_statistics_background_expanded) - trackManagementViews.visibility = View.VISIBLE - shareButton.visibility = View.GONE + trackManagementViews.isVisible = true + shareButton.isGone = true // bottomSheet.setPadding(0,24,0,0) } else -> { statisticsSheet.background = context.getDrawable(R.drawable.shape_statistics_background_collapsed) - trackManagementViews.visibility = View.GONE - shareButton.visibility = View.VISIBLE + trackManagementViews.isGone = true + shareButton.isVisible = true // bottomSheet.setPadding(0,0,0,0) } } @@ -262,12 +264,12 @@ data class TrackFragmentLayoutHolder(private var context: Context, private var m override fun onSlide(bottomSheet: View, slideOffset: Float) { if (slideOffset < 0.125f) { statisticsSheet.background = context.getDrawable(R.drawable.shape_statistics_background_collapsed) - trackManagementViews.visibility = View.GONE - shareButton.visibility = View.VISIBLE + trackManagementViews.isGone = true + shareButton.isVisible = true } else { statisticsSheet.background = context.getDrawable(R.drawable.shape_statistics_background_expanded) - trackManagementViews.visibility = View.VISIBLE - shareButton.visibility = View.GONE + trackManagementViews.isVisible = true + shareButton.isGone = true } } } diff --git a/build.gradle b/build.gradle index e2af8fe..3bc3d41 100644 --- a/build.gradle +++ b/build.gradle @@ -3,14 +3,14 @@ buildscript { ext { kotlin_version = '1.4.10' - navigation_version = '2.3.0' + navigation_version = '2.3.1' } repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:4.1.0' + classpath 'com.android.tools.build:gradle:4.1.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$navigation_version"