package de.blau.android.util; import java.io.File; import java.io.IOException; import java.util.ArrayList; import com.nononsenseapps.filepicker.FilePickerActivity; import android.content.ClipData; import android.content.Intent; import android.net.Uri; import android.os.Build; import android.os.Environment; import android.support.annotation.NonNull; import android.support.v4.app.FragmentActivity; import android.util.Log; import android.view.View; import de.blau.android.R; import de.blau.android.dialogs.GetFileName; import de.blau.android.prefs.Preferences; /** * Helper class that tries to provide some minimal file selector functionality for all supported Android versions * * @author simon * */ public class SelectFile { private static final String DEBUG_TAG = SelectFile.class.getName(); public static final int SAVE_FILE = 7113; public static final int READ_FILE = 9340; public static final int READ_FILE_OLD = 9341; private static SaveFile saveCallback; private final static Object saveCallbackLock = new Object(); private static ReadFile readCallback; private final static Object readCallbackLock = new Object(); private static FragmentActivity activity = null; /** * Save a file * * @param activity activity that called us * @param directoryPrefKey string resources for shared preferences for preferred (last) directory * @param callback callback that does the actual saving, should call {@link #savePref(Preferences, int, Uri)} */ public static void save(@NonNull FragmentActivity activity, int directoryPrefKey, @NonNull de.blau.android.util.SaveFile callback) { synchronized (saveCallbackLock) { saveCallback = callback; SelectFile.activity = activity; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { Intent i = new Intent(activity, ThemedFilePickerActivity.class); i.putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false); i.putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, true); i.putExtra(FilePickerActivity.EXTRA_ALLOW_EXISTING_FILE, true); i.putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_NEW_FILE); Preferences prefs = new Preferences(activity); String path = prefs.getString(directoryPrefKey); if (path != null) { i.putExtra(FilePickerActivity.EXTRA_START_PATH, path); } else { try { i.putExtra(FilePickerActivity.EXTRA_START_PATH, FileUtil.getPublicDirectory().getPath()); } catch (IOException e) { // if for whatever reason the above doesn't work we use the standard directory Log.d(DEBUG_TAG, "falling back to standard dir instead"); i.putExtra(FilePickerActivity.EXTRA_START_PATH, Environment.getExternalStorageDirectory().getPath()); } } activity.startActivityForResult(i, SAVE_FILE); } else { GetFileName.showDialog(activity, callback); } } /** * @param activity activity activity that called us * @param directoryPrefKey string resources for shared preferences for preferred (last) directory * @param readFile callback callback that does the actual saving, should call {@link #savePref(Preferences, int, Uri)} */ public static void read(@NonNull FragmentActivity activity, int directoryPrefKey, @NonNull ReadFile readFile) { synchronized (readCallbackLock) { readCallback = readFile; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { Intent i = new Intent(activity, ThemedFilePickerActivity.class); i.putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false); i.putExtra(FilePickerActivity.EXTRA_SINGLE_CLICK, true); i.putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_FILE); Preferences prefs = new Preferences(activity); String path = prefs.getString(directoryPrefKey); if (path != null) { i.putExtra(FilePickerActivity.EXTRA_START_PATH, path); } else { try { i.putExtra(FilePickerActivity.EXTRA_START_PATH, FileUtil.getPublicDirectory().getPath()); } catch (IOException e) { // if for whatever reason the above doesn't work we use the standard directory Log.d(DEBUG_TAG, "falling back to standard dir instead"); i.putExtra(FilePickerActivity.EXTRA_START_PATH, Environment.getExternalStorageDirectory().getPath()); } } activity.startActivityForResult(i, READ_FILE); } else { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("*/*"); intent.addCategory(Intent.CATEGORY_OPENABLE); try { activity.startActivityForResult(intent,READ_FILE_OLD); } catch (android.content.ActivityNotFoundException ex) { // Potentially direct the user to the Market with a Dialog Snack.barError(activity, R.string.toast_missing_filemanager); } } } /** * Handle the file selector result * * @param code returned request code * @param data the returned intent */ public static void handleResult(int code, Intent data) { // for now this doesn't do anything when multiple files are selected if (data.getBooleanExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false)) { // For JellyBean and above if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { ClipData clip = data.getClipData(); if (clip != null) { for (int i = 0; i < clip.getItemCount(); i++) { Uri uri = clip.getItemAt(i).getUri(); // Do something with the URI } } // For Ice Cream Sandwich } else { ArrayList<String> paths = data.getStringArrayListExtra (FilePickerActivity.EXTRA_PATHS); if (paths != null) { for (String path: paths) { Uri uri = Uri.parse(path); // Do something with the URI } } } } else { final Uri uri = data.getData(); if (code == SAVE_FILE) { File file = new File(uri.getPath()); if (file.exists()) { Snack.barWarning(activity, activity.getResources().getString(R.string.toast_file_exists, file.getName()), R.string.overwrite, new View.OnClickListener() { @Override public void onClick(View v) { synchronized (saveCallbackLock) { if (saveCallback != null) { saveCallback.save(uri); } } } }); } synchronized (saveCallbackLock) { if (saveCallback != null) { Log.d(DEBUG_TAG, "saving to " + uri); saveCallback.save(uri); } } } else if (code == READ_FILE) { synchronized (readCallbackLock) { if (readCallback != null) { Log.d(DEBUG_TAG, "reading " + uri); readCallback.read(uri); } } } else if (code == READ_FILE_OLD) { synchronized (readCallbackLock) { if (readCallback != null) { Log.d(DEBUG_TAG, "reading " + uri); readCallback.read(uri); } } } } } /** * Save the director path to shared preferences * * @param prefs the Preferences instance * @param directoryPrefKey the key * @param fileUri the file uri */ public static void savePref(Preferences prefs, int directoryPrefKey, Uri fileUri) { if (fileUri.getScheme().equals("file")) { int slash = fileUri.getPath().lastIndexOf("/"); if (slash >= 0) { String path = fileUri.getPath().substring(0, slash+1); prefs.putString(directoryPrefKey, path); } } } }