Implements most of of the changes proposed by @TacoTheDank (thank you!) in this pull request (see https://github.com/y20k/trackbook/pull/91)
This commit is contained in:
parent
1b69980491
commit
eb296188d8
16 changed files with 79 additions and 76 deletions
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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()
|
||||
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()
|
||||
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) }
|
||||
}
|
||||
|
||||
}
|
|
@ -181,11 +181,11 @@ object TrackHelper {
|
|||
/* Creates name for GPX file */
|
||||
private fun createGpxName(track: Track): String {
|
||||
val gpxName = StringBuilder("")
|
||||
gpxName.append("\t<metadata>\n");
|
||||
gpxName.append("\t<metadata>\n")
|
||||
gpxName.append("\t\t<name>")
|
||||
gpxName.append("Trackbook Recording: ${track.name}")
|
||||
gpxName.append("</name>\n")
|
||||
gpxName.append("\t</metadata>\n");
|
||||
gpxName.append("\t</metadata>\n")
|
||||
return gpxName.toString()
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
Loading…
Reference in a new issue