aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java201
1 files changed, 136 insertions, 65 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java
index e0c94b947..b640ecb03 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java
@@ -23,15 +23,26 @@ import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.Point;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Messenger;
+import android.provider.DocumentsContract;
+import android.provider.OpenableColumns;
import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
import android.widget.Toast;
-import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
+import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment;
+
+import java.io.File;
+import java.text.DecimalFormat;
public class FileHelper {
@@ -55,25 +66,18 @@ public class FileHelper {
* Opens the preferred installed file manager on Android and shows a toast if no manager is
* installed.
*
- * @param activity
- * @param filename default selected file, not supported by all file managers
+ * @param fragment
+ * @param last default selected Uri, not supported by all file managers
* @param mimeType can be text/plain for example
* @param requestCode requestCode used to identify the result coming back from file manager to
* onActivityResult() in your activity
*/
- public static void openFile(Activity activity, String filename, String mimeType, int requestCode) {
- Intent intent = buildFileIntent(filename, mimeType);
-
- try {
- activity.startActivityForResult(intent, requestCode);
- } catch (ActivityNotFoundException e) {
- // No compatible file manager was found.
- Toast.makeText(activity, R.string.no_filemanager_installed, Toast.LENGTH_SHORT).show();
- }
- }
+ public static void openFile(Fragment fragment, Uri last, String mimeType, int requestCode) {
+ Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
- public static void openFile(Fragment fragment, String filename, String mimeType, int requestCode) {
- Intent intent = buildFileIntent(filename, mimeType);
+ intent.setData(last);
+ intent.setType(mimeType);
try {
fragment.startActivityForResult(intent, requestCode);
@@ -84,86 +88,153 @@ public class FileHelper {
}
}
+ public static void saveFile(final FileDialogCallback callback, final FragmentManager fragmentManager,
+ final String title, final String message, final File defaultFile,
+ final String checkMsg) {
+ // Message is received after file is selected
+ Handler returnHandler = new Handler() {
+ @Override
+ public void handleMessage(Message message) {
+ if (message.what == FileDialogFragment.MESSAGE_OKAY) {
+ callback.onFileSelected(
+ new File(message.getData().getString(FileDialogFragment.MESSAGE_DATA_FILE)),
+ message.getData().getBoolean(FileDialogFragment.MESSAGE_DATA_CHECKED));
+ }
+ }
+ };
+
+ // Create a new Messenger for the communication back
+ final Messenger messenger = new Messenger(returnHandler);
+
+ DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() {
+ @Override
+ public void run() {
+ FileDialogFragment fileDialog = FileDialogFragment.newInstance(messenger, title, message,
+ defaultFile, checkMsg);
+
+ fileDialog.show(fragmentManager, "fileDialog");
+ }
+ });
+ }
+
+ public static void saveFile(Fragment fragment, String title, String message, File defaultFile, int requestCode) {
+ saveFile(fragment, title, message, defaultFile, requestCode, null);
+ }
+
+ public static void saveFile(final Fragment fragment, String title, String message, File defaultFile,
+ final int requestCode, String checkMsg) {
+ saveFile(new FileDialogCallback() {
+ @Override
+ public void onFileSelected(File file, boolean checked) {
+ Intent intent = new Intent();
+ intent.setData(Uri.fromFile(file));
+ fragment.onActivityResult(requestCode, Activity.RESULT_OK, intent);
+ }
+ }, fragment.getActivity().getSupportFragmentManager(), title, message, defaultFile, checkMsg);
+ }
+
+ @TargetApi(Build.VERSION_CODES.KITKAT)
+ public static void openDocument(Fragment fragment, String mimeType, int requestCode) {
+ openDocument(fragment, mimeType, false, requestCode);
+ }
/**
* Opens the storage browser on Android 4.4 or later for opening a file
+ *
* @param fragment
- * @param last default selected file
- * @param mimeType can be text/plain for example
+ * @param mimeType can be text/plain for example
+ * @param multiple allow file chooser to return multiple files
* @param requestCode used to identify the result coming back from storage browser onActivityResult() in your
*/
@TargetApi(Build.VERSION_CODES.KITKAT)
- public static void openDocument(Fragment fragment, Uri last, String mimeType, int requestCode) {
+ public static void openDocument(Fragment fragment, String mimeType, boolean multiple, int requestCode) {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
- intent.setData(last);
intent.setType(mimeType);
+ intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, multiple);
+
fragment.startActivityForResult(intent, requestCode);
}
/**
* Opens the storage browser on Android 4.4 or later for saving a file
+ *
* @param fragment
- * @param last default selected file
- * @param mimeType can be text/plain for example
- * @param requestCode used to identify the result coming back from storage browser onActivityResult() in your
+ * @param mimeType can be text/plain for example
+ * @param suggestedName a filename desirable for the file to be saved
+ * @param requestCode used to identify the result coming back from storage browser onActivityResult() in your
*/
@TargetApi(Build.VERSION_CODES.KITKAT)
- public static void saveDocument(Fragment fragment, Uri last, String mimeType, int requestCode) {
+ public static void saveDocument(Fragment fragment, String mimeType, String suggestedName, int requestCode) {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
- intent.setData(last);
intent.setType(mimeType);
+ intent.putExtra("android.content.extra.SHOW_ADVANCED", true); // Note: This is not documented, but works
+ intent.putExtra(Intent.EXTRA_TITLE, suggestedName);
fragment.startActivityForResult(intent, requestCode);
}
- private static Intent buildFileIntent(String filename, String mimeType) {
- Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
- intent.addCategory(Intent.CATEGORY_OPENABLE);
+ public static String getFilename(Context context, Uri uri) {
+ String filename = null;
+ try {
+ Cursor cursor = context.getContentResolver().query(uri, new String[]{OpenableColumns.DISPLAY_NAME}, null, null, null);
- intent.setData(Uri.parse("file://" + filename));
- intent.setType(mimeType);
+ if (cursor != null) {
+ if (cursor.moveToNext()) {
+ filename = cursor.getString(0);
+ }
+ cursor.close();
+ }
+ } catch (Exception ignored) {
+ // This happens in rare cases (eg: document deleted since selection) and should not cause a failure
+ }
+ if (filename == null) {
+ String[] split = uri.toString().split("/");
+ filename = split[split.length - 1];
+ }
+ return filename;
+ }
- return intent;
+ public static long getFileSize(Context context, Uri uri) {
+ return getFileSize(context, uri, -1);
}
- /**
- * Get a file path from a Uri.
- * <p/>
- * from https://github.com/iPaulPro/aFileChooser/blob/master/aFileChooser/src/com/ipaulpro/
- * afilechooser/utils/FileUtils.java
- *
- * @param context
- * @param uri
- * @return
- * @author paulburke
- */
- public static String getPath(Context context, Uri uri) {
- Log.d(Constants.TAG + " File -",
- "Authority: " + uri.getAuthority() + ", Fragment: " + uri.getFragment()
- + ", Port: " + uri.getPort() + ", Query: " + uri.getQuery() + ", Scheme: "
- + uri.getScheme() + ", Host: " + uri.getHost() + ", Segments: "
- + uri.getPathSegments().toString());
-
- if ("content".equalsIgnoreCase(uri.getScheme())) {
- String[] projection = {"_data"};
- Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null);
- try {
- if (cursor != null && cursor.moveToFirst()) {
- int columnIndex = cursor.getColumnIndexOrThrow("_data");
- return cursor.getString(columnIndex);
- }
- } catch (Exception e) {
- // Eat it
- } finally {
- if (cursor != null) {
- cursor.close();
+ public static long getFileSize(Context context, Uri uri, long def) {
+ long size = def;
+ try {
+ Cursor cursor = context.getContentResolver().query(uri, new String[]{OpenableColumns.SIZE}, null, null, null);
+
+ if (cursor != null) {
+ if (cursor.moveToNext()) {
+ size = cursor.getLong(0);
}
+ cursor.close();
}
- } else if ("file".equalsIgnoreCase(uri.getScheme())) {
- return uri.getPath();
+ } catch (Exception ignored) {
+ // This happens in rare cases (eg: document deleted since selection) and should not cause a failure
+ }
+ return size;
+ }
+
+ /**
+ * Retrieve thumbnail of file, document api feature and thus KitKat only
+ */
+ public static Bitmap getThumbnail(Context context, Uri uri, Point size) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ return DocumentsContract.getDocumentThumbnail(context.getContentResolver(), uri, size, null);
+ } else {
+ return null;
}
+ }
+
+ public static String readableFileSize(long size) {
+ if (size <= 0) return "0";
+ final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"};
+ int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
+ return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
+ }
- return null;
+ public static interface FileDialogCallback {
+ public void onFileSelected(File file, boolean checked);
}
}