[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [orbot/master] restore backup dialog
commit 872ec4021444a536b484ffc78ee2d8d5a19b0588
Author: arrase <arrase@xxxxxxxxx>
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>
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits