diff options
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.java | 201 |
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); } } |