Fix #1340 mass track deletion time

This commit is contained in:
Peter Storch
2022-08-19 22:25:01 +02:00
parent 0ada9a2463
commit 5a5f040ed5
36 changed files with 69 additions and 88 deletions
@@ -84,8 +84,8 @@ public abstract class AbstractTrackDeleteActivity extends AbstractActivity imple
/** /**
* Called every time a track is deleted. * Called every time a track is deleted.
*/ */
protected void onTrackDeleteStatus(TrackDeleteService.DeleteStatus deleteStatus) { protected void onTrackDeleteStatus(TrackDeleteService.DeletionFinishedStatus deletionFinishedStatus) {
if (deleteStatus.isFinished() && trackDeleteServiceConnection != null) { if (trackDeleteServiceConnection != null) {
trackDeleteServiceConnection.unbind(this); trackDeleteServiceConnection.unbind(this);
trackDeleteServiceConnection = null; trackDeleteServiceConnection = null;
onDeleteFinished(); onDeleteFinished();
@@ -232,9 +232,9 @@ public class TrackRecordedActivity extends AbstractTrackDeleteActivity implement
} }
@Override @Override
protected void onTrackDeleteStatus(TrackDeleteService.DeleteStatus deleteStatus) { protected void onTrackDeleteStatus(TrackDeleteService.DeletionFinishedStatus deletionFinishedStatus) {
super.onTrackDeleteStatus(deleteStatus); super.onTrackDeleteStatus(deletionFinishedStatus);
if (deleteStatus.isDeleted(trackId)) { if (deletionFinishedStatus.isDeleted(trackId)) {
runOnUiThread(this::finish); runOnUiThread(this::finish);
} }
} }
@@ -187,7 +187,6 @@ public class ContentProviderUtils {
FileUtils.deleteDirectoryRecurse(FileUtils.getPhotoDir(context, trackId)); FileUtils.deleteDirectoryRecurse(FileUtils.getPhotoDir(context, trackId));
} }
// Delete track last since it triggers a database vacuum call
String whereClause = String.format(TracksColumns._ID + " IN (%s)", TextUtils.join(",", Collections.nCopies(trackIds.size(), "?"))); String whereClause = String.format(TracksColumns._ID + " IN (%s)", TextUtils.join(",", Collections.nCopies(trackIds.size(), "?")));
contentResolver.delete(TracksColumns.CONTENT_URI, whereClause, trackIds.stream().map(id -> Long.toString(id.getId())).toArray(String[]::new)); contentResolver.delete(TracksColumns.CONTENT_URI, whereClause, trackIds.stream().map(id -> Long.toString(id.getId())).toArray(String[]::new));
} }
@@ -195,8 +194,6 @@ public class ContentProviderUtils {
public void deleteTrack(Context context, @NonNull Track.Id trackId) { public void deleteTrack(Context context, @NonNull Track.Id trackId) {
// Delete track folder resources. // Delete track folder resources.
FileUtils.deleteDirectoryRecurse(FileUtils.getPhotoDir(context, trackId)); FileUtils.deleteDirectoryRecurse(FileUtils.getPhotoDir(context, trackId));
// Delete track last since it triggers a database vacuum call
contentResolver.delete(TracksColumns.CONTENT_URI, TracksColumns._ID + "=?", new String[]{Long.toString(trackId.getId())}); contentResolver.delete(TracksColumns.CONTENT_URI, TracksColumns._ID + "=?", new String[]{Long.toString(trackId.getId())});
} }
@@ -27,6 +27,7 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteQueryBuilder; import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
@@ -39,6 +40,7 @@ import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.data.tables.MarkerColumns; import de.dennisguse.opentracks.data.tables.MarkerColumns;
import de.dennisguse.opentracks.data.tables.TrackPointsColumns; import de.dennisguse.opentracks.data.tables.TrackPointsColumns;
import de.dennisguse.opentracks.data.tables.TracksColumns; import de.dennisguse.opentracks.data.tables.TracksColumns;
import de.dennisguse.opentracks.settings.PreferencesUtils;
/** /**
* A {@link ContentProvider} that handles access to track points, tracks, and markers tables. * A {@link ContentProvider} that handles access to track points, tracks, and markers tables.
@@ -53,6 +55,8 @@ public class CustomContentProvider extends ContentProvider {
private static final String SQL_LIST_DELIMITER = ","; private static final String SQL_LIST_DELIMITER = ",";
private static final int TOTAL_DELETED_ROWS_VACUUM_THRESHOLD = 10000;
private final UriMatcher uriMatcher; private final UriMatcher uriMatcher;
private SQLiteDatabase db; private SQLiteDatabase db;
@@ -131,14 +135,12 @@ public class CustomContentProvider extends ContentProvider {
@Override @Override
public int delete(@NonNull Uri url, String where, String[] selectionArgs) { public int delete(@NonNull Uri url, String where, String[] selectionArgs) {
String table; String table;
boolean shouldVacuum = false;
switch (getUrlType(url)) { switch (getUrlType(url)) {
case TRACKPOINTS: case TRACKPOINTS:
table = TrackPointsColumns.TABLE_NAME; table = TrackPointsColumns.TABLE_NAME;
break; break;
case TRACKS: case TRACKS:
table = TracksColumns.TABLE_NAME; table = TracksColumns.TABLE_NAME;
shouldVacuum = true;
break; break;
case MARKERS: case MARKERS:
table = MarkerColumns.TABLE_NAME; table = MarkerColumns.TABLE_NAME;
@@ -147,23 +149,40 @@ public class CustomContentProvider extends ContentProvider {
throw new IllegalArgumentException("Unknown URL " + url); throw new IllegalArgumentException("Unknown URL " + url);
} }
Log.w(TAG, "Deleting table " + table); Log.w(TAG, "Deleting from table " + table);
int count; int totalChangesBefore = getTotalChanges();
int deletedRowsFromTable;
try { try {
db.beginTransaction(); db.beginTransaction();
count = db.delete(table, where, selectionArgs); deletedRowsFromTable = db.delete(table, where, selectionArgs);
Log.i(TAG, "Deleted " + deletedRowsFromTable + " rows of table " + table);
db.setTransactionSuccessful(); db.setTransactionSuccessful();
} finally { } finally {
db.endTransaction(); db.endTransaction();
} }
getContext().getContentResolver().notifyChange(url, null, false); getContext().getContentResolver().notifyChange(url, null, false);
if (shouldVacuum) { int totalChanges = getTotalChanges() - totalChangesBefore;
// If a potentially large amount of data was deleted, reclaim its space. Log.i(TAG, "Deleted " + totalChanges + " total rows from database");
Log.i(TAG, "Vacuuming the database.");
PreferencesUtils.addTotalRowsDeleted(totalChanges);
int totalRowsDeleted = PreferencesUtils.getTotalRowsDeleted();
if (totalRowsDeleted > TOTAL_DELETED_ROWS_VACUUM_THRESHOLD) {
Log.i(TAG, "TotalRowsDeleted " + totalRowsDeleted + ", starting to vacuum the database.");
db.execSQL("VACUUM"); db.execSQL("VACUUM");
PreferencesUtils.resetTotalRowsDeleted();
} }
return count;
return deletedRowsFromTable;
}
private int getTotalChanges() {
int totalCount;
try (Cursor cursor = db.rawQuery("SELECT total_changes()", null)) {
cursor.moveToNext();
totalCount = cursor.getInt(0);
}
return totalCount;
} }
@Override @Override
@@ -25,6 +25,7 @@ import de.dennisguse.opentracks.data.models.Marker;
import de.dennisguse.opentracks.data.models.Speed; import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.stats.TrackStatistics; import de.dennisguse.opentracks.stats.TrackStatistics;
import de.dennisguse.opentracks.stats.TrackStatisticsUpdater; import de.dennisguse.opentracks.stats.TrackStatisticsUpdater;
import de.dennisguse.opentracks.ui.markers.MarkerUtils; import de.dennisguse.opentracks.ui.markers.MarkerUtils;
@@ -290,4 +291,5 @@ public class TrackImporter {
public void cleanImport() { public void cleanImport() {
contentProviderUtils.deleteTracks(context, trackIds); contentProviderUtils.deleteTracks(context, trackIds);
} }
} }
@@ -15,12 +15,14 @@ import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.ContentProviderUtils; import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.settings.PreferencesUtils;
public class TrackDeleteService extends Service { public class TrackDeleteService extends Service {
@@ -31,7 +33,7 @@ public class TrackDeleteService extends Service {
private final Binder binder = new Binder(); private final Binder binder = new Binder();
private ExecutorService serviceExecutor; private ExecutorService serviceExecutor;
private MutableLiveData<DeleteStatus> deleteResultObservable; private MutableLiveData<DeletionFinishedStatus> deleteResultObservable;
private NotificationManager notificationManager; private NotificationManager notificationManager;
private NotificationCompat.Builder notificationBuilder; private NotificationCompat.Builder notificationBuilder;
@@ -59,22 +61,18 @@ public class TrackDeleteService extends Service {
return START_NOT_STICKY; return START_NOT_STICKY;
} }
private void deleteTracks(@NonNull ArrayList<Track.Id> trackIds) { private void deleteTracks(@NonNull List<Track.Id> trackIds) {
sendResult(null,0, trackIds.size());
serviceExecutor.execute(() -> { serviceExecutor.execute(() -> {
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(this); ContentProviderUtils contentProviderUtils = new ContentProviderUtils(this);
for (int i = 0; i < trackIds.size(); i++) { contentProviderUtils.deleteTracks(this, trackIds);
updateNotification(i + 1, trackIds.size()); sendResult(trackIds);
contentProviderUtils.deleteTrack(this, trackIds.get(i));
sendResult(trackIds.get(i), i + 1, trackIds.size());
}
stopSelf(); stopSelf();
}); });
} }
private void sendResult(Track.Id trackId, int deletes, int total) { private void sendResult(List<Track.Id> trackIds) {
if (deleteResultObservable != null) { if (deleteResultObservable != null) {
deleteResultObservable.postValue(new DeleteStatus(trackId, deletes, total)); deleteResultObservable.postValue(new DeletionFinishedStatus(trackIds));
} }
} }
@@ -83,7 +81,7 @@ public class TrackDeleteService extends Service {
return binder; return binder;
} }
public LiveData<DeleteStatus> getDeletingStatusObservable() { public LiveData<DeletionFinishedStatus> getDeletingStatusObservable() {
return deleteResultObservable; return deleteResultObservable;
} }
@@ -106,25 +104,13 @@ public class TrackDeleteService extends Service {
notificationBuilder = new NotificationCompat.Builder(this, CHANNEL_ID); notificationBuilder = new NotificationCompat.Builder(this, CHANNEL_ID);
notificationBuilder notificationBuilder
.setContentTitle(this.getString(R.string.track_delete_progress_message)) .setContentTitle(this.getString(R.string.track_delete_progress_message))
.setContentText(this.getString(R.string.track_delete_progress, 0, tracksToDelete)) .setContentText(this.getString(R.string.track_delete_number_of_tracks, tracksToDelete))
.setSmallIcon(R.drawable.ic_logo_color_24dp) .setSmallIcon(R.drawable.ic_logo_color_24dp)
.setProgress(tracksToDelete, 0, false); .setProgress(0, 0, true);
startForeground(NOTIFICATION_ID, notificationBuilder.build()); startForeground(NOTIFICATION_ID, notificationBuilder.build());
} }
/**
* Updates notification progress.
*
* @param progress number of tracks already deleted.
* @param total total of tracks to be deleted.
*/
private void updateNotification(int progress, int total) {
notificationBuilder.setProgress(total, progress, false);
notificationBuilder.setContentText(this.getString(R.string.track_delete_progress, progress, total));
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
}
public class Binder extends android.os.Binder { public class Binder extends android.os.Binder {
private Binder() { private Binder() {
@@ -136,36 +122,25 @@ public class TrackDeleteService extends Service {
} }
} }
public static class DeleteStatus { public static class DeletionFinishedStatus {
private final int progress; private final List<Track.Id> trackIds;
private final int max;
private final Track.Id trackId;
/** /**
* @param trackId Track.Id just deleted if any. * @param trackIds List of deleted Track.Ids.
* @param progress number of deletes.
* @param max total of deletes to be done.
*/ */
private DeleteStatus(@Nullable Track.Id trackId, int progress, int max) { private DeletionFinishedStatus(@Nullable List<Track.Id> trackIds) {
this.trackId = trackId; this.trackIds = trackIds;
this.progress = progress;
this.max = max;
}
public boolean isFinished() {
return progress == max;
} }
public boolean isDeleted(Track.Id trackId) { public boolean isDeleted(Track.Id trackId) {
return this.trackId != null && this.trackId.equals(trackId); return this.trackIds != null && this.trackIds.contains(trackId);
} }
@NonNull @NonNull
@Override @Override
public String toString() { public String toString() {
return "DeleteStatus{" + return "DeleteStatus{" +
"number of deletes=" + progress + "trackIds=" + trackIds +
", total=" + max +
'}'; '}';
} }
} }
@@ -826,4 +826,17 @@ public class PreferencesUtils {
return getString(R.string.show_on_map_format_key, IntentDashboardUtils.PREFERENCE_ID_ASK); return getString(R.string.show_on_map_format_key, IntentDashboardUtils.PREFERENCE_ID_ASK);
} }
public static int getTotalRowsDeleted() {
return getInt(R.string.total_rows_deleted_key, 0);
}
public static void addTotalRowsDeleted(final int totalRowsDeletedToAdd) {
int newTotalRowsDeleted = getTotalRowsDeleted() + totalRowsDeletedToAdd;
setInt(R.string.total_rows_deleted_key, newTotalRowsDeleted);
}
public static void resetTotalRowsDeleted() {
setInt(R.string.total_rows_deleted_key, 0);
}
} }
-1
View File
@@ -411,7 +411,6 @@
<string name="stats_split_interval">Intervalo partido</string> <string name="stats_split_interval">Intervalo partido</string>
<string name="track_recording_notification_accuracy">Precisión de ubicación: %1$s</string> <string name="track_recording_notification_accuracy">Precisión de ubicación: %1$s</string>
<string name="track_pace_notification">Ritmo: %1$s</string> <string name="track_pace_notification">Ritmo: %1$s</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="track_detail_intervals_tab">Intervalos</string> <string name="track_detail_intervals_tab">Intervalos</string>
<string name="interval_list_empty_message">Aún no hay ningún intervalo</string> <string name="interval_list_empty_message">Aún no hay ningún intervalo</string>
<string name="settings_recording_customize_layout_title">Personalice su pantalla de grabación</string> <string name="settings_recording_customize_layout_title">Personalice su pantalla de grabación</string>
-1
View File
@@ -458,7 +458,6 @@ limitations under the License.
<string name="settings_recording_show_on_lockscreen_while_recording_title">Показване на статистически данни на заключения екран</string> <string name="settings_recording_show_on_lockscreen_while_recording_title">Показване на статистически данни на заключения екран</string>
<string name="help_data_google_play_services_title">Изисква ли OpenTracks/използва ли услугата Google Play\?</string> <string name="help_data_google_play_services_title">Изисква ли OpenTracks/използва ли услугата Google Play\?</string>
<string name="about_version_code">Код на версията: %1$d</string> <string name="about_version_code">Код на версията: %1$d</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="export_error_post_workout">Експортът след тренировка е неуспешен, моля, проверете директорията за експорт.</string> <string name="export_error_post_workout">Експортът след тренировка е неуспешен, моля, проверете директорията за експорт.</string>
<string name="about_third_party_data">Данни от трети страни</string> <string name="about_third_party_data">Данни от трети страни</string>
<string name="import_unsupported_format">Неподдържан формат на файла</string> <string name="import_unsupported_format">Неподдържан формат на файла</string>
-1
View File
@@ -469,7 +469,6 @@ limitations under the License.
<string name="track_speed_notification">Rychlost: %1$s</string> <string name="track_speed_notification">Rychlost: %1$s</string>
<string name="track_pace_notification">Rychlost: %1$s</string> <string name="track_pace_notification">Rychlost: %1$s</string>
<string name="about_third_party_data">Údaje třetích stran</string> <string name="about_third_party_data">Údaje třetích stran</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="delete_service">Služba mazání</string> <string name="delete_service">Služba mazání</string>
<string name="menu_voice_rate">Rychlost hlasových oznámení</string> <string name="menu_voice_rate">Rychlost hlasových oznámení</string>
<string name="track_delete_not_recording">Není možno vymazat aktuálně zaznamenávanou trasu.</string> <string name="track_delete_not_recording">Není možno vymazat aktuálně zaznamenávanou trasu.</string>
-1
View File
@@ -467,7 +467,6 @@ Hvis GPS-enheden rapporterer unøjagtige data (f.eks. Placering, hastighed, høj
<string name="track_speed_notification">Hastighed: %1$s</string> <string name="track_speed_notification">Hastighed: %1$s</string>
<string name="about_third_party_data">Data fra tredjeparter</string> <string name="about_third_party_data">Data fra tredjeparter</string>
<string name="delete_service">Tjeneste til sletning</string> <string name="delete_service">Tjeneste til sletning</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="menu_voice_rate">Stemmehastighed</string> <string name="menu_voice_rate">Stemmehastighed</string>
<string name="track_delete_not_recording">Dette spor kan ikke slettes, da det er optaget i øjeblikket.</string> <string name="track_delete_not_recording">Dette spor kan ikke slettes, da det er optaget i øjeblikket.</string>
<string name="settings_sensor_cycling_distance_speed">Afstand og hastighed</string> <string name="settings_sensor_cycling_distance_speed">Afstand og hastighed</string>
-1
View File
@@ -470,7 +470,6 @@ Meldet das GPS-Gerät ungenaue Daten (z.B. Standort, Geschwindigkeit, Höhe), ka
<string name="sensor_state_heart_rate_avg">Durchschnittlicher Herzfrequenz</string> <string name="sensor_state_heart_rate_avg">Durchschnittlicher Herzfrequenz</string>
<string name="settings_prevent_reimport_tracks_title">Verhindere den erneuten Import von Strecken(aufzeichnungen)</string> <string name="settings_prevent_reimport_tracks_title">Verhindere den erneuten Import von Strecken(aufzeichnungen)</string>
<string name="import_no_kml_file_found">Keine doc.kml Datei im KMZ gefunden</string> <string name="import_no_kml_file_found">Keine doc.kml Datei im KMZ gefunden</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="import_thread_interrupted">Thread unterbrochen</string> <string name="import_thread_interrupted">Thread unterbrochen</string>
<string name="import_unable_to_import_file">Importieren der Datei gescheitert: %1$s</string> <string name="import_unable_to_import_file">Importieren der Datei gescheitert: %1$s</string>
<string name="delete_service">Löschdienst</string> <string name="delete_service">Löschdienst</string>
-1
View File
@@ -464,7 +464,6 @@ limitations under the License.
<string name="track_pace_notification">Ritmo: %1$s</string> <string name="track_pace_notification">Ritmo: %1$s</string>
<string name="about_third_party_data">Datos de terceros</string> <string name="about_third_party_data">Datos de terceros</string>
<string name="delete_service">Borrar servicio</string> <string name="delete_service">Borrar servicio</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="menu_voice_rate">Velocidad de la voz</string> <string name="menu_voice_rate">Velocidad de la voz</string>
<string name="track_delete_not_recording">Este recorrido no puede ser eliminado porque se está grabando actualmente.</string> <string name="track_delete_not_recording">Este recorrido no puede ser eliminado porque se está grabando actualmente.</string>
<string name="settings_sensor_running_speed_and_cadence">Distancia, velocidad y cadencia</string> <string name="settings_sensor_running_speed_and_cadence">Distancia, velocidad y cadencia</string>
-1
View File
@@ -464,7 +464,6 @@ limitations under the License.
<string name="track_pace_notification">Tempo: %1$s</string> <string name="track_pace_notification">Tempo: %1$s</string>
<string name="about_third_party_data">Kolmanda osapoole andmed</string> <string name="about_third_party_data">Kolmanda osapoole andmed</string>
<string name="delete_service">Kustutamise teenus</string> <string name="delete_service">Kustutamise teenus</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="menu_voice_rate">Hääle kiirus</string> <string name="menu_voice_rate">Hääle kiirus</string>
<string name="track_delete_not_recording">Seda pala ei saa kustutada, kuna see on praegu salvestatud.</string> <string name="track_delete_not_recording">Seda pala ei saa kustutada, kuna see on praegu salvestatud.</string>
<string name="settings_sensor_cycling_cadence">Rütm</string> <string name="settings_sensor_cycling_cadence">Rütm</string>
-1
View File
@@ -467,7 +467,6 @@ GPS gailuak datu okerrak salatzen baditu (adibidez, kokapena, abiadura, kota), O
<string name="track_pace_notification">Erritmoa: %1$s</string> <string name="track_pace_notification">Erritmoa: %1$s</string>
<string name="about_third_party_data">Hirugarrenen datuak</string> <string name="about_third_party_data">Hirugarrenen datuak</string>
<string name="delete_service">Ezabatzeko zerbitzua</string> <string name="delete_service">Ezabatzeko zerbitzua</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="menu_voice_rate">Ahots abiadura</string> <string name="menu_voice_rate">Ahots abiadura</string>
<string name="track_delete_not_recording">Pista hau ezin da ezabatu da gaur egun grabatzen.</string> <string name="track_delete_not_recording">Pista hau ezin da ezabatu da gaur egun grabatzen.</string>
<string name="settings_sensor_cycling_cadence">Kadentzia</string> <string name="settings_sensor_cycling_cadence">Kadentzia</string>
-1
View File
@@ -469,7 +469,6 @@ limitations under the License.
<string name="track_speed_notification">Nopeus: %1$s</string> <string name="track_speed_notification">Nopeus: %1$s</string>
<string name="about_third_party_data">Kolmannen osapuolen tiedot</string> <string name="about_third_party_data">Kolmannen osapuolen tiedot</string>
<string name="delete_service">Poistopalvelu</string> <string name="delete_service">Poistopalvelu</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="menu_voice_rate">Äänen nopeus</string> <string name="menu_voice_rate">Äänen nopeus</string>
<string name="track_delete_not_recording">Tätä reittiä ei voi poistaa koska sitä tallennetaan parhaillaan.</string> <string name="track_delete_not_recording">Tätä reittiä ei voi poistaa koska sitä tallennetaan parhaillaan.</string>
<string name="settings_sensor_cycling_cadence">Pyöräily: tahtiaika</string> <string name="settings_sensor_cycling_cadence">Pyöräily: tahtiaika</string>
-1
View File
@@ -465,7 +465,6 @@ Si le dispositif GPS signale des données inexactes (par exemple, la localisatio
<string name="export_track_already_exists_msg">La trace %1$s existe déjà dans le répertoire de destination.</string> <string name="export_track_already_exists_msg">La trace %1$s existe déjà dans le répertoire de destination.</string>
<string name="export_progress_summary_overwrite_msg">Traces écrasées</string> <string name="export_progress_summary_overwrite_msg">Traces écrasées</string>
<string name="about_third_party_data">Données de tiers</string> <string name="about_third_party_data">Données de tiers</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="delete_service">Service de suppression</string> <string name="delete_service">Service de suppression</string>
<string name="menu_voice_rate">Vitesse vocale</string> <string name="menu_voice_rate">Vitesse vocale</string>
<string name="track_delete_not_recording">Cette piste ne peut pas être supprimée car elle est en cours d\'enregistrement.</string> <string name="track_delete_not_recording">Cette piste ne peut pas être supprimée car elle est en cours d\'enregistrement.</string>
-1
View File
@@ -472,7 +472,6 @@ Se te detés ou estás en interiores, non se gardarán datos do sensor (mais ser
<string name="track_speed_notification">Velocidade: %1$s</string> <string name="track_speed_notification">Velocidade: %1$s</string>
<string name="about_third_party_data">Datos de terceiros alleos</string> <string name="about_third_party_data">Datos de terceiros alleos</string>
<string name="delete_service">Eliminación de servizo</string> <string name="delete_service">Eliminación de servizo</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="menu_voice_rate">Velocidade da voz</string> <string name="menu_voice_rate">Velocidade da voz</string>
<string name="track_delete_not_recording">Esta pista non se pode eliminar porque está a funcionar a gravación.</string> <string name="track_delete_not_recording">Esta pista non se pode eliminar porque está a funcionar a gravación.</string>
<string name="settings_sensor_cycling_distance_speed">Distancia e Velocidade</string> <string name="settings_sensor_cycling_distance_speed">Distancia e Velocidade</string>
-1
View File
@@ -460,7 +460,6 @@ limitations under the License.
\n * pályák megjelenítése térképen (lásd alább)</string> \n * pályák megjelenítése térképen (lásd alább)</string>
<string name="about_third_party_data">Harmadik féltől származó adatok</string> <string name="about_third_party_data">Harmadik féltől származó adatok</string>
<string name="delete_service">Törlési szolgáltatás</string> <string name="delete_service">Törlési szolgáltatás</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="menu_voice_rate">Hang sebesség</string> <string name="menu_voice_rate">Hang sebesség</string>
<string name="track_delete_not_recording">Ez a sáv nem törölhető, mivel jelenleg is rögzítve van.</string> <string name="track_delete_not_recording">Ez a sáv nem törölhető, mivel jelenleg is rögzítve van.</string>
<string name="settings_sensor_cycling_cadence">Kerékpározás: lépésszám</string> <string name="settings_sensor_cycling_cadence">Kerékpározás: lépésszám</string>
-1
View File
@@ -471,7 +471,6 @@ Infatti, un\'applicazione deve supportare <i>ACTION_VIEW</i> con MIME <i>applica
<string name="track_pace_notification">Ritmo: %1$s</string> <string name="track_pace_notification">Ritmo: %1$s</string>
<string name="about_third_party_data">Dati di terzi</string> <string name="about_third_party_data">Dati di terzi</string>
<string name="delete_service">Servizio di eliminazione</string> <string name="delete_service">Servizio di eliminazione</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="menu_voice_rate">Velocità della voce</string> <string name="menu_voice_rate">Velocità della voce</string>
<string name="track_delete_not_recording">Questa traccia non può essere cancellata perché è attualmente in registrazione.</string> <string name="track_delete_not_recording">Questa traccia non può essere cancellata perché è attualmente in registrazione.</string>
<string name="settings_sensor_cycling_cadence">Cadenza</string> <string name="settings_sensor_cycling_cadence">Cadenza</string>
-1
View File
@@ -416,7 +416,6 @@ limitations under the License.
<string name="help_recording_content">OpenTracks naudoja prietaiso GPS jutiklį, kad nuolat įrašytų vietą. Jei GPS įrenginys praneša apie netikslius duomenis (pvz., Vietą, greitį, aukštį), OpenTracks negali nieko padaryti.</string> <string name="help_recording_content">OpenTracks naudoja prietaiso GPS jutiklį, kad nuolat įrašytų vietą. Jei GPS įrenginys praneša apie netikslius duomenis (pvz., Vietą, greitį, aukštį), OpenTracks negali nieko padaryti.</string>
<string name="generic_open_track">Atidaryti takelį</string> <string name="generic_open_track">Atidaryti takelį</string>
<string name="settings_recording_keep_screen_on_while_recording_summary">Įrašydami palaikykite ekraną įjungtą.</string> <string name="settings_recording_keep_screen_on_while_recording_summary">Įrašydami palaikykite ekraną įjungtą.</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="open_track_as_GPX">Atidaryti kaip GPX</string> <string name="open_track_as_GPX">Atidaryti kaip GPX</string>
<string name="help_gps_troubleshooting_title">OpenTracks nefiksuoja vietų\?</string> <string name="help_gps_troubleshooting_title">OpenTracks nefiksuoja vietų\?</string>
<string name="generic_overwrite">Perrašyti</string> <string name="generic_overwrite">Perrašyti</string>
-1
View File
@@ -416,7 +416,6 @@ limitations under the License.
<string name="help_track_export_title">Kā es varu eksportēt/ kopīgot ierakstītos ierakstus\?</string> <string name="help_track_export_title">Kā es varu eksportēt/ kopīgot ierakstītos ierakstus\?</string>
<string name="instant_export_enabled_summary">Dziesmas eksportēšana uz krātuvi pēc ierakstīšanas pabeigšanas</string> <string name="instant_export_enabled_summary">Dziesmas eksportēšana uz krātuvi pēc ierakstīšanas pabeigšanas</string>
<string name="activity_type_escooter">eScooter</string> <string name="activity_type_escooter">eScooter</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="sensor_state_power_avg">Vidējā jauda</string> <string name="sensor_state_power_avg">Vidējā jauda</string>
<string name="about_libraries">Bibliotēkas</string> <string name="about_libraries">Bibliotēkas</string>
<string name="description_default_speed_or_pace">Pēc aktivitātes veida</string> <string name="description_default_speed_or_pace">Pēc aktivitātes veida</string>
-1
View File
@@ -460,7 +460,6 @@ limitations under the License.
<string name="track_pace_notification">Tempo: %1$s</string> <string name="track_pace_notification">Tempo: %1$s</string>
<string name="about_third_party_data">Tredjepartsdata</string> <string name="about_third_party_data">Tredjepartsdata</string>
<string name="delete_service">Slettingstjeneste</string> <string name="delete_service">Slettingstjeneste</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="menu_voice_rate">Talehastighet</string> <string name="menu_voice_rate">Talehastighet</string>
<string name="track_delete_not_recording">Dette sporet kan ikke slettes da det tas opp nå.</string> <string name="track_delete_not_recording">Dette sporet kan ikke slettes da det tas opp nå.</string>
<string name="settings_sensor_cycling_cadence">Kadens</string> <string name="settings_sensor_cycling_cadence">Kadens</string>
-1
View File
@@ -465,7 +465,6 @@ Als het GPS-apparaat onnauwkeurige gegevens rapporteert (bijv. locatie, snelheid
<string name="track_distance_notification">Afstand: %1$s</string> <string name="track_distance_notification">Afstand: %1$s</string>
<string name="track_pace_notification">Tempo: %1$s</string> <string name="track_pace_notification">Tempo: %1$s</string>
<string name="about_third_party_data">Gegevens van derden</string> <string name="about_third_party_data">Gegevens van derden</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="delete_service">Dienst verwijdering</string> <string name="delete_service">Dienst verwijdering</string>
<string name="menu_voice_rate">Spraak snelheid</string> <string name="menu_voice_rate">Spraak snelheid</string>
<string name="track_delete_not_recording">Dit fragment kan niet worden gewist omdat het momenteel is opgenomen.</string> <string name="track_delete_not_recording">Dit fragment kan niet worden gewist omdat het momenteel is opgenomen.</string>
-1
View File
@@ -476,7 +476,6 @@ limitations under the License.
<string name="track_distance_notification">Odległość: %1$s</string> <string name="track_distance_notification">Odległość: %1$s</string>
<string name="about_third_party_data">Dane osób trzecich</string> <string name="about_third_party_data">Dane osób trzecich</string>
<string name="delete_service">Usługa usuwania</string> <string name="delete_service">Usługa usuwania</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="menu_voice_rate">Szybkość głosu</string> <string name="menu_voice_rate">Szybkość głosu</string>
<string name="track_delete_not_recording">Tej ścieżki nie można usunąć, ponieważ jest ona aktualnie nagrywana.</string> <string name="track_delete_not_recording">Tej ścieżki nie można usunąć, ponieważ jest ona aktualnie nagrywana.</string>
<string name="settings_sensor_cycling_distance_speed">Dystans i Prędkość</string> <string name="settings_sensor_cycling_distance_speed">Dystans i Prędkość</string>
-1
View File
@@ -404,7 +404,6 @@
<string name="track_pace_notification">Parcela: %1$s</string> <string name="track_pace_notification">Parcela: %1$s</string>
<string name="about_third_party_data">Dados de terceiros</string> <string name="about_third_party_data">Dados de terceiros</string>
<string name="delete_service">Serviço de exclusão</string> <string name="delete_service">Serviço de exclusão</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="menu_voice_rate">Velocidade da voz</string> <string name="menu_voice_rate">Velocidade da voz</string>
<string name="track_delete_not_recording">Esta trilha não pode ser excluída porque está gravada no momento.</string> <string name="track_delete_not_recording">Esta trilha não pode ser excluída porque está gravada no momento.</string>
<plurals name="voiceSpeedKilometersPerHour"> <plurals name="voiceSpeedKilometersPerHour">
-1
View File
@@ -426,7 +426,6 @@ limitations under the License.
<string name="import_progress_summary_exists_msg">Există deja</string> <string name="import_progress_summary_exists_msg">Există deja</string>
<string name="track_detail_intervals_tab">Intervaluri</string> <string name="track_detail_intervals_tab">Intervaluri</string>
<string name="track_recording_notification_accuracy">Precizia locației: %1$s</string> <string name="track_recording_notification_accuracy">Precizia locației: %1$s</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="sensor_state_cadence_max">Max Cadență</string> <string name="sensor_state_cadence_max">Max Cadență</string>
<string name="sensor_could_not_scan">Nu a fost posibilă scanarea pentru dispozitive Bluetooth (eroare %1$i).</string> <string name="sensor_could_not_scan">Nu a fost posibilă scanarea pentru dispozitive Bluetooth (eroare %1$i).</string>
<string name="share_image_subject">Aș dori să vă împărtășesc o imagine</string> <string name="share_image_subject">Aș dori să vă împărtășesc o imagine</string>
-1
View File
@@ -465,7 +465,6 @@ limitations under the License.
<string name="generic_overwrite">Перезаписать</string> <string name="generic_overwrite">Перезаписать</string>
<string name="import_prevent_reimport">Вы настроили предотвращение повторного импорта трека</string> <string name="import_prevent_reimport">Вы настроили предотвращение повторного импорта трека</string>
<string name="delete_service">Услуга удаления</string> <string name="delete_service">Услуга удаления</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="about_third_party_data">Сторонние данные</string> <string name="about_third_party_data">Сторонние данные</string>
<string name="menu_voice_rate">Скорость голоса</string> <string name="menu_voice_rate">Скорость голоса</string>
<string name="track_delete_not_recording">Эта дорожка не может быть удалена, поскольку она записана в данный момент.</string> <string name="track_delete_not_recording">Эта дорожка не может быть удалена, поскольку она записана в данный момент.</string>
-1
View File
@@ -517,7 +517,6 @@ limitations under the License.
<string name="settings_sensors_title">Senzory Bluetooth</string> <string name="settings_sensors_title">Senzory Bluetooth</string>
<string name="settings_sensors_summary">Cyklistické snímače, obvod kolies, snímače behu</string> <string name="settings_sensors_summary">Cyklistické snímače, obvod kolies, snímače behu</string>
<string name="settings_open_tracks_summary">Viac o projekte OpenTracks</string> <string name="settings_open_tracks_summary">Viac o projekte OpenTracks</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="settings_gps_summary">Interval času, interval vzdialenosti, Max. vzdialenosť, Presnosť</string> <string name="settings_gps_summary">Interval času, interval vzdialenosti, Max. vzdialenosť, Presnosť</string>
<string name="help_support_content"/> <string name="help_support_content"/>
<string name="share_image_body">Myslím, že by vás mohol zaujímať tento obrázok.</string> <string name="share_image_body">Myslím, že by vás mohol zaujímať tento obrázok.</string>
-1
View File
@@ -488,7 +488,6 @@ limitations under the License.
<string name="lap_time">Čas kroga</string> <string name="lap_time">Čas kroga</string>
<string name="track_detail_intervals_tab">Intervali</string> <string name="track_detail_intervals_tab">Intervali</string>
<string name="track_delete_not_recording">Te sledi ni mogoče izbrisati, saj je trenutno posneta.</string> <string name="track_delete_not_recording">Te sledi ni mogoče izbrisati, saj je trenutno posneta.</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="stats_clock">Ura</string> <string name="stats_clock">Ura</string>
<string name="settings_import_section">Uvoz</string> <string name="settings_import_section">Uvoz</string>
<string name="share_image_subject">Rad bi z vami delil sliko</string> <string name="share_image_subject">Rad bi z vami delil sliko</string>
-1
View File
@@ -431,7 +431,6 @@ limitations under the License.
<string name="generic_overwrite">Skriva</string> <string name="generic_overwrite">Skriva</string>
<string name="generic_separator_done_total">/</string> <string name="generic_separator_done_total">/</string>
<string name="export_track_errors">Spår som inte exporteras</string> <string name="export_track_errors">Spår som inte exporteras</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="help_data_storage_content"> Sensordata lagras per inspelad plats. När det gäller en pulssensor betyder det att endast <i>en</i> pulsmätning lagras per plats. Om du står stilla eller är inomhus, kommer inga sensordata att registreras (men det kommer att visas). </string> <string name="help_data_storage_content"> Sensordata lagras per inspelad plats. När det gäller en pulssensor betyder det att endast <i>en</i> pulsmätning lagras per plats. Om du står stilla eller är inomhus, kommer inga sensordata att registreras (men det kommer att visas). </string>
<string name="help_recording_title">Hur registrerar OpenTracks data\?</string> <string name="help_recording_title">Hur registrerar OpenTracks data\?</string>
<string name="about_description"><i>OpenTracks</i> är ett program för sportspårning som helt respekterar din integritet.</string> <string name="about_description"><i>OpenTracks</i> är ett program för sportspårning som helt respekterar din integritet.</string>
-1
View File
@@ -492,7 +492,6 @@ limitations under the License.
<string name="settings_prevent_reimport_tracks_title">Parçaların yeniden içe aktarılmasını önleme</string> <string name="settings_prevent_reimport_tracks_title">Parçaların yeniden içe aktarılmasını önleme</string>
<string name="stats_coordinates">Enlem/Boylam</string> <string name="stats_coordinates">Enlem/Boylam</string>
<string name="stats_sensors_power">Güç</string> <string name="stats_sensors_power">Güç</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="aggregated_stats_filter_no_results">Belirtilen filtre için etkinlik yok</string> <string name="aggregated_stats_filter_no_results">Belirtilen filtre için etkinlik yok</string>
<string name="value_float_kilometer_hour">%1$.1f km/s</string> <string name="value_float_kilometer_hour">%1$.1f km/s</string>
<string name="custom_layout_list_title">Dizilimler</string> <string name="custom_layout_list_title">Dizilimler</string>
-1
View File
@@ -472,7 +472,6 @@ limitations under the License.
<string name="track_pace_notification">Темп: %1$s</string> <string name="track_pace_notification">Темп: %1$s</string>
<string name="about_third_party_data">Дані третіх сторін</string> <string name="about_third_party_data">Дані третіх сторін</string>
<string name="delete_service">Служба видалення</string> <string name="delete_service">Служба видалення</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="track_delete_not_recording">Цей трек не може бути видалений в тому вигляді, в якому він записаний в даний момент.</string> <string name="track_delete_not_recording">Цей трек не може бути видалений в тому вигляді, в якому він записаний в даний момент.</string>
<string name="menu_voice_rate">Швидкість передачі голосу</string> <string name="menu_voice_rate">Швидкість передачі голосу</string>
<string name="settings_sensor_cycling_cadence">Велоспорт: частота обертання педалей</string> <string name="settings_sensor_cycling_cadence">Велоспорт: частота обертання педалей</string>
-1
View File
@@ -471,7 +471,6 @@ limitations under the License.
<string name="interval_list_empty_message">Không có bất kỳ khoảng thời gian sơ</string> <string name="interval_list_empty_message">Không có bất kỳ khoảng thời gian sơ</string>
<string name="aggregated_stats_empty_message">Hồ sơ của đua đầu tiên, để xem tổng thống kê</string> <string name="aggregated_stats_empty_message">Hồ sơ của đua đầu tiên, để xem tổng thống kê</string>
<string name="track_detail_intervals_tab">Khoảng thời gian</string> <string name="track_detail_intervals_tab">Khoảng thời gian</string>
<string name="track_delete_progress">%1$d/%2$d</string>
<string name="settings_recording_keep_screen_on_while_recording_title">Giữ trên màn hình</string> <string name="settings_recording_keep_screen_on_while_recording_title">Giữ trên màn hình</string>
<string name="bluetooth_disabled">Xin vui lòng cho phép Bluetooth.</string> <string name="bluetooth_disabled">Xin vui lòng cho phép Bluetooth.</string>
<string name="sensor_state_cadence_avg">Nhịp trung bình</string> <string name="sensor_state_cadence_avg">Nhịp trung bình</string>
+2
View File
@@ -46,6 +46,8 @@
<string name="show_on_map_format_key" translatable="false">showOnMapFormatKey</string> <string name="show_on_map_format_key" translatable="false">showOnMapFormatKey</string>
<string name="total_rows_deleted_key" translatable="false">totalRowsDeletedKey</string>
<string name="settings_default_export_directory_key" translatable="false">settingsDefaultExportDirectory</string> <string name="settings_default_export_directory_key" translatable="false">settingsDefaultExportDirectory</string>
<string name="post_workout_export_enabled_key" translatable="false">instantExportEnabled</string> <string name="post_workout_export_enabled_key" translatable="false">instantExportEnabled</string>
<bool name="post_workout_export_enabled_default" translatable="false">false</bool> <bool name="post_workout_export_enabled_default" translatable="false">false</bool>
+1 -1
View File
@@ -494,7 +494,7 @@ limitations under the License.
<string name="track_delete_one_confirm_title">Delete track?</string> <string name="track_delete_one_confirm_title">Delete track?</string>
<string name="track_delete_multiple_confirm_message">The selected tracks and their markers will be permanently deleted from the device.</string> <string name="track_delete_multiple_confirm_message">The selected tracks and their markers will be permanently deleted from the device.</string>
<string name="track_delete_progress_message">Deleting&#8230;</string> <string name="track_delete_progress_message">Deleting&#8230;</string>
<string name="track_delete_progress">%1$d/%2$d</string> <string name="track_delete_number_of_tracks">%1$d tracks</string>
<string name="track_delete_not_recording">This track cannot be deleted as it is currently recorded.</string> <string name="track_delete_not_recording">This track cannot be deleted as it is currently recorded.</string>
<string name="track_discarding">Discarding Track</string> <string name="track_discarding">Discarding Track</string>
<!-- Track Detail --> <!-- Track Detail -->