gpx export now uses file picker (instead of share sheet)
This commit is contained in:
parent
063d84e39f
commit
beb0d2f236
22 changed files with 117 additions and 89 deletions
|
@ -11,7 +11,7 @@ android {
|
||||||
applicationId 'org.y20k.trackbook'
|
applicationId 'org.y20k.trackbook'
|
||||||
minSdkVersion 25
|
minSdkVersion 25
|
||||||
targetSdkVersion 27
|
targetSdkVersion 27
|
||||||
versionCode 27
|
versionCode 37
|
||||||
versionName '2.0.0'
|
versionName '2.0.0'
|
||||||
resConfigs "en", "da", "de", "fr", "id", "it", "ja", "nb-rNO", "nl", "sv", "zh-rCN"
|
resConfigs "en", "da", "de", "fr", "id", "it", "ja", "nb-rNO", "nl", "sv", "zh-rCN"
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,12 +32,6 @@ object Keys {
|
||||||
const val CURRENT_TRACK_FORMAT_VERSION: Int = 4
|
const val CURRENT_TRACK_FORMAT_VERSION: Int = 4
|
||||||
const val CURRENT_TRACKLIST_FORMAT_VERSION: Int = 0
|
const val CURRENT_TRACKLIST_FORMAT_VERSION: Int = 0
|
||||||
|
|
||||||
// other values
|
|
||||||
const val MAXIMUM_TRACK_FILES: Int = 25
|
|
||||||
const val FIFTY_METER_RADIUS: Int = 50
|
|
||||||
const val UNIT_METRIC: Int = 1
|
|
||||||
const val UNIT_IMPERIAL: Int = -1
|
|
||||||
|
|
||||||
// intent actions
|
// intent actions
|
||||||
const val ACTION_START: String = "org.y20k.trackbooks.action.START"
|
const val ACTION_START: String = "org.y20k.trackbooks.action.START"
|
||||||
const val ACTION_STOP: String = "org.y20k.trackbooks.action.STOP"
|
const val ACTION_STOP: String = "org.y20k.trackbooks.action.STOP"
|
||||||
|
@ -78,14 +72,8 @@ object Keys {
|
||||||
const val DIALOG_REMOVE_TRACK: Int = 1
|
const val DIALOG_REMOVE_TRACK: Int = 1
|
||||||
|
|
||||||
// dialog results
|
// dialog results
|
||||||
const val DIALOG_RESULT_DEFAULT: Int = -1
|
|
||||||
const val DIALOG_EMPTY_PAYLOAD_STRING: String = ""
|
const val DIALOG_EMPTY_PAYLOAD_STRING: String = ""
|
||||||
const val DIALOG_EMPTY_PAYLOAD_INT: Int = -1
|
const val DIALOG_EMPTY_PAYLOAD_INT: Int = -1
|
||||||
const val DIALOG_RESULT_SAVE_DIALOG: Int = 1
|
|
||||||
const val DIALOG_RESULT_CLEAR_DIALOG: Int = 2
|
|
||||||
const val DIALOG_RESULT_DELETE_DIALOG: Int = 3
|
|
||||||
const val DIALOG_RESULT_EXPORT_DIALOG: Int = 4
|
|
||||||
const val DIALOG_RESULT_EMPTY_RECORDING_DIALOG: Int = 5
|
|
||||||
|
|
||||||
// folder names
|
// folder names
|
||||||
const val FOLDER_TEMP: String = "temp"
|
const val FOLDER_TEMP: String = "temp"
|
||||||
|
@ -93,16 +81,12 @@ object Keys {
|
||||||
const val FOLDER_GPX: String = "gpx"
|
const val FOLDER_GPX: String = "gpx"
|
||||||
|
|
||||||
// file names and extensions
|
// file names and extensions
|
||||||
|
const val MIME_TYPE_GPX: String = "application/gpx+xml"
|
||||||
const val GPX_FILE_EXTENSION: String = ".gpx"
|
const val GPX_FILE_EXTENSION: String = ".gpx"
|
||||||
const val TRACKBOOK_LEGACY_FILE_EXTENSION: String = ".trackbook"
|
const val TRACKBOOK_LEGACY_FILE_EXTENSION: String = ".trackbook"
|
||||||
const val TRACKBOOK_FILE_EXTENSION: String = ".json"
|
const val TRACKBOOK_FILE_EXTENSION: String = ".json"
|
||||||
const val TEMP_FILE: String = "temp.json"
|
const val TEMP_FILE: String = "temp.json"
|
||||||
const val TRACKLIST_FILE: String = "tracklist.json"
|
const val TRACKLIST_FILE: String = "tracklist.json"
|
||||||
const val PODCAST_COVER_FILE: String = "cover.jpg"
|
|
||||||
const val PODCAST_SMALL_COVER_FILE: String = "cover-small.jpg"
|
|
||||||
const val DEBUG_LOG_FILE: String = "log-can-be-deleted.txt"
|
|
||||||
const val FILE_TYPE_TEMP: Int = 0
|
|
||||||
const val FILE_TYPE_TRACK: Int = 1
|
|
||||||
|
|
||||||
|
|
||||||
// default values
|
// default values
|
||||||
|
@ -127,11 +111,9 @@ object Keys {
|
||||||
const val REQUEST_CODE_FOREGROUND = 42
|
const val REQUEST_CODE_FOREGROUND = 42
|
||||||
|
|
||||||
// requests
|
// requests
|
||||||
|
const val REQUEST_SAVE_GPX: Int = 23
|
||||||
// results
|
|
||||||
|
|
||||||
// notification
|
// notification
|
||||||
const val TRACKER_SERVICE_NOTIFICATION_ID: Int = 1
|
const val TRACKER_SERVICE_NOTIFICATION_ID: Int = 1
|
||||||
const val NOTIFICATION_CHANNEL_RECORDING: String = "notificationChannelIdRecordingChannel"
|
const val NOTIFICATION_CHANNEL_RECORDING: String = "notificationChannelIdRecordingChannel"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,13 @@ package org.y20k.trackbook
|
||||||
|
|
||||||
|
|
||||||
import YesNoDialog
|
import YesNoDialog
|
||||||
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Vibrator
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
@ -36,6 +38,7 @@ import androidx.navigation.fragment.findNavController
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.y20k.trackbook.Keys.ARG_TRACK_ID
|
import org.y20k.trackbook.Keys.ARG_TRACK_ID
|
||||||
|
import org.y20k.trackbook.core.Track
|
||||||
import org.y20k.trackbook.dialogs.RenameTrackDialog
|
import org.y20k.trackbook.dialogs.RenameTrackDialog
|
||||||
import org.y20k.trackbook.helpers.FileHelper
|
import org.y20k.trackbook.helpers.FileHelper
|
||||||
import org.y20k.trackbook.helpers.LogHelper
|
import org.y20k.trackbook.helpers.LogHelper
|
||||||
|
@ -48,17 +51,37 @@ class TrackFragment : Fragment(), RenameTrackDialog.RenameTrackListener, YesNoDi
|
||||||
|
|
||||||
|
|
||||||
/* Main class variables */
|
/* Main class variables */
|
||||||
private lateinit var layout:TrackFragmentLayoutHolder
|
private lateinit var layout: TrackFragmentLayoutHolder
|
||||||
|
private lateinit var track: Track
|
||||||
|
|
||||||
|
|
||||||
|
/* Overrides onCreate from Fragment */
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
// get track
|
||||||
|
val fileUriString: String = arguments?.getString(Keys.ARG_TRACK_FILE_URI, String()) ?: String()
|
||||||
|
if (fileUriString.isNotBlank()) {
|
||||||
|
track = FileHelper.readTrack(activity as Context, Uri.parse(fileUriString))
|
||||||
|
} else {
|
||||||
|
track = Track()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Overrides onCreateView from Fragment */
|
/* Overrides onCreateView from Fragment */
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
// initialize layout
|
// initialize layout
|
||||||
layout = TrackFragmentLayoutHolder(activity as Context, inflater, container, arguments)
|
layout = TrackFragmentLayoutHolder(activity as Context, inflater, container, track)
|
||||||
|
|
||||||
// set up share button
|
// set up share button
|
||||||
layout.shareButton.setOnClickListener {
|
layout.shareButton.setOnClickListener {
|
||||||
shareGpXTrack()
|
openSaveGpxDialog()
|
||||||
|
}
|
||||||
|
layout.shareButton.setOnLongClickListener {
|
||||||
|
val v = (activity as Context).getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
|
||||||
|
v.vibrate(50)
|
||||||
|
shareGpxTrack()
|
||||||
|
return@setOnLongClickListener true
|
||||||
}
|
}
|
||||||
// set up delete button
|
// set up delete button
|
||||||
layout.deleteButton.setOnClickListener {
|
layout.deleteButton.setOnClickListener {
|
||||||
|
@ -90,6 +113,27 @@ class TrackFragment : Fragment(), RenameTrackDialog.RenameTrackListener, YesNoDi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Overrides onActivityResult from Fragment */
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
when (requestCode) {
|
||||||
|
// save GPX file to result file location
|
||||||
|
Keys.REQUEST_SAVE_GPX -> {
|
||||||
|
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||||
|
val sourceUri: Uri = Uri.parse(track.gpxUriString)
|
||||||
|
val targetUri: Uri? = data.data
|
||||||
|
if (targetUri != null) {
|
||||||
|
// copy file async (= fire & forget - no return value needed)
|
||||||
|
GlobalScope.launch { FileHelper.saveCopyOfFileSuspended( activity as Context, originalFileUri = sourceUri, targetFileUri = targetUri) }
|
||||||
|
Toast.makeText(activity as Context, R.string.toast_message_save_gpx, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// let activity handle result
|
||||||
|
else -> super.onActivityResult(requestCode, resultCode, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Overrides onRenameTrackDialog from RenameTrackDialog */
|
/* Overrides onRenameTrackDialog from RenameTrackDialog */
|
||||||
override fun onRenameTrackDialog(textInput: String) {
|
override fun onRenameTrackDialog(textInput: String) {
|
||||||
// rename track async (= fire & forget - no return value needed)
|
// rename track async (= fire & forget - no return value needed)
|
||||||
|
@ -118,17 +162,28 @@ class TrackFragment : Fragment(), RenameTrackDialog.RenameTrackListener, YesNoDi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Opens up a file picker to select the save location */
|
||||||
|
private fun openSaveGpxDialog() {
|
||||||
|
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
|
||||||
|
addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
|
type = Keys.MIME_TYPE_GPX
|
||||||
|
putExtra(Intent.EXTRA_TITLE, FileHelper.getGpxFileName(track))
|
||||||
|
}
|
||||||
|
// file gets saved in onActivityResult
|
||||||
|
startActivityForResult(intent, Keys.REQUEST_SAVE_GPX)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Share track as GPX via share sheet */
|
/* Share track as GPX via share sheet */
|
||||||
private fun shareGpXTrack() {
|
private fun shareGpxTrack() {
|
||||||
val gpxFile = Uri.parse(layout.track.gpxUriString).toFile()
|
val gpxFile = Uri.parse(layout.track.gpxUriString).toFile()
|
||||||
val gpxShareUri = FileProvider.getUriForFile(this.activity as Context, "${activity!!.applicationContext.packageName}.provider", gpxFile)
|
val gpxShareUri = FileProvider.getUriForFile(this.activity as Context, "${activity!!.applicationContext.packageName}.provider", gpxFile)
|
||||||
val shareIntent: Intent = Intent.createChooser(Intent().apply {
|
val shareIntent: Intent = Intent.createChooser(Intent().apply {
|
||||||
action = Intent.ACTION_SEND
|
action = Intent.ACTION_SEND
|
||||||
data = gpxShareUri
|
data = gpxShareUri
|
||||||
type = "application/gpx+xml"
|
type = Keys.MIME_TYPE_GPX
|
||||||
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
|
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
putExtra(Intent.EXTRA_STREAM, gpxShareUri)
|
putExtra(Intent.EXTRA_STREAM, gpxShareUri)
|
||||||
putExtra(Intent.EXTRA_TITLE, getString(R.string.dialog_share_gpx))
|
|
||||||
}, null)
|
}, null)
|
||||||
|
|
||||||
// show share sheet - if file helper is available
|
// show share sheet - if file helper is available
|
||||||
|
|
|
@ -125,8 +125,16 @@ class TracklistFragment : Fragment(), TracklistAdapter.TracklistAdapterListener,
|
||||||
// toggle onboarding layout
|
// toggle onboarding layout
|
||||||
private fun toggleOnboardingLayout(trackCount: Int) {
|
private fun toggleOnboardingLayout(trackCount: Int) {
|
||||||
when (trackCount == 0) {
|
when (trackCount == 0) {
|
||||||
true -> tracklistOnboarding.visibility = View.VISIBLE // show onboarding layout
|
true -> {
|
||||||
false -> tracklistOnboarding.visibility = View.GONE // hide onboarding layout
|
// show onboarding layout
|
||||||
|
tracklistOnboarding.visibility = View.VISIBLE
|
||||||
|
trackElementList.visibility = View.GONE
|
||||||
|
}
|
||||||
|
false -> {
|
||||||
|
// hide onboarding layout
|
||||||
|
tracklistOnboarding.visibility = View.GONE
|
||||||
|
trackElementList.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -154,10 +154,11 @@ object FileHelper {
|
||||||
|
|
||||||
|
|
||||||
/* Creates Uri for Gpx file of a track */
|
/* Creates Uri for Gpx file of a track */
|
||||||
fun getGpxFileUri(context: Context, track: Track): Uri {
|
fun getGpxFileUri(context: Context, track: Track): Uri = File(context.getExternalFilesDir(Keys.FOLDER_GPX), getGpxFileName(track)).toUri()
|
||||||
val fileName: String = DateTimeHelper.convertToSortableDateString(track.recordingStart) + Keys.GPX_FILE_EXTENSION
|
|
||||||
return File(context.getExternalFilesDir(Keys.FOLDER_GPX), fileName).toUri()
|
|
||||||
}
|
/* Creates file name for Gpx file of a track */
|
||||||
|
fun getGpxFileName(track: Track): String = DateTimeHelper.convertToSortableDateString(track.recordingStart) + Keys.GPX_FILE_EXTENSION
|
||||||
|
|
||||||
|
|
||||||
/* Creates Uri for json track file */
|
/* Creates Uri for json track file */
|
||||||
|
@ -232,9 +233,9 @@ object FileHelper {
|
||||||
|
|
||||||
|
|
||||||
/* Suspend function: Wrapper for copyFile */
|
/* Suspend function: Wrapper for copyFile */
|
||||||
suspend fun saveCopyOfFileSuspended(context: Context, originalFileUri: Uri, targetFileUri: Uri) {
|
suspend fun saveCopyOfFileSuspended(context: Context, originalFileUri: Uri, targetFileUri: Uri, deleteOriginal: Boolean = false) {
|
||||||
return suspendCoroutine { cont ->
|
return suspendCoroutine { cont ->
|
||||||
cont.resume(copyFile(context, originalFileUri, targetFileUri, deleteOriginal = true))
|
cont.resume(copyFile(context, originalFileUri, targetFileUri, deleteOriginal))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,6 @@ package org.y20k.trackbook.ui
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
@ -52,7 +50,7 @@ import kotlin.math.roundToInt
|
||||||
/*
|
/*
|
||||||
* TrackFragmentLayoutHolder class
|
* TrackFragmentLayoutHolder class
|
||||||
*/
|
*/
|
||||||
data class TrackFragmentLayoutHolder(var context: Context, var inflater: LayoutInflater, var container: ViewGroup?, var arguments: Bundle?) {
|
data class TrackFragmentLayoutHolder(var context: Context, var inflater: LayoutInflater, var container: ViewGroup?, var track: Track) {
|
||||||
|
|
||||||
/* Define log tag */
|
/* Define log tag */
|
||||||
private val TAG: String = LogHelper.makeLogTag(TrackFragmentLayoutHolder::class.java)
|
private val TAG: String = LogHelper.makeLogTag(TrackFragmentLayoutHolder::class.java)
|
||||||
|
@ -60,7 +58,6 @@ data class TrackFragmentLayoutHolder(var context: Context, var inflater: LayoutI
|
||||||
|
|
||||||
/* Main class variables */
|
/* Main class variables */
|
||||||
val rootView: View
|
val rootView: View
|
||||||
val track: Track
|
|
||||||
val shareButton: ImageButton
|
val shareButton: ImageButton
|
||||||
val deleteButton: ImageButton
|
val deleteButton: ImageButton
|
||||||
val editButton: ImageButton
|
val editButton: ImageButton
|
||||||
|
@ -92,7 +89,7 @@ data class TrackFragmentLayoutHolder(var context: Context, var inflater: LayoutI
|
||||||
// find views
|
// find views
|
||||||
rootView = inflater.inflate(R.layout.fragment_track, container, false)
|
rootView = inflater.inflate(R.layout.fragment_track, container, false)
|
||||||
mapView = rootView.findViewById(R.id.map)
|
mapView = rootView.findViewById(R.id.map)
|
||||||
shareButton = rootView.findViewById(R.id.share_button)
|
shareButton = rootView.findViewById(R.id.save_button)
|
||||||
deleteButton = rootView.findViewById(R.id.delete_button)
|
deleteButton = rootView.findViewById(R.id.delete_button)
|
||||||
editButton = rootView.findViewById(R.id.edit_button)
|
editButton = rootView.findViewById(R.id.edit_button)
|
||||||
trackNameView = rootView.findViewById(R.id.statistics_track_name_headline)
|
trackNameView = rootView.findViewById(R.id.statistics_track_name_headline)
|
||||||
|
@ -136,13 +133,7 @@ data class TrackFragmentLayoutHolder(var context: Context, var inflater: LayoutI
|
||||||
compassOverlay.setCompassCenter(36f, 60f)
|
compassOverlay.setCompassCenter(36f, 60f)
|
||||||
mapView.overlays.add(compassOverlay)
|
mapView.overlays.add(compassOverlay)
|
||||||
|
|
||||||
// get track and create map overlay
|
// create map overlay
|
||||||
val fileUriString: String = arguments?.getString(Keys.ARG_TRACK_FILE_URI, String()) ?: String()
|
|
||||||
if (fileUriString.isNotBlank()) {
|
|
||||||
track = FileHelper.readTrack(context, Uri.parse(fileUriString))
|
|
||||||
} else {
|
|
||||||
track = Track()
|
|
||||||
}
|
|
||||||
trackOverlay = MapHelper.createTrackOverlay(context, track, Keys.STATE_TRACKING_NOT)
|
trackOverlay = MapHelper.createTrackOverlay(context, track, Keys.STATE_TRACKING_NOT)
|
||||||
if (track.wayPoints.isNotEmpty()) {
|
if (track.wayPoints.isNotEmpty()) {
|
||||||
mapView.overlays.add(trackOverlay)
|
mapView.overlays.add(trackOverlay)
|
||||||
|
|
14
app/src/main/res/drawable/ic_delete_24dp.xml
Executable file → Normal file
14
app/src/main/res/drawable/ic_delete_24dp.xml
Executable file → Normal file
|
@ -1,9 +1,9 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:viewportWidth="24.0"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24.0">
|
android:viewportHeight="24">
|
||||||
<path
|
<path
|
||||||
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2L18,7L6,7v12zM8.46,11.88l1.41,-1.41L12,12.59l2.12,-2.12 1.41,1.41L13.41,14l2.12,2.12 -1.41,1.41L12,15.41l-2.12,2.12 -1.41,-1.41L10.59,14l-2.13,-2.12zM15.5,4l-1,-1h-5l-1,1L5,4v2h14L19,4z"
|
android:fillColor="@color/icon_default"
|
||||||
android:fillColor="@color/icon_default" />
|
android:pathData="M16,9v10H8V9h8m-1.5,-6h-5l-1,1H5v2h14V4h-3.5l-1,-1zM18,7H6v12c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7z"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|
|
@ -5,5 +5,5 @@
|
||||||
android:viewportHeight="24.0">
|
android:viewportHeight="24.0">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@color/icon_default"
|
android:fillColor="@color/icon_default"
|
||||||
android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
|
android:pathData="M14.06,9.02l0.92,0.92L5.92,19L5,19v-0.92l9.06,-9.06M17.66,3c-0.25,0 -0.51,0.1 -0.7,0.29l-1.83,1.83 3.75,3.75 1.83,-1.83c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.2,-0.2 -0.45,-0.29 -0.71,-0.29zM14.06,6.19L3,17.25L3,21h3.75L17.81,9.94l-3.75,-3.75z"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|
9
app/src/main/res/drawable/ic_save_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_save_24dp.xml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@color/icon_default"
|
||||||
|
android:pathData="M19,12v7L5,19v-7L3,12v7c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2v-7h-2zM13,12.67l2.59,-2.58L17,11.5l-5,5 -5,-5 1.41,-1.41L11,12.67L11,3h2z"/>
|
||||||
|
</vector>
|
|
@ -1,9 +0,0 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24.0"
|
|
||||||
android:viewportHeight="24.0">
|
|
||||||
<path
|
|
||||||
android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"
|
|
||||||
android:fillColor="@color/icon_default" />
|
|
||||||
</vector>
|
|
|
@ -1,9 +0,0 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:fillColor="@color/icon_default"
|
|
||||||
android:pathData="M20.38,8.57l-1.23,1.85a8,8 0,0 1,-0.22 7.58L5.07,18A8,8 0,0 1,15.58 6.85l1.85,-1.23A10,10 0,0 0,3.35 19a2,2 0,0 0,1.72 1h13.85a2,2 0,0 0,1.74 -1,10 10,0 0,0 -0.27,-10.44zM10.59,15.41a2,2 0,0 0,2.83 0l5.66,-8.49 -8.49,5.66a2,2 0,0 0,0 2.83z"/>
|
|
||||||
</vector>
|
|
|
@ -23,12 +23,11 @@
|
||||||
<include
|
<include
|
||||||
layout="@layout/track_onboarding"
|
layout="@layout/track_onboarding"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/track_element_list"
|
app:layout_constraintTop_toBottomOf="@+id/track_element_list"
|
||||||
tools:visibility="gone" />
|
tools:visibility="gone" />
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
android:backgroundTint="@color/trackbook_transparent"
|
android:backgroundTint="@color/trackbook_transparent"
|
||||||
android:contentDescription="@string/descr_statistics_sheet_delete_button"
|
android:contentDescription="@string/descr_statistics_sheet_delete_button"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/edit_button"
|
app:layout_constraintBottom_toBottomOf="@+id/edit_button"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/share_button"
|
app:layout_constraintEnd_toStartOf="@+id/save_button"
|
||||||
app:layout_constraintTop_toTopOf="@+id/edit_button"
|
app:layout_constraintTop_toTopOf="@+id/edit_button"
|
||||||
app:srcCompat="@drawable/ic_delete_24dp" />
|
app:srcCompat="@drawable/ic_delete_24dp" />
|
||||||
|
|
||||||
|
@ -62,16 +62,16 @@
|
||||||
app:srcCompat="@drawable/ic_edit_24dp" />
|
app:srcCompat="@drawable/ic_edit_24dp" />
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/share_button"
|
android:id="@+id/save_button"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:backgroundTint="@color/trackbook_transparent"
|
android:backgroundTint="@color/trackbook_transparent"
|
||||||
android:contentDescription="@string/descr_statistics_sheet_share_button"
|
android:contentDescription="@string/descr_statistics_sheet_save_button"
|
||||||
android:visibility="visible"
|
android:visibility="visible"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/statistics_track_name_headline"
|
app:layout_constraintBottom_toBottomOf="@+id/statistics_track_name_headline"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@+id/statistics_track_name_headline"
|
app:layout_constraintTop_toTopOf="@+id/statistics_track_name_headline"
|
||||||
app:srcCompat="@drawable/ic_share_24dp" />
|
app:srcCompat="@drawable/ic_save_24dp" />
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
android:id="@+id/statistics_p_distance"
|
android:id="@+id/statistics_p_distance"
|
||||||
|
|
|
@ -54,5 +54,5 @@
|
||||||
<string name="descr_fab_sub_menu_button_clear">Ryd knap</string>
|
<string name="descr_fab_sub_menu_button_clear">Ryd knap</string>
|
||||||
<string name="descr_fab_sub_menu_button_resume">Fortsæt knap</string>
|
<string name="descr_fab_sub_menu_button_resume">Fortsæt knap</string>
|
||||||
<string name="descr_statistics_sheet_delete_button">Slet tur knap</string>
|
<string name="descr_statistics_sheet_delete_button">Slet tur knap</string>
|
||||||
<string name="descr_statistics_sheet_share_button">Del eksport som GPX knap</string>
|
<string name="descr_statistics_sheet_save_button">Del eksport som GPX knap</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -55,5 +55,5 @@
|
||||||
<string name="descr_fab_sub_menu_button_clear">Zurücksetzen-Knopf</string>
|
<string name="descr_fab_sub_menu_button_clear">Zurücksetzen-Knopf</string>
|
||||||
<string name="descr_fab_sub_menu_button_resume">Fortsetzen-Knopf</string>
|
<string name="descr_fab_sub_menu_button_resume">Fortsetzen-Knopf</string>
|
||||||
<string name="descr_statistics_sheet_delete_button">Schaltfläche „Aufzeichnung löschen”</string>
|
<string name="descr_statistics_sheet_delete_button">Schaltfläche „Aufzeichnung löschen”</string>
|
||||||
<string name="descr_statistics_sheet_share_button">Share-Taste, die den Export als GPX anbietet</string>
|
<string name="descr_statistics_sheet_save_button">Share-Taste, die den Export als GPX anbietet</string>
|
||||||
</resources>
|
</resources>
|
|
@ -55,7 +55,7 @@
|
||||||
<string name="descr_fab_sub_menu_button_save">Bouton « Sauvegarder »</string>
|
<string name="descr_fab_sub_menu_button_save">Bouton « Sauvegarder »</string>
|
||||||
<string name="descr_map_current_track">Affichage du parcours actuel</string>
|
<string name="descr_map_current_track">Affichage du parcours actuel</string>
|
||||||
<string name="descr_map_last_track">Affichage du dernier parcours</string>
|
<string name="descr_map_last_track">Affichage du dernier parcours</string>
|
||||||
<string name="descr_statistics_sheet_share_button">Bouton « Partager au format GPX »</string>
|
<string name="descr_statistics_sheet_save_button">Bouton « Partager au format GPX »</string>
|
||||||
<string name="tab_tracks">Itinéraires</string>
|
<string name="tab_tracks">Itinéraires</string>
|
||||||
<string name="tab_settings">Paramètres</string>
|
<string name="tab_settings">Paramètres</string>
|
||||||
<string name="snackbar_message_location_permission_denied">Permission manquante. Le suivi ne fonctionnera pas.</string>
|
<string name="snackbar_message_location_permission_denied">Permission manquante. Le suivi ne fonctionnera pas.</string>
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
<string name="descr_fab_sub_menu_button_clear">Pulsante Cancella</string>
|
<string name="descr_fab_sub_menu_button_clear">Pulsante Cancella</string>
|
||||||
<string name="descr_fab_sub_menu_button_resume">Pulsante Riprendi</string>
|
<string name="descr_fab_sub_menu_button_resume">Pulsante Riprendi</string>
|
||||||
<string name="descr_statistics_sheet_delete_button">Pulsante Elimina traccia</string>
|
<string name="descr_statistics_sheet_delete_button">Pulsante Elimina traccia</string>
|
||||||
<string name="descr_statistics_sheet_share_button">Pulsante Condividi che permette di esportare come GPX</string>
|
<string name="descr_statistics_sheet_save_button">Pulsante Condividi che permette di esportare come GPX</string>
|
||||||
<string name="tab_tracks">Tracce</string>
|
<string name="tab_tracks">Tracce</string>
|
||||||
<string name="tab_settings">Impostazioni</string>
|
<string name="tab_settings">Impostazioni</string>
|
||||||
<string name="snackbar_message_location_permission_denied">Permesso alla posizione non concesso. Trackbook non funzionerà.</string>
|
<string name="snackbar_message_location_permission_denied">Permesso alla posizione non concesso. Trackbook non funzionerà.</string>
|
||||||
|
|
|
@ -55,5 +55,5 @@
|
||||||
<string name="descr_fab_sub_menu_button_clear">クリアボタン</string>
|
<string name="descr_fab_sub_menu_button_clear">クリアボタン</string>
|
||||||
<string name="descr_fab_sub_menu_button_resume">再開ボタン</string>
|
<string name="descr_fab_sub_menu_button_resume">再開ボタン</string>
|
||||||
<string name="descr_statistics_sheet_delete_button">トレース削除ボタン</string>
|
<string name="descr_statistics_sheet_delete_button">トレース削除ボタン</string>
|
||||||
<string name="descr_statistics_sheet_share_button">GPX としてエクスポートする共有ボタン</string>
|
<string name="descr_statistics_sheet_save_button">GPX としてエクスポートする共有ボタン</string>
|
||||||
</resources>
|
</resources>
|
|
@ -55,7 +55,7 @@
|
||||||
<string name="descr_fab_sub_menu_button_clear">Tøm-knapp</string>
|
<string name="descr_fab_sub_menu_button_clear">Tøm-knapp</string>
|
||||||
<string name="descr_fab_sub_menu_button_resume">Fortsett-knapp</string>
|
<string name="descr_fab_sub_menu_button_resume">Fortsett-knapp</string>
|
||||||
<string name="descr_statistics_sheet_delete_button">Sporslettingsknapp</string>
|
<string name="descr_statistics_sheet_delete_button">Sporslettingsknapp</string>
|
||||||
<string name="descr_statistics_sheet_share_button">Delingsknapp som muliggjør eksport som GPX</string>
|
<string name="descr_statistics_sheet_save_button">Delingsknapp som muliggjør eksport som GPX</string>
|
||||||
<string name="tab_tracks">Spor</string>
|
<string name="tab_tracks">Spor</string>
|
||||||
<string name="tab_settings">Innstillinger</string>
|
<string name="tab_settings">Innstillinger</string>
|
||||||
<string name="snackbar_message_location_permission_denied">Plasseringstilgang ikke innvilget. Trackbook vil ikke fungere.</string>
|
<string name="snackbar_message_location_permission_denied">Plasseringstilgang ikke innvilget. Trackbook vil ikke fungere.</string>
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
<string name="descr_fab_sub_menu_button_clear">Wissen-knop</string>
|
<string name="descr_fab_sub_menu_button_clear">Wissen-knop</string>
|
||||||
<string name="descr_fab_sub_menu_button_resume">Voortzetten-knop</string>
|
<string name="descr_fab_sub_menu_button_resume">Voortzetten-knop</string>
|
||||||
<string name="descr_statistics_sheet_delete_button">Track verwijderknop</string>
|
<string name="descr_statistics_sheet_delete_button">Track verwijderknop</string>
|
||||||
<string name="descr_statistics_sheet_share_button">Deelknop met ondersteuning voor het exporteren naar GPX</string>
|
<string name="descr_statistics_sheet_save_button">Deelknop met ondersteuning voor het exporteren naar GPX</string>
|
||||||
<string name="tab_tracks">Routes</string>
|
<string name="tab_tracks">Routes</string>
|
||||||
<string name="tab_settings">Instellingen</string>
|
<string name="tab_settings">Instellingen</string>
|
||||||
<string name="snackbar_message_location_permission_denied">Locatiemachtiging niet verleend. Trackbook zal niet werken.</string>
|
<string name="snackbar_message_location_permission_denied">Locatiemachtiging niet verleend. Trackbook zal niet werken.</string>
|
||||||
|
|
|
@ -87,7 +87,7 @@
|
||||||
<string name="descr_mark_starred_button">加星按钮</string>
|
<string name="descr_mark_starred_button">加星按钮</string>
|
||||||
<string name="descr_statistics_sheet_delete_button">删除记录按钮</string>
|
<string name="descr_statistics_sheet_delete_button">删除记录按钮</string>
|
||||||
<string name="descr_statistics_sheet_edit_button">记录编辑按钮</string>
|
<string name="descr_statistics_sheet_edit_button">记录编辑按钮</string>
|
||||||
<string name="descr_statistics_sheet_share_button">以GPX文件分享按钮</string>
|
<string name="descr_statistics_sheet_save_button">以GPX文件分享按钮</string>
|
||||||
<!-- Sample Text -->
|
<!-- Sample Text -->
|
||||||
<string name="sample_text_track_data" translatable="false">23.0 km • 5 时 23 分 42 秒</string>
|
<string name="sample_text_track_data" translatable="false">23.0 km • 5 时 23 分 42 秒</string>
|
||||||
<string name="sample_text_track_name" translatable="false">1969年7月20日</string>
|
<string name="sample_text_track_name" translatable="false">1969年7月20日</string>
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
<!-- Toast Messages -->
|
<!-- Toast Messages -->
|
||||||
<string name="toast_message_elevation_info">Hint: The accuracy of elevation data depends on your device. The uphill and downhill elevation of the whole route is measured.</string>
|
<string name="toast_message_elevation_info">Hint: The accuracy of elevation data depends on your device. The uphill and downhill elevation of the whole route is measured.</string>
|
||||||
<string name="toast_message_install_file_helper">Please install a file manager or a GPX track viewer first.</string>
|
<string name="toast_message_install_file_helper">Please install a file manager or a GPX track viewer first.</string>
|
||||||
|
<string name="toast_message_save_gpx">Saving recording as GPX.</string>
|
||||||
<!-- Map Markers -->
|
<!-- Map Markers -->
|
||||||
<string name="marker_description_time">Time</string>
|
<string name="marker_description_time">Time</string>
|
||||||
<string name="marker_description_accuracy">Accuracy</string>
|
<string name="marker_description_accuracy">Accuracy</string>
|
||||||
|
@ -64,7 +65,7 @@
|
||||||
<string name="track_list_onboarding_h1_part_1">Your recorded tracks</string>
|
<string name="track_list_onboarding_h1_part_1">Your recorded tracks</string>
|
||||||
<string name="track_list_onboarding_h1_part_2">… will show up here.</string>
|
<string name="track_list_onboarding_h1_part_2">… will show up here.</string>
|
||||||
<!-- Settings -->
|
<!-- Settings -->
|
||||||
<string name="pref_accuracy_threshold_summary">Discard location fixes with an accuracy larger than</string>
|
<string name="pref_accuracy_threshold_summary">Discard location fixes with an accuracy larger than:</string>
|
||||||
<string name="pref_accuracy_threshold_title">Accuracy Threshold</string>
|
<string name="pref_accuracy_threshold_title">Accuracy Threshold</string>
|
||||||
<string name="pref_advanced_title">Advanced</string>
|
<string name="pref_advanced_title">Advanced</string>
|
||||||
<string name="pref_general_title">General</string>
|
<string name="pref_general_title">General</string>
|
||||||
|
@ -97,7 +98,7 @@
|
||||||
<string name="descr_quick_settings_tile_title_stop">Stop Recording</string>
|
<string name="descr_quick_settings_tile_title_stop">Stop Recording</string>
|
||||||
<string name="descr_statistics_sheet_delete_button">Track delete button</string>
|
<string name="descr_statistics_sheet_delete_button">Track delete button</string>
|
||||||
<string name="descr_statistics_sheet_edit_button">Track edit button</string>
|
<string name="descr_statistics_sheet_edit_button">Track edit button</string>
|
||||||
<string name="descr_statistics_sheet_share_button">Share as GPX button</string>
|
<string name="descr_statistics_sheet_save_button">Save as GPX button</string>
|
||||||
<!-- Sample Text -->
|
<!-- Sample Text -->
|
||||||
<string name="sample_text_track_data" translatable="false">23.0 km • 5 hrs 23 min 42 sec</string>
|
<string name="sample_text_track_data" translatable="false">23.0 km • 5 hrs 23 min 42 sec</string>
|
||||||
<string name="sample_text_track_name" translatable="false">July 20, 1969</string>
|
<string name="sample_text_track_name" translatable="false">July 20, 1969</string>
|
||||||
|
|
Loading…
Reference in a new issue