diff --git a/android_app/app/build.gradle b/android_app/app/build.gradle index 99fbccd7..c65c7e01 100644 --- a/android_app/app/build.gradle +++ b/android_app/app/build.gradle @@ -6,7 +6,7 @@ android { defaultConfig { applicationId "com.health.openscale" testApplicationId "com.health.openscale.test" - minSdkVersion 18 + minSdkVersion 19 targetSdkVersion 27 versionCode 23 versionName "1.7" diff --git a/android_app/app/src/main/java/com/health/openscale/core/OpenScale.java b/android_app/app/src/main/java/com/health/openscale/core/OpenScale.java index e13b6d8d..6b9fe3b4 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/OpenScale.java +++ b/android_app/app/src/main/java/com/health/openscale/core/OpenScale.java @@ -49,10 +49,11 @@ import com.health.openscale.core.utils.CsvHelper; import com.health.openscale.gui.fragments.FragmentUpdateListener; import java.io.BufferedReader; -import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; import java.text.ParseException; import java.util.ArrayList; import java.util.Calendar; @@ -194,6 +195,18 @@ public class OpenScale { public void deleteScaleUser(int id) { userDAO.delete(userDAO.get(id)); selectedScaleUser = null; + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + + // Remove user specific settings + SharedPreferences.Editor editor = prefs.edit(); + final String prefix = ScaleUser.getPreferenceKey(id, ""); + for (String key : prefs.getAll().keySet()) { + if (key.startsWith(prefix)) { + editor.remove(key); + } + } + editor.apply(); } public void updateScaleUser(ScaleUser user) { @@ -332,7 +345,7 @@ public class OpenScale { updateScaleData(); } - private String getFilenameFromUri(Uri uri) { + public String getFilenameFromUri(Uri uri) { Cursor cursor = context.getContentResolver().query( uri, null, null, null, null); cursor.moveToFirst(); @@ -362,9 +375,10 @@ public class OpenScale { } } - public boolean exportData(String filename) { + public boolean exportData(Uri uri) { try { - CsvHelper.exportTo(new FileWriter(filename), scaleMeasurementList); + OutputStream output = context.getContentResolver().openOutputStream(uri); + CsvHelper.exportTo(new OutputStreamWriter(output), scaleMeasurementList); return true; } catch (IOException e) { Toast.makeText(context, context.getResources().getString(R.string.error_exporting) + " " + e.getMessage(), Toast.LENGTH_SHORT).show(); diff --git a/android_app/app/src/main/java/com/health/openscale/core/datatypes/ScaleUser.java b/android_app/app/src/main/java/com/health/openscale/core/datatypes/ScaleUser.java index d99df719..b5d28f8b 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/datatypes/ScaleUser.java +++ b/android_app/app/src/main/java/com/health/openscale/core/datatypes/ScaleUser.java @@ -152,6 +152,14 @@ public class ScaleUser { return Converters.fromKilogram(initialWeight, scaleUnit); } + public static String getPreferenceKey(int userId, String key) { + return String.format("user.%d.%s", userId, key); + } + + public String getPreferenceKey(String key) { + return getPreferenceKey(getId(), key); + } + @Override public String toString() { diff --git a/android_app/app/src/main/java/com/health/openscale/gui/MainActivity.java b/android_app/app/src/main/java/com/health/openscale/gui/MainActivity.java index 8f0b723b..119dce65 100644 --- a/android_app/app/src/main/java/com/health/openscale/gui/MainActivity.java +++ b/android_app/app/src/main/java/com/health/openscale/gui/MainActivity.java @@ -26,7 +26,6 @@ import android.content.pm.PackageManager; import android.content.res.Configuration; import android.net.Uri; import android.os.Bundle; -import android.os.Environment; import android.os.Handler; import android.os.Message; import android.preference.PreferenceManager; @@ -48,7 +47,6 @@ import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; -import android.widget.EditText; import android.widget.Toast; import com.health.openscale.BuildConfig; @@ -81,6 +79,7 @@ public class MainActivity extends AppCompatActivity private MenuItem bluetoothStatus; private static final int IMPORT_DATA_REQUEST = 100; + private static final int EXPORT_DATA_REQUEST = 101; private DrawerLayout drawerLayout; private Toolbar toolbar; @@ -400,9 +399,7 @@ public class MainActivity extends AppCompatActivity importCsvFile(); return true; case R.id.exportData: - if (PermissionHelper.requestWritePermission(this)) { - exportCsvFile(); - } + exportCsvFile(); return true; case R.id.shareData: shareCsvFile(); @@ -556,7 +553,7 @@ public class MainActivity extends AppCompatActivity else { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.addCategory(Intent.CATEGORY_OPENABLE); - intent.setType("text/*"); + intent.setType("*/*"); startActivityForResult( Intent.createChooser(intent, getResources().getString(R.string.label_import)), @@ -564,50 +561,95 @@ public class MainActivity extends AppCompatActivity } } - private void exportCsvFile() { - AlertDialog.Builder filenameDialog = new AlertDialog.Builder(this); + private String getExportFilename(ScaleUser selectedScaleUser) { + return String.format("openScale %s.csv", selectedScaleUser.getUserName()); + } - filenameDialog.setTitle(getResources().getString(R.string.info_set_filename) + " " - + Environment.getExternalStorageDirectory().getPath()); + private void startActionCreateDocumentForExportIntent() { + OpenScale openScale = OpenScale.getInstance(getApplicationContext()); + ScaleUser selectedScaleUser = openScale.getSelectedScaleUser(); + + Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType("text/csv"); + intent.putExtra(Intent.EXTRA_TITLE, getExportFilename(selectedScaleUser)); + + startActivityForResult(intent, EXPORT_DATA_REQUEST); + } + + private boolean doExportData(Uri uri) { + OpenScale openScale = OpenScale.getInstance(getApplicationContext()); + if (openScale.exportData(uri)) { + String filename = openScale.getFilenameFromUri(uri); + Toast.makeText(this, + getResources().getString(R.string.info_data_exported) + " " + filename, + Toast.LENGTH_SHORT).show(); + return true; + } + return false; + } + + private String getExportPreferenceKey(ScaleUser selectedScaleUser) { + return selectedScaleUser.getPreferenceKey("exportUri"); + } + + private void exportCsvFile() { + OpenScale openScale = OpenScale.getInstance(getApplicationContext()); + final ScaleUser selectedScaleUser = openScale.getSelectedScaleUser(); final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); - final ScaleUser selectedScaleUser = OpenScale.getInstance(getApplicationContext()).getSelectedScaleUser(); - String exportFilename = prefs.getString("exportFilename" + selectedScaleUser.getId(), - "openScale_data_" + selectedScaleUser.getUserName() + ".csv"); + Uri uri; + try { + String exportUri = prefs.getString(getExportPreferenceKey(selectedScaleUser), ""); + uri = Uri.parse(exportUri); + getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + } + catch (Exception ex) { + uri = null; + } - final EditText txtFilename = new EditText(this); - txtFilename.setText(exportFilename); + if (uri == null) { + startActionCreateDocumentForExportIntent(); + return; + } - filenameDialog.setView(txtFilename); + AlertDialog.Builder exportDialog = new AlertDialog.Builder(this); + exportDialog.setTitle(R.string.label_export); + exportDialog.setMessage(getResources().getString(R.string.label_export_overwrite, + openScale.getFilenameFromUri(uri))); - filenameDialog.setPositiveButton(getResources().getString(R.string.label_export), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - String fullPath = Environment.getExternalStorageDirectory().getPath() + "/" + txtFilename.getText().toString(); - - if (OpenScale.getInstance(getApplicationContext()).exportData(fullPath)) { - prefs.edit().putString("exportFilename" + selectedScaleUser.getId(), txtFilename.getText().toString()).commit(); - Toast.makeText(getApplicationContext(), getResources().getString( - R.string.info_data_exported) + " " + fullPath, Toast.LENGTH_SHORT).show(); + final Uri exportUri = uri; + exportDialog.setPositiveButton(R.string.label_yes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (!doExportData(exportUri)) { + prefs.edit().remove(getExportPreferenceKey(selectedScaleUser)).apply(); } } }); - - filenameDialog.setNegativeButton(getResources().getString(R.string.label_cancel), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { + exportDialog.setNegativeButton(R.string.label_no, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + startActionCreateDocumentForExportIntent(); + } + }); + exportDialog.setNeutralButton(R.string.label_cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); - filenameDialog.show(); + exportDialog.show(); } private void shareCsvFile() { final ScaleUser selectedScaleUser = OpenScale.getInstance(getApplicationContext()).getSelectedScaleUser(); File shareFile = new File(getApplicationContext().getCacheDir(), - String.format("openScale %s.csv", selectedScaleUser.getUserName())); - if (!OpenScale.getInstance(getApplicationContext()).exportData(shareFile.getPath())) { + getExportFilename(selectedScaleUser)); + if (!OpenScale.getInstance(getApplicationContext()).exportData(Uri.fromFile(shareFile))) { return; } @@ -629,8 +671,30 @@ public class MainActivity extends AppCompatActivity public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - if (requestCode == IMPORT_DATA_REQUEST && resultCode == RESULT_OK && data != null) { - OpenScale.getInstance(getApplicationContext()).importData(data.getData()); + if (resultCode != RESULT_OK || data == null) { + return; + } + + OpenScale openScale = OpenScale.getInstance(getApplicationContext()); + + switch (requestCode) { + case IMPORT_DATA_REQUEST: + openScale.importData(data.getData()); + break; + case EXPORT_DATA_REQUEST: + if (doExportData(data.getData())) { + try { + getContentResolver().takePersistableUriPermission( + data.getData(), Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + String key = getExportPreferenceKey(openScale.getSelectedScaleUser()); + PreferenceManager.getDefaultSharedPreferences(this).edit() + .putString(key, data.getData().toString()).apply(); + } + catch (Exception ex) { + // Ignore + } + } + break; } } @@ -646,13 +710,6 @@ public class MainActivity extends AppCompatActivity permissionGranted = false; } break; - case PermissionHelper.PERMISSIONS_REQUEST_ACCESS_WRITE_STORAGE: - if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - exportCsvFile(); - } else { - permissionGranted = false; - } - break; } if (!permissionGranted) { diff --git a/android_app/app/src/main/res/values-ca/strings.xml b/android_app/app/src/main/res/values-ca/strings.xml index 3713dcd6..1e50722f 100644 --- a/android_app/app/src/main/res/values-ca/strings.xml +++ b/android_app/app/src/main/res/values-ca/strings.xml @@ -78,7 +78,6 @@ Totes les entrades eliminades Dades exportades a Dades importades de - Establir nom d\'arxiu a Valor en cm Valor en Comentari opcional diff --git a/android_app/app/src/main/res/values-de/strings.xml b/android_app/app/src/main/res/values-de/strings.xml index c48e2b54..4e24dd87 100644 --- a/android_app/app/src/main/res/values-de/strings.xml +++ b/android_app/app/src/main/res/values-de/strings.xml @@ -18,7 +18,6 @@ ist nicht verfügbar Kein Benutzer vorhanden. Bitte erzeugen Sie ein neuen Benutzer unter Einstellungen. am - Setzte Dateiname auf Geburtstag Suche nach Waage beim Start Bluetooth diff --git a/android_app/app/src/main/res/values-es/strings.xml b/android_app/app/src/main/res/values-es/strings.xml index a71bb47e..71961e04 100644 --- a/android_app/app/src/main/res/values-es/strings.xml +++ b/android_app/app/src/main/res/values-es/strings.xml @@ -78,7 +78,6 @@ Todas las entradas borradas Datos exportados a Datos importados de - Establecer nombre de archivo a Introduzca valor en cm Introduzca valor en Introduzca un comentario opcional diff --git a/android_app/app/src/main/res/values-fr/strings.xml b/android_app/app/src/main/res/values-fr/strings.xml index be1449cc..4180d988 100644 --- a/android_app/app/src/main/res/values-fr/strings.xml +++ b/android_app/app/src/main/res/values-fr/strings.xml @@ -72,7 +72,6 @@ Toutes les entrées ont été supprimées de la base de données Données exportées vers Donnéees importées depuis - Définir le nom du fichier vers Entrez la valeur en cm Entrez la valeur en Ajouter un commentaire optionnel diff --git a/android_app/app/src/main/res/values-ja/strings.xml b/android_app/app/src/main/res/values-ja/strings.xml index 64fdc0e7..767d01ee 100644 --- a/android_app/app/src/main/res/values-ja/strings.xml +++ b/android_app/app/src/main/res/values-ja/strings.xml @@ -54,7 +54,6 @@ でした - ユーザーは存在しません!設定で新しいユーザを入れてください ユーザーの追加する - にファイル名を設定 メモの上にデータ点 表示されています 表示されていません diff --git a/android_app/app/src/main/res/values-nl/strings.xml b/android_app/app/src/main/res/values-nl/strings.xml index 66485982..ed3f06c0 100644 --- a/android_app/app/src/main/res/values-nl/strings.xml +++ b/android_app/app/src/main/res/values-nl/strings.xml @@ -80,7 +80,6 @@ Alle database vermeldingen verwijderd Data geexporteerd naar Data geinporteerd van - Zet bestandsnaam op Geef waarde op cm\'s in Geef waaarde op Voeg een optionele opmerking toe. diff --git a/android_app/app/src/main/res/values-pl/strings.xml b/android_app/app/src/main/res/values-pl/strings.xml index c0ecdc96..0ded86a5 100644 --- a/android_app/app/src/main/res/values-pl/strings.xml +++ b/android_app/app/src/main/res/values-pl/strings.xml @@ -75,7 +75,6 @@ Wszytkie wpisy w bazie danych usunięte Dane wyeksportowane do Dane zaimportowane z - Ustaw nazwę pliku na Wprowadź wartość w cm Wprowadź wartość w Wprowadź opcjonlany komentarz diff --git a/android_app/app/src/main/res/values-pt/strings.xml b/android_app/app/src/main/res/values-pt/strings.xml index f7a34d45..152e4cf1 100644 --- a/android_app/app/src/main/res/values-pt/strings.xml +++ b/android_app/app/src/main/res/values-pt/strings.xml @@ -44,7 +44,6 @@ Valor não pode ser processado em Nenhum usuário existe. Por favor, crie um novo usuário em Configurações. - Definir nome de arquivo para Por favor suba na balança para medidas de referência Adicionar usuário Backup diff --git a/android_app/app/src/main/res/values-sk/strings.xml b/android_app/app/src/main/res/values-sk/strings.xml index 33cbf0da..6d3ddb4b 100644 --- a/android_app/app/src/main/res/values-sk/strings.xml +++ b/android_app/app/src/main/res/values-sk/strings.xml @@ -1,6 +1,6 @@ - Prehľad + Prehľad Graf Tabuľka Štatistiky @@ -64,7 +64,6 @@ Všetkých položky boli vymazané z databázy Údaje boli exportované do Údaje boli importované z - Nastaviť názov súboru na Zadajte hodnotu v cm Zadajte hodnotu v palcoch Zadajte voliteľný komentár diff --git a/android_app/app/src/main/res/values-sv/strings.xml b/android_app/app/src/main/res/values-sv/strings.xml index 768de44e..d7aecd25 100644 --- a/android_app/app/src/main/res/values-sv/strings.xml +++ b/android_app/app/src/main/res/values-sv/strings.xml @@ -80,7 +80,6 @@ Alla databasposter borttagna Data exporterad till Data importerad från - Sätt filnamn till Ange värde i cm Ange värde i Ange en frivillig kommentar @@ -187,5 +186,6 @@ Ställ in standardordning Veckovy + Skriv över föregående export \"%s\"? diff --git a/android_app/app/src/main/res/values-tr/strings.xml b/android_app/app/src/main/res/values-tr/strings.xml index 84fa4788..7e954e48 100644 --- a/android_app/app/src/main/res/values-tr/strings.xml +++ b/android_app/app/src/main/res/values-tr/strings.xml @@ -76,7 +76,6 @@ Veri tabaný giriþi silindi Veri dýþarý aktarma Veri içeri aktarma - Dosya adýný ayarla Deðeri cm olarak girin Ýçine deðer girin Ýsteðebaðlý açýklama girin diff --git a/android_app/app/src/main/res/values/strings.xml b/android_app/app/src/main/res/values/strings.xml index d45e0d5f..b3d5023e 100644 --- a/android_app/app/src/main/res/values/strings.xml +++ b/android_app/app/src/main/res/values/strings.xml @@ -88,7 +88,6 @@ All database entries deleted Data exported to Data imported from - Set filename to Enter value in cm Enter value in Enter an optional comment @@ -211,6 +210,7 @@ Measurement order Press and hold to reorder Set default order + Overwrite previous export \"%s\"?