From beb0d2f236550f49bcf52ccda4a9fcf2dbb95d24 Mon Sep 17 00:00:00 2001 From: y20k Date: Thu, 13 Feb 2020 17:12:34 +0100 Subject: [PATCH] gpx export now uses file picker (instead of share sheet) --- app/build.gradle | 2 +- app/src/main/java/org/y20k/trackbook/Keys.kt | 22 +----- .../java/org/y20k/trackbook/TrackFragment.kt | 67 +++++++++++++++++-- .../org/y20k/trackbook/TracklistFragment.kt | 12 +++- .../org/y20k/trackbook/helpers/FileHelper.kt | 13 ++-- .../trackbook/ui/TrackFragmentLayoutHolder.kt | 15 +---- app/src/main/res/drawable/ic_delete_24dp.xml | 14 ++-- app/src/main/res/drawable/ic_edit_24dp.xml | 2 +- app/src/main/res/drawable/ic_save_24dp.xml | 9 +++ app/src/main/res/drawable/ic_share_24dp.xml | 9 --- app/src/main/res/drawable/ic_speed_24px.xml | 9 --- .../main/res/layout/fragment_tracklist.xml | 3 +- app/src/main/res/layout/track_statistics.xml | 8 +-- app/src/main/res/values-da/strings.xml | 2 +- app/src/main/res/values-de/strings.xml | 2 +- app/src/main/res/values-fr/strings.xml | 2 +- app/src/main/res/values-it/strings.xml | 2 +- app/src/main/res/values-ja/strings.xml | 2 +- app/src/main/res/values-nb-rNO/strings.xml | 2 +- app/src/main/res/values-nl/strings.xml | 2 +- app/src/main/res/values-zh-rCN/strings.xml | 2 +- app/src/main/res/values/strings.xml | 5 +- 22 files changed, 117 insertions(+), 89 deletions(-) mode change 100755 => 100644 app/src/main/res/drawable/ic_delete_24dp.xml create mode 100644 app/src/main/res/drawable/ic_save_24dp.xml delete mode 100755 app/src/main/res/drawable/ic_share_24dp.xml delete mode 100644 app/src/main/res/drawable/ic_speed_24px.xml diff --git a/app/build.gradle b/app/build.gradle index d9e0633..9bc36ac 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,7 +11,7 @@ android { applicationId 'org.y20k.trackbook' minSdkVersion 25 targetSdkVersion 27 - versionCode 27 + versionCode 37 versionName '2.0.0' resConfigs "en", "da", "de", "fr", "id", "it", "ja", "nb-rNO", "nl", "sv", "zh-rCN" } diff --git a/app/src/main/java/org/y20k/trackbook/Keys.kt b/app/src/main/java/org/y20k/trackbook/Keys.kt index dc971dc..277f191 100644 --- a/app/src/main/java/org/y20k/trackbook/Keys.kt +++ b/app/src/main/java/org/y20k/trackbook/Keys.kt @@ -32,12 +32,6 @@ object Keys { const val CURRENT_TRACK_FORMAT_VERSION: Int = 4 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 const val ACTION_START: String = "org.y20k.trackbooks.action.START" const val ACTION_STOP: String = "org.y20k.trackbooks.action.STOP" @@ -78,14 +72,8 @@ object Keys { const val DIALOG_REMOVE_TRACK: Int = 1 // dialog results - const val DIALOG_RESULT_DEFAULT: Int = -1 const val DIALOG_EMPTY_PAYLOAD_STRING: String = "" 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 const val FOLDER_TEMP: String = "temp" @@ -93,16 +81,12 @@ object Keys { const val FOLDER_GPX: String = "gpx" // file names and extensions + const val MIME_TYPE_GPX: String = "application/gpx+xml" const val GPX_FILE_EXTENSION: String = ".gpx" const val TRACKBOOK_LEGACY_FILE_EXTENSION: String = ".trackbook" const val TRACKBOOK_FILE_EXTENSION: String = ".json" const val TEMP_FILE: String = "temp.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 @@ -127,11 +111,9 @@ object Keys { const val REQUEST_CODE_FOREGROUND = 42 // requests - - // results + const val REQUEST_SAVE_GPX: Int = 23 // notification const val TRACKER_SERVICE_NOTIFICATION_ID: Int = 1 const val NOTIFICATION_CHANNEL_RECORDING: String = "notificationChannelIdRecordingChannel" - } diff --git a/app/src/main/java/org/y20k/trackbook/TrackFragment.kt b/app/src/main/java/org/y20k/trackbook/TrackFragment.kt index 706fbe1..b124ed7 100644 --- a/app/src/main/java/org/y20k/trackbook/TrackFragment.kt +++ b/app/src/main/java/org/y20k/trackbook/TrackFragment.kt @@ -19,11 +19,13 @@ package org.y20k.trackbook import YesNoDialog +import android.app.Activity import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.net.Uri import android.os.Bundle +import android.os.Vibrator import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -36,6 +38,7 @@ import androidx.navigation.fragment.findNavController import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import org.y20k.trackbook.Keys.ARG_TRACK_ID +import org.y20k.trackbook.core.Track import org.y20k.trackbook.dialogs.RenameTrackDialog import org.y20k.trackbook.helpers.FileHelper import org.y20k.trackbook.helpers.LogHelper @@ -48,17 +51,37 @@ class TrackFragment : Fragment(), RenameTrackDialog.RenameTrackListener, YesNoDi /* 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 */ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { // initialize layout - layout = TrackFragmentLayoutHolder(activity as Context, inflater, container, arguments) + layout = TrackFragmentLayoutHolder(activity as Context, inflater, container, track) // set up share button 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 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 */ override fun onRenameTrackDialog(textInput: String) { // 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 */ - private fun shareGpXTrack() { + private fun shareGpxTrack() { val gpxFile = Uri.parse(layout.track.gpxUriString).toFile() val gpxShareUri = FileProvider.getUriForFile(this.activity as Context, "${activity!!.applicationContext.packageName}.provider", gpxFile) val shareIntent: Intent = Intent.createChooser(Intent().apply { action = Intent.ACTION_SEND data = gpxShareUri - type = "application/gpx+xml" + type = Keys.MIME_TYPE_GPX flags = Intent.FLAG_GRANT_READ_URI_PERMISSION putExtra(Intent.EXTRA_STREAM, gpxShareUri) - putExtra(Intent.EXTRA_TITLE, getString(R.string.dialog_share_gpx)) }, null) // show share sheet - if file helper is available diff --git a/app/src/main/java/org/y20k/trackbook/TracklistFragment.kt b/app/src/main/java/org/y20k/trackbook/TracklistFragment.kt index 4c52350..fa3f544 100644 --- a/app/src/main/java/org/y20k/trackbook/TracklistFragment.kt +++ b/app/src/main/java/org/y20k/trackbook/TracklistFragment.kt @@ -125,8 +125,16 @@ class TracklistFragment : Fragment(), TracklistAdapter.TracklistAdapterListener, // toggle onboarding layout private fun toggleOnboardingLayout(trackCount: Int) { when (trackCount == 0) { - true -> tracklistOnboarding.visibility = View.VISIBLE // show onboarding layout - false -> tracklistOnboarding.visibility = View.GONE // hide onboarding layout + true -> { + // show onboarding layout + tracklistOnboarding.visibility = View.VISIBLE + trackElementList.visibility = View.GONE + } + false -> { + // hide onboarding layout + tracklistOnboarding.visibility = View.GONE + trackElementList.visibility = View.VISIBLE + } } } 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 049e317..39e832a 100644 --- a/app/src/main/java/org/y20k/trackbook/helpers/FileHelper.kt +++ b/app/src/main/java/org/y20k/trackbook/helpers/FileHelper.kt @@ -154,10 +154,11 @@ object FileHelper { /* Creates Uri for Gpx file of a track */ - fun getGpxFileUri(context: Context, track: Track): Uri { - val fileName: String = DateTimeHelper.convertToSortableDateString(track.recordingStart) + Keys.GPX_FILE_EXTENSION - return File(context.getExternalFilesDir(Keys.FOLDER_GPX), fileName).toUri() - } + fun getGpxFileUri(context: Context, track: Track): Uri = File(context.getExternalFilesDir(Keys.FOLDER_GPX), getGpxFileName(track)).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 */ @@ -232,9 +233,9 @@ object FileHelper { /* 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 -> - cont.resume(copyFile(context, originalFileUri, targetFileUri, deleteOriginal = true)) + cont.resume(copyFile(context, originalFileUri, targetFileUri, deleteOriginal)) } } 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 c171a3a..d73f911 100644 --- a/app/src/main/java/org/y20k/trackbook/ui/TrackFragmentLayoutHolder.kt +++ b/app/src/main/java/org/y20k/trackbook/ui/TrackFragmentLayoutHolder.kt @@ -19,8 +19,6 @@ package org.y20k.trackbook.ui import android.app.Activity import android.content.Context -import android.net.Uri -import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -52,7 +50,7 @@ import kotlin.math.roundToInt /* * 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 */ 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 */ val rootView: View - val track: Track val shareButton: ImageButton val deleteButton: ImageButton val editButton: ImageButton @@ -92,7 +89,7 @@ data class TrackFragmentLayoutHolder(var context: Context, var inflater: LayoutI // find views rootView = inflater.inflate(R.layout.fragment_track, container, false) 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) editButton = rootView.findViewById(R.id.edit_button) 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) mapView.overlays.add(compassOverlay) - // get track and 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() - } + // create map overlay trackOverlay = MapHelper.createTrackOverlay(context, track, Keys.STATE_TRACKING_NOT) if (track.wayPoints.isNotEmpty()) { mapView.overlays.add(trackOverlay) diff --git a/app/src/main/res/drawable/ic_delete_24dp.xml b/app/src/main/res/drawable/ic_delete_24dp.xml old mode 100755 new mode 100644 index 651f304..8698fa6 --- a/app/src/main/res/drawable/ic_delete_24dp.xml +++ b/app/src/main/res/drawable/ic_delete_24dp.xml @@ -1,9 +1,9 @@ - + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + diff --git a/app/src/main/res/drawable/ic_edit_24dp.xml b/app/src/main/res/drawable/ic_edit_24dp.xml index 1a9a294..6c65efa 100644 --- a/app/src/main/res/drawable/ic_edit_24dp.xml +++ b/app/src/main/res/drawable/ic_edit_24dp.xml @@ -5,5 +5,5 @@ android:viewportHeight="24.0"> + 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"/> diff --git a/app/src/main/res/drawable/ic_save_24dp.xml b/app/src/main/res/drawable/ic_save_24dp.xml new file mode 100644 index 0000000..14e3ad6 --- /dev/null +++ b/app/src/main/res/drawable/ic_save_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_share_24dp.xml b/app/src/main/res/drawable/ic_share_24dp.xml deleted file mode 100755 index 24bf669..0000000 --- a/app/src/main/res/drawable/ic_share_24dp.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_speed_24px.xml b/app/src/main/res/drawable/ic_speed_24px.xml deleted file mode 100644 index 0eb105b..0000000 --- a/app/src/main/res/drawable/ic_speed_24px.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/layout/fragment_tracklist.xml b/app/src/main/res/layout/fragment_tracklist.xml index 4b8fea5..cc535b7 100644 --- a/app/src/main/res/layout/fragment_tracklist.xml +++ b/app/src/main/res/layout/fragment_tracklist.xml @@ -23,12 +23,11 @@ - diff --git a/app/src/main/res/layout/track_statistics.xml b/app/src/main/res/layout/track_statistics.xml index 118a42e..a86f81d 100755 --- a/app/src/main/res/layout/track_statistics.xml +++ b/app/src/main/res/layout/track_statistics.xml @@ -46,7 +46,7 @@ android:backgroundTint="@color/trackbook_transparent" android:contentDescription="@string/descr_statistics_sheet_delete_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:srcCompat="@drawable/ic_delete_24dp" /> @@ -62,16 +62,16 @@ app:srcCompat="@drawable/ic_edit_24dp" /> + app:srcCompat="@drawable/ic_save_24dp" /> Ryd knap Fortsæt knap Slet tur knap - Del eksport som GPX knap + Del eksport som GPX knap diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 229f740..92ecba2 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -55,5 +55,5 @@ Zurücksetzen-Knopf Fortsetzen-Knopf Schaltfläche „Aufzeichnung löschen” - Share-Taste, die den Export als GPX anbietet + Share-Taste, die den Export als GPX anbietet \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 938c895..31f7963 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -55,7 +55,7 @@ Bouton « Sauvegarder » Affichage du parcours actuel Affichage du dernier parcours - Bouton « Partager au format GPX » + Bouton « Partager au format GPX » Itinéraires Paramètres Permission manquante. Le suivi ne fonctionnera pas. diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 3413d27..ad6b56a 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -55,7 +55,7 @@ Pulsante Cancella Pulsante Riprendi Pulsante Elimina traccia - Pulsante Condividi che permette di esportare come GPX + Pulsante Condividi che permette di esportare come GPX Tracce Impostazioni Permesso alla posizione non concesso. Trackbook non funzionerà. diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 340ffd1..f41c2d8 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -55,5 +55,5 @@ クリアボタン 再開ボタン トレース削除ボタン - GPX としてエクスポートする共有ボタン + GPX としてエクスポートする共有ボタン \ No newline at end of file diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 59b9986..7572ae5 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -55,7 +55,7 @@ Tøm-knapp Fortsett-knapp Sporslettingsknapp - Delingsknapp som muliggjør eksport som GPX + Delingsknapp som muliggjør eksport som GPX Spor Innstillinger Plasseringstilgang ikke innvilget. Trackbook vil ikke fungere. diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 1777ed4..b89899d 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -55,7 +55,7 @@ Wissen-knop Voortzetten-knop Track verwijderknop - Deelknop met ondersteuning voor het exporteren naar GPX + Deelknop met ondersteuning voor het exporteren naar GPX Routes Instellingen Locatiemachtiging niet verleend. Trackbook zal niet werken. diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index d89b48e..09dd8ca 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -87,7 +87,7 @@ 加星按钮 删除记录按钮 记录编辑按钮 - 以GPX文件分享按钮 + 以GPX文件分享按钮 23.0 km • 5 时 23 分 42 秒 1969年7月20日 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 853a101..70a4c07 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -39,6 +39,7 @@ Hint: The accuracy of elevation data depends on your device. The uphill and downhill elevation of the whole route is measured. Please install a file manager or a GPX track viewer first. + Saving recording as GPX. Time Accuracy @@ -64,7 +65,7 @@ Your recorded tracks … will show up here. - Discard location fixes with an accuracy larger than + Discard location fixes with an accuracy larger than: Accuracy Threshold Advanced General @@ -97,7 +98,7 @@ Stop Recording Track delete button Track edit button - Share as GPX button + Save as GPX button 23.0 km • 5 hrs 23 min 42 sec July 20, 1969