[tor-commits] [orbot/master] restore backup dialog

n8fr8 at torproject.org n8fr8 at torproject.org
Thu Mar 2 04:10:21 UTC 2017


commit 872ec4021444a536b484ffc78ee2d8d5a19b0588
Author: arrase <arrase at gmail.com>
Date:   Thu Nov 24 02:22:41 2016 +0100

    restore backup dialog
---
 .../org/torproject/android/backup/BackupUtils.java | 33 ++++++---
 .../android/storage/ExternalStorage.java           | 30 +++-----
 .../android/storage/PermissionManager.java         | 50 +++++++++++++
 .../android/ui/hs/HiddenServicesActivity.java      | 11 ++-
 .../android/ui/hs/adapters/BackupAdapter.java      | 50 +++++++++++++
 .../android/ui/hs/dialogs/HSActionsDialog.java     | 38 ++--------
 .../android/ui/hs/dialogs/SelectBackupDialog.java  | 81 ++++++++++++++++++++++
 app/src/main/res/layout/layout_hs_backups_list.xml | 10 +++
 .../res/layout/layout_hs_backups_list_item.xml     | 24 +++++++
 app/src/main/res/values/strings.xml                |  4 +-
 10 files changed, 269 insertions(+), 62 deletions(-)

diff --git a/app/src/main/java/org/torproject/android/backup/BackupUtils.java b/app/src/main/java/org/torproject/android/backup/BackupUtils.java
index e05532f..57d8c8d 100644
--- a/app/src/main/java/org/torproject/android/backup/BackupUtils.java
+++ b/app/src/main/java/org/torproject/android/backup/BackupUtils.java
@@ -2,17 +2,22 @@ package org.torproject.android.backup;
 
 import android.app.Application;
 import android.content.Context;
+import android.widget.Toast;
 
+import org.torproject.android.service.R;
 import org.torproject.android.service.TorServiceConstants;
 import org.torproject.android.storage.ExternalStorage;
 
 import java.io.File;
+import java.io.IOException;
 
 public class BackupUtils {
     private File mHSBasePath;
+    private Context mContext;
 
     public BackupUtils(Context context) {
-        mHSBasePath = context.getDir(
+        mContext = context;
+        mHSBasePath = mContext.getDir(
                 TorServiceConstants.DIRECTORY_TOR_DATA,
                 Application.MODE_PRIVATE
         );
@@ -20,13 +25,12 @@ public class BackupUtils {
 
     public String createZipBackup(Integer port) {
 
-        ExternalStorage storage = new ExternalStorage();
-        String storage_path = storage.createBackupDir();
-        if (storage_path == null) {
+        File storage_path = ExternalStorage.getOrCreateBackupDir();
+
+        if (storage_path == null)
             return null;
-        }
 
-        String zip_path = storage_path + "/hs" + port + ".zip";
+        String zip_path = storage_path.getAbsolutePath() + "/hs" + port + ".zip";
         String files[] = {
                 mHSBasePath + "/" + TorServiceConstants.HIDDEN_SERVICES_DIR + "/hs" + port + "/hostname",
                 mHSBasePath + "/" + TorServiceConstants.HIDDEN_SERVICES_DIR + "/hs" + port + "/private_key"
@@ -42,7 +46,20 @@ public class BackupUtils {
     }
 
     public void restoreZipBackup(Integer port, String path) {
-        ZipIt zip = new ZipIt(null, path);
-        zip.unzip(mHSBasePath + "/hs" + port);
+        String hsBasePath;
+
+        try {
+            hsBasePath = mHSBasePath.getCanonicalPath() + "/" + TorServiceConstants.HIDDEN_SERVICES_DIR;
+            File hsPath = new File(hsBasePath, "/hs" + port);
+            if (hsPath.mkdirs()) {
+                ZipIt zip = new ZipIt(null, path);
+                zip.unzip(hsPath.getCanonicalPath());
+                return;
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        Toast.makeText(mContext, R.string.error, Toast.LENGTH_LONG).show();
     }
 }
diff --git a/app/src/main/java/org/torproject/android/storage/ExternalStorage.java b/app/src/main/java/org/torproject/android/storage/ExternalStorage.java
index 6da650d..bea196e 100644
--- a/app/src/main/java/org/torproject/android/storage/ExternalStorage.java
+++ b/app/src/main/java/org/torproject/android/storage/ExternalStorage.java
@@ -5,38 +5,30 @@ import android.os.Environment;
 import java.io.File;
 
 public class ExternalStorage {
-    private final String BACKUPS_DIR = "Orbot-HiddenServices";
+    private static final String BACKUPS_DIR = "Orbot-HiddenServices";
 
-    public String createBackupDir() {
-        if (!isExternalStorageWritable()) {
+    public static File getOrCreateBackupDir() {
+        if (!isExternalStorageWritable())
             return null;
-        }
 
-        File path = Environment.getExternalStoragePublicDirectory(BACKUPS_DIR);
+        File dir = new File(Environment.getExternalStorageDirectory(), BACKUPS_DIR);
 
-        if (!path.mkdirs()) {
+        if (!dir.isDirectory() && !dir.mkdirs())
             return null;
-        }
 
-        return path.getAbsolutePath();
+        return dir;
     }
 
     /* Checks if external storage is available for read and write */
-    public boolean isExternalStorageWritable() {
+    public static boolean isExternalStorageWritable() {
         String state = Environment.getExternalStorageState();
-        if (Environment.MEDIA_MOUNTED.equals(state)) {
-            return true;
-        }
-        return false;
+        return Environment.MEDIA_MOUNTED.equals(state);
     }
 
     /* Checks if external storage is available to at least read */
-    public boolean isExternalStorageReadable() {
+    public static boolean isExternalStorageReadable() {
         String state = Environment.getExternalStorageState();
-        if (Environment.MEDIA_MOUNTED.equals(state) ||
-                Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
-            return true;
-        }
-        return false;
+        return Environment.MEDIA_MOUNTED.equals(state) ||
+                Environment.MEDIA_MOUNTED_READ_ONLY.equals(state);
     }
 }
diff --git a/app/src/main/java/org/torproject/android/storage/PermissionManager.java b/app/src/main/java/org/torproject/android/storage/PermissionManager.java
new file mode 100644
index 0000000..128db8e
--- /dev/null
+++ b/app/src/main/java/org/torproject/android/storage/PermissionManager.java
@@ -0,0 +1,50 @@
+package org.torproject.android.storage;
+
+
+import android.Manifest;
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.support.design.widget.Snackbar;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.app.FragmentActivity;
+import android.view.View;
+
+import org.torproject.android.R;
+
+public class PermissionManager {
+    private static final int PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 1;
+
+    public static boolean usesRuntimePermissions() {
+        return (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1);
+    }
+
+    @SuppressLint("NewApi")
+    public static boolean hasExternalWritePermission(Context context) {
+        return (context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
+    }
+
+    public static void requestPermissions(FragmentActivity activity) {
+        final FragmentActivity mActivity = activity;
+
+        if (ActivityCompat.shouldShowRequestPermissionRationale
+                (mActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
+            Snackbar.make(mActivity.findViewById(android.R.id.content),
+                    R.string.please_grant_permissions_for_external_storage,
+                    Snackbar.LENGTH_INDEFINITE).setAction("ENABLE",
+                    new View.OnClickListener() {
+                        @Override
+                        public void onClick(View v) {
+                            ActivityCompat.requestPermissions(mActivity,
+                                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
+                                    PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
+                        }
+                    }).show();
+        } else {
+            ActivityCompat.requestPermissions(mActivity,
+                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
+                    PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
+        }
+    }
+}
diff --git a/app/src/main/java/org/torproject/android/ui/hs/HiddenServicesActivity.java b/app/src/main/java/org/torproject/android/ui/hs/HiddenServicesActivity.java
index 52103dc..4474668 100644
--- a/app/src/main/java/org/torproject/android/ui/hs/HiddenServicesActivity.java
+++ b/app/src/main/java/org/torproject/android/ui/hs/HiddenServicesActivity.java
@@ -16,9 +16,11 @@ import android.widget.ListView;
 import android.widget.TextView;
 
 import org.torproject.android.R;
+import org.torproject.android.storage.PermissionManager;
 import org.torproject.android.ui.hs.adapters.OnionListAdapter;
 import org.torproject.android.ui.hs.dialogs.HSActionsDialog;
 import org.torproject.android.ui.hs.dialogs.HSDataDialog;
+import org.torproject.android.ui.hs.dialogs.SelectBackupDialog;
 import org.torproject.android.ui.hs.providers.HSContentProvider;
 
 public class HiddenServicesActivity extends AppCompatActivity {
@@ -98,7 +100,14 @@ public class HiddenServicesActivity extends AppCompatActivity {
         int id = item.getItemId();
 
         if (id == R.id.menu_restore_backup) {
-            // TODO: Restore backup
+            if (PermissionManager.usesRuntimePermissions()
+                    && !PermissionManager.hasExternalWritePermission(this)) {
+                PermissionManager.requestPermissions(this);
+                return true;
+            }
+
+            SelectBackupDialog dialog = new SelectBackupDialog();
+            dialog.show(getSupportFragmentManager(), "SelectBackupDialog");
             return true;
         }
 
diff --git a/app/src/main/java/org/torproject/android/ui/hs/adapters/BackupAdapter.java b/app/src/main/java/org/torproject/android/ui/hs/adapters/BackupAdapter.java
new file mode 100644
index 0000000..bcc7a5a
--- /dev/null
+++ b/app/src/main/java/org/torproject/android/ui/hs/adapters/BackupAdapter.java
@@ -0,0 +1,50 @@
+package org.torproject.android.ui.hs.adapters;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+
+import org.torproject.android.R;
+
+import java.io.File;
+import java.util.List;
+
+public class BackupAdapter extends ArrayAdapter<File> {
+    private int mResource;
+
+    public BackupAdapter(Context context, int resource) {
+        super(context, resource);
+        mResource = resource;
+    }
+
+    public BackupAdapter(Context context, int resource, List<File> zips) {
+        super(context, resource, zips);
+        mResource = resource;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+
+        View v = convertView;
+
+        if (v == null) {
+            LayoutInflater vi;
+            vi = LayoutInflater.from(getContext());
+            v = vi.inflate(mResource, null);
+        }
+
+        File p = getItem(position);
+
+        if (p != null) {
+            TextView name = (TextView) v.findViewById(R.id.backup_name);
+
+            if (name != null)
+                name.setText(p.getName());
+        }
+
+        return v;
+    }
+}
diff --git a/app/src/main/java/org/torproject/android/ui/hs/dialogs/HSActionsDialog.java b/app/src/main/java/org/torproject/android/ui/hs/dialogs/HSActionsDialog.java
index 4631543..d5603b7 100644
--- a/app/src/main/java/org/torproject/android/ui/hs/dialogs/HSActionsDialog.java
+++ b/app/src/main/java/org/torproject/android/ui/hs/dialogs/HSActionsDialog.java
@@ -23,6 +23,7 @@ import android.widget.Toast;
 
 import org.torproject.android.R;
 import org.torproject.android.backup.BackupUtils;
+import org.torproject.android.storage.PermissionManager;
 import org.torproject.android.ui.hs.providers.HSContentProvider;
 
 public class HSActionsDialog extends DialogFragment {
@@ -44,8 +45,9 @@ public class HSActionsDialog extends DialogFragment {
             public void onClick(View v) {
                 Context mContext = v.getContext();
 
-                if (usesRuntimePermissions() && !hasExternalWritePermission(mContext)) {
-                    requestPermissions();
+                if (PermissionManager.usesRuntimePermissions()
+                        && !PermissionManager.hasExternalWritePermission(mContext)) {
+                    PermissionManager.requestPermissions(getActivity());
                     return;
                 }
 
@@ -58,7 +60,7 @@ public class HSActionsDialog extends DialogFragment {
                     return;
                 }
 
-                Toast.makeText(mContext, R.string.done, Toast.LENGTH_LONG).show();
+                Toast.makeText(mContext, R.string.backup_saved_at_external_storage, Toast.LENGTH_LONG).show();
 
                 Uri selectedUri = Uri.parse(backupPath.substring(0, backupPath.lastIndexOf("/")));
                 Intent intent = new Intent(Intent.ACTION_VIEW);
@@ -104,34 +106,4 @@ public class HSActionsDialog extends DialogFragment {
 
         return actionDialog;
     }
-
-    private boolean usesRuntimePermissions() {
-        return (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1);
-    }
-
-    @SuppressLint("NewApi")
-    private boolean hasExternalWritePermission(Context context) {
-        return (context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
-    }
-
-    private void requestPermissions() {
-        if (ActivityCompat.shouldShowRequestPermissionRationale
-                (getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
-            Snackbar.make(getActivity().findViewById(android.R.id.content),
-                    R.string.please_grant_permissions_for_external_storage,
-                    Snackbar.LENGTH_INDEFINITE).setAction("ENABLE",
-                    new View.OnClickListener() {
-                        @Override
-                        public void onClick(View v) {
-                            ActivityCompat.requestPermissions(getActivity(),
-                                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
-                                    PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
-                        }
-                    }).show();
-        } else {
-            ActivityCompat.requestPermissions(getActivity(),
-                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
-                    PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
-        }
-    }
 }
diff --git a/app/src/main/java/org/torproject/android/ui/hs/dialogs/SelectBackupDialog.java b/app/src/main/java/org/torproject/android/ui/hs/dialogs/SelectBackupDialog.java
new file mode 100644
index 0000000..37c722b
--- /dev/null
+++ b/app/src/main/java/org/torproject/android/ui/hs/dialogs/SelectBackupDialog.java
@@ -0,0 +1,81 @@
+package org.torproject.android.ui.hs.dialogs;
+
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.DialogFragment;
+import android.support.v7.app.AlertDialog;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListView;
+
+import org.torproject.android.R;
+import org.torproject.android.storage.ExternalStorage;
+import org.torproject.android.ui.hs.adapters.BackupAdapter;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class SelectBackupDialog extends DialogFragment {
+
+    @NonNull
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        AlertDialog.Builder backupsDialog = new AlertDialog.Builder(getActivity());
+
+        backupsDialog.setTitle(R.string.restore_backup);
+
+        File backupDir = ExternalStorage.getOrCreateBackupDir();
+        File[] files = null;
+
+        try {
+            files = backupDir.listFiles(new FilenameFilter() {
+                @Override
+                public boolean accept(File dir, String name) {
+                    return name.toLowerCase().endsWith(".zip");
+                }
+            });
+        } catch (NullPointerException e) {
+            // Silent block
+        }
+
+        if (files == null || files.length < 1) {
+            backupsDialog.setMessage(R.string.create_a_backup_first);
+            backupsDialog.setNegativeButton(R.string.btn_cancel, new DialogInterface.OnClickListener() {
+                public void onClick(DialogInterface dialog, int id) {
+                    dialog.dismiss();
+                }
+            });
+
+            return backupsDialog.create();
+        }
+
+        final View dialog_view = getActivity().getLayoutInflater().inflate(R.layout.layout_hs_backups_list, null);
+
+        backupsDialog.setView(dialog_view);
+        backupsDialog.setPositiveButton(R.string.btn_okay, new DialogInterface.OnClickListener() {
+            public void onClick(DialogInterface dialog, int id) {
+                dialog.dismiss();
+            }
+        });
+
+        ListView backups = (ListView) dialog_view.findViewById(R.id.listview_hs_backups);
+
+        List<File> zips = new ArrayList<>();
+        Collections.addAll(zips, files);
+
+        backups.setAdapter(new BackupAdapter(getContext(), R.layout.layout_hs_backups_list_item, zips));
+        backups.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            @Override
+            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+                // TODO
+            }
+        });
+
+        return backupsDialog.create();
+    }
+}
diff --git a/app/src/main/res/layout/layout_hs_backups_list.xml b/app/src/main/res/layout/layout_hs_backups_list.xml
new file mode 100644
index 0000000..6c123ff
--- /dev/null
+++ b/app/src/main/res/layout/layout_hs_backups_list.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical" android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <ListView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:id="@+id/listview_hs_backups" />
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/layout_hs_backups_list_item.xml b/app/src/main/res/layout/layout_hs_backups_list_item.xml
new file mode 100644
index 0000000..fe76d47
--- /dev/null
+++ b/app/src/main/res/layout/layout_hs_backups_list_item.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/backup_list_item"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:paddingLeft="15dp"
+        tools:paddingLeft="15dp"
+        android:paddingRight="15dp"
+        tools:paddingRight="15dp">
+
+        <TextView
+            android:id="@+id/backup_name"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:textSize="35sp" />
+    </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index adeba6f..3e37d3d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -337,14 +337,16 @@
     <string name="local_port">Local Port</string>
     <string name="onion_port">Onion Port</string>
     <string name="name">Name</string>
+    <string name="done">Done!</string>
     <string name="invalid_port">Invalid Port</string>
     <string name="copy_address_to_clipboard">Copy address to clipboard</string>
     <string name="backup_service">Backup Service</string>
     <string name="delete_service">Delete Service</string>
-    <string name="done">Done!</string>
+    <string name="backup_saved_at_external_storage">Backup saved at external storage</string>
     <string name="filemanager_not_available">Filemanager not available</string>
     <string name="please_grant_permissions_for_external_storage">Please grant permissions for external storage</string>
     <string name="permission_granted">Permission granted</string>
     <string name="permission_denied">Permission denied</string>
     <string name="restore_backup">Restore Backup</string>
+    <string name="create_a_backup_first">Create a backup first</string>
 </resources>





More information about the tor-commits mailing list