diff --git a/README.md b/README.md
index 5b6c4de..3f99ef6 100644
--- a/README.md
+++ b/README.md
@@ -73,6 +73,7 @@ The app uses:
- AutoSuggestTextViewAPICall (https://github.com/Truiton/AutoSuggestTextViewAPICall) which is licensed under Apache License Version 2.0
- Map data from OpenStreetMap, licensed under the Open Data Commons Open Database License (ODbL) by the OpenStreetMap Foundation (OSMF) (https://www.openstreetmap.org/copyright)
- Solar positioning library (https://github.com/klausbrunner/solarpositioning) which is licensed under MIT License
+- Zip4j (https://github.com/srikanth-lingala/zip4j) which is licensed under Apache License Version 2.0
## Contributing
If you find a bug, please open an issue in the Github repository, assuming one does not already exist.
diff --git a/app/build.gradle b/app/build.gradle
index 5a0a807..7f4c7f6 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -38,6 +38,7 @@ dependencies {
implementation 'com.android.volley:volley:1.2.1'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation 'androidx.cardview:cardview:1.0.0'
+ implementation 'net.lingala.zip4j:zip4j:2.9.1'
implementation "androidx.lifecycle:lifecycle-viewmodel:2.5.1" //needed due to duplicate class error
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1" //needed due to duplicate class error
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a1dac11..5425ae1 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -4,9 +4,12 @@
+
+
+
+
+
+
{
+ dialog.cancel();
+ ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
+ });
+ builder.setNegativeButton(R.string.dialog_NO_button, (dialog, whichButton) -> dialog.cancel());
+ AlertDialog dialog = builder.create();
+ dialog.show();
+ }
+
+ public static void zipExtract(Context context, File targetDir, Uri zipFile) {
+ ZipEntry zipEntry;
+ int readLen;
+ byte[] readBuffer = new byte[4096];
+ try {
+ InputStream src = context.getContentResolver().openInputStream(zipFile);
+ try {
+ try (ZipInputStream zipInputStream = new ZipInputStream(src)) {
+ while ((zipEntry = zipInputStream.getNextEntry()) != null) {
+ File extractedFile = new File(targetDir ,zipEntry.getName());
+ try (OutputStream outputStream = new FileOutputStream(extractedFile)) {
+ while ((readLen = zipInputStream.read(readBuffer)) != -1) {
+ outputStream.write(readBuffer, 0, readLen);
+ }
+ }
+ }
+ }
+ } catch (IOException ioException) {
+ ioException.printStackTrace();
+ }
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/app/src/main/java/org/woheller69/weather/activities/BackupRestoreActivity.java b/app/src/main/java/org/woheller69/weather/activities/BackupRestoreActivity.java
new file mode 100644
index 0000000..ebcfeaa
--- /dev/null
+++ b/app/src/main/java/org/woheller69/weather/activities/BackupRestoreActivity.java
@@ -0,0 +1,115 @@
+package org.woheller69.weather.activities;
+
+import static android.os.Environment.DIRECTORY_DOCUMENTS;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Environment;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.Toast;
+
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts;
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.app.AlertDialog;
+
+import net.lingala.zip4j.ZipFile;
+import net.lingala.zip4j.exception.ZipException;
+
+import org.woheller69.weather.Backup;
+import org.woheller69.weather.R;
+
+import java.io.File;
+import java.util.Objects;
+
+
+public class BackupRestoreActivity extends NavigationActivity{
+ ActivityResultLauncher mRestore;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_backuprestore);
+
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ }
+
+ mRestore = registerForActivityResult(
+ new ActivityResultContracts.StartActivityForResult(),
+ result -> {
+ File intData = new File(Environment.getDataDirectory() + "//databases//" + this.getPackageName());
+ if (result.getData()!=null && result.getData().getData()!=null) Backup.zipExtract(this, intData, result.getData().getData());
+ });
+ }
+
+ @Override
+ protected int getNavigationDrawerID() {
+ return R.id.nav_backuprestore;
+ }
+
+ public void performBackup(View view) {
+ File extStorage;
+ File intData;
+ intData = new File(Environment.getDataDirectory()+"//data//" + this.getPackageName() + "//databases//");
+ extStorage = Environment.getExternalStoragePublicDirectory(DIRECTORY_DOCUMENTS);
+ String filesBackup = getResources().getString(R.string.app_name)+".zip";
+ final File dbBackup = new File(extStorage, filesBackup);
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setMessage(getResources().getString(R.string.backup_database) +" -> " + dbBackup.toString());
+ builder.setPositiveButton(R.string.dialog_OK_button, (dialog, whichButton) -> {
+ if (!Backup.checkPermissionStorage(this)) {
+ Backup.requestPermission(this);
+ } else {
+ if (dbBackup.exists()){
+ if (!dbBackup.delete()){
+ Toast.makeText(this,getResources().getString(R.string.toast_delete), Toast.LENGTH_LONG).show();
+ }
+ }
+ try {
+ new ZipFile(dbBackup).addFolder(intData);
+ } catch (ZipException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ builder.setNegativeButton(R.string.dialog_NO_button, (dialog, whichButton) -> dialog.cancel());
+ AlertDialog dialog = builder.create();
+ dialog.show();
+ Objects.requireNonNull(dialog.getWindow()).setGravity(Gravity.BOTTOM);
+
+ }
+
+ public void performRestore(View view) {
+ File extStorage;
+ File intData;
+ intData = new File(Environment.getDataDirectory() + "//data//" + this.getPackageName());
+ extStorage = Environment.getExternalStoragePublicDirectory(DIRECTORY_DOCUMENTS);
+ String filesBackup = getResources().getString(R.string.app_name)+".zip";
+ final File zipFileBackup = new File(extStorage, filesBackup);
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setMessage(getResources().getString(R.string.restore_database));
+ builder.setPositiveButton(R.string.dialog_OK_button, (dialog, whichButton) -> {
+ if (!Backup.checkPermissionStorage(this)) {
+ Backup.requestPermission(this);
+ } else {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+ intent.setType("application/zip");
+ mRestore.launch(intent);
+ } else {
+ Backup.zipExtract(this, intData, Uri.fromFile(zipFileBackup));
+ }
+ }
+ });
+ builder.setNegativeButton(R.string.dialog_NO_button, (dialog, whichButton) -> dialog.cancel());
+ AlertDialog dialog = builder.create();
+ dialog.show();
+ Objects.requireNonNull(dialog.getWindow()).setGravity(Gravity.BOTTOM);
+ }
+}
diff --git a/app/src/main/java/org/woheller69/weather/activities/NavigationActivity.java b/app/src/main/java/org/woheller69/weather/activities/NavigationActivity.java
index 7efa3e1..d9a159e 100644
--- a/app/src/main/java/org/woheller69/weather/activities/NavigationActivity.java
+++ b/app/src/main/java/org/woheller69/weather/activities/NavigationActivity.java
@@ -169,6 +169,9 @@ public class NavigationActivity extends AppCompatActivity implements OnNavigatio
}else if(itemId==R.id.nav_help) {
intent = new Intent(this, HelpActivity.class);
startActivity(intent);
+ }else if(itemId==R.id.nav_backuprestore) {
+ intent = new Intent(this, BackupRestoreActivity.class);
+ startActivity(intent);
}else if (itemId==R.id.star_on_github){
startActivity(new Intent(Intent.ACTION_VIEW,
Uri.parse(BuildConfig.GITHUB_URL)));
diff --git a/app/src/main/res/drawable/ic_settings_backup_restore_24px.xml b/app/src/main/res/drawable/ic_settings_backup_restore_24px.xml
new file mode 100644
index 0000000..edc6466
--- /dev/null
+++ b/app/src/main/res/drawable/ic_settings_backup_restore_24px.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_warning_amber_black_24dp.xml b/app/src/main/res/drawable/ic_warning_amber_black_24dp.xml
new file mode 100644
index 0000000..dfc11fb
--- /dev/null
+++ b/app/src/main/res/drawable/ic_warning_amber_black_24dp.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_backuprestore.xml b/app/src/main/res/layout/activity_backuprestore.xml
new file mode 100644
index 0000000..c0122dc
--- /dev/null
+++ b/app/src/main/res/layout/activity_backuprestore.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/menu/activity_main_drawer.xml b/app/src/main/res/menu/activity_main_drawer.xml
index 4dd2e71..81cee38 100644
--- a/app/src/main/res/menu/activity_main_drawer.xml
+++ b/app/src/main/res/menu/activity_main_drawer.xml
@@ -25,6 +25,10 @@
android:id="@+id/nav_help"
android:icon="@drawable/ic_help_24px"
android:title="@string/activity_help" />
+
- Über
Privatsphäre-Informationen
Mehr Informationen können gefunden werden auf:
- Diese App ist abgeleitet von Privacy Friendly Weather, entwickelt von der Forschungsgruppe SECUSO. Quelltext lizenziert unter GPLv3. Die App benutzt Icons von Google Material Design Icons, lizenziert unter Apache License Version 2.0, die Leaflet Bibliothek, lizenziert unter 2-clause BSD License, AutoSuggestTextViewAPICall, lizenziert unter der Apache License Version 2.0, Solarpositioning (net.e175.klaus:solarpositioning), lizenziert unter MIT Lizenz und die WilliamChart Bibliothek (com.db.chart), lizenziert unter der Apache License Version 2.0
+ Diese App ist abgeleitet von Privacy Friendly Weather, entwickelt von der Forschungsgruppe SECUSO. Quelltext lizenziert unter GPLv3. Die App benutzt Icons von Google Material Design Icons, lizenziert unter Apache License Version 2.0, die Leaflet Bibliothek, lizenziert unter 2-clause BSD License, AutoSuggestTextViewAPICall, lizenziert unter der Apache License Version 2.0, Solarpositioning (net.e175.klaus:solarpositioning), lizenziert unter MIT Lizenz, Zip4j, lizenziert unter Apache License Version 2.0 und die WilliamChart Bibliothek (com.db.chart), lizenziert unter der Apache License Version 2.0
Lizenz
solXpect benötigt nur Zugang zum Internet. Es werden weder persönliche Daten gesammelt, noch wird Werbung angezeigt.
Woher kommen die Wetterinformationen?
@@ -95,5 +95,12 @@
Sonnenposition
Elevation [°]
Temperaturkoeffizient [%/K]
+ Sichern/Wiederherstellen
+ Datenbank sichern
+ Datenbank wiederherstellen
+ Berechtigung erforderlich
+ %s benötigt Zugriff auf den externen Speicher. Bitte die Berechtigung erteilen und erneut versuchen.
+ Bitte die Datei zuerst löschen und erneut versuchen.
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 80c5f3f..817a72b 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -20,7 +20,7 @@
About
Version
License
- This application is derived from Privacy Friendly Weather, developed by the research group SECUSO. Sourcecode licensed under GPLv3. The app uses icons from Google Material Design Icons licensed under Apache License Version 2.0, the Leaflet library which is licensed under 2-clause BSD License, AutoSuggestTextViewAPICall which is licensed under Apache License Version 2.0, Solarpositioning (net.e175.klaus:solarpositioning) which is licensed under MIT License, and WilliamChart library (com.db.chart) which is licensed under Apache License Version 2.0
+ This application is derived from Privacy Friendly Weather, developed by the research group SECUSO. Sourcecode licensed under GPLv3. The app uses icons from Google Material Design Icons licensed under Apache License Version 2.0, the Leaflet library which is licensed under 2-clause BSD License, AutoSuggestTextViewAPICall which is licensed under Apache License Version 2.0, Solarpositioning (net.e175.klaus:solarpositioning) which is licensed under MIT License, Zip4j (https://github.com/srikanth-lingala/zip4j) which is licensed under Apache License Version 2.0, and WilliamChart library (com.db.chart) which is licensed under Apache License Version 2.0
More information can be found on:
Github-Repo
Open-Meteo \n(Attribution 4.0 International CC BY 4.0)
@@ -98,4 +98,10 @@
Sun position
Elevation [°]
Temperature coefficient [%/K]
+ Backup/Restore
+ Backup database
+ Restore database
+ Permission required
+ %s needs access to external storage. Please accept permission and try again.
+ Please delete file and try again