diff --git a/library/src/main/java/com/nononsenseapps/filepicker/AbstractFilePickerFragment.java b/library/src/main/java/com/nononsenseapps/filepicker/AbstractFilePickerFragment.java
index a573b5d0..2e954bdd 100644
--- a/library/src/main/java/com/nononsenseapps/filepicker/AbstractFilePickerFragment.java
+++ b/library/src/main/java/com/nononsenseapps/filepicker/AbstractFilePickerFragment.java
@@ -319,14 +319,13 @@ public void onActivityCreated(Bundle savedInstanceState) {
}
}
}
-
- // If still null
- if (mCurrentPath == null) {
- mCurrentPath = getRoot();
- }
}
- refresh();
+ // If still null
+ if (mCurrentPath == null) {
+ mCurrentPath = getRoot();
+ }
+ refresh(mCurrentPath);
}
@Override
@@ -372,14 +371,17 @@ public void onDetach() {
* if permissions are granted and requests them if necessary. See hasPermission()
* and handlePermission(). By default, these methods do nothing. Override them if
* you need to request permissions at runtime.
+ *
+ * @param nextPath path to list files for
*/
- protected void refresh() {
- if (hasPermission()) {
+ protected void refresh(@NonNull T nextPath) {
+ if (hasPermission(nextPath)) {
+ mCurrentPath = nextPath;
isLoading = true;
getLoaderManager()
.restartLoader(0, null, AbstractFilePickerFragment.this);
} else {
- handlePermission();
+ handlePermission(nextPath);
}
}
@@ -387,8 +389,10 @@ protected void refresh() {
* If permission has not been granted yet, this method should request it.
*
* Override only if you need to request a permission.
+ *
+ * @param path The path for which permission should be requested
*/
- protected void handlePermission() {
+ protected void handlePermission(@NonNull T path) {
// Nothing to do by default
}
@@ -396,9 +400,10 @@ protected void handlePermission() {
* If your implementation needs to request a specific permission to function, check if it
* has been granted here. You should probably also override handlePermission() to request it.
*
+ * @param path the path for which permissions should be checked
* @return true if permission has been granted, false otherwise.
*/
- protected boolean hasPermission() {
+ protected boolean hasPermission(@NonNull T path) {
// Nothing to request by default
return true;
}
@@ -573,10 +578,9 @@ public void onClickDir(@NonNull View view, @NonNull DirViewHolder viewHolder) {
*/
public void goToDir(@NonNull T file) {
if (!isLoading) {
- mCurrentPath = file;
mCheckedItems.clear();
mCheckedVisibleViewHolders.clear();
- refresh();
+ refresh(file);
}
}
diff --git a/library/src/main/java/com/nononsenseapps/filepicker/FilePickerFragment.java b/library/src/main/java/com/nononsenseapps/filepicker/FilePickerFragment.java
index 66c0bc8e..539a22d8 100644
--- a/library/src/main/java/com/nononsenseapps/filepicker/FilePickerFragment.java
+++ b/library/src/main/java/com/nononsenseapps/filepicker/FilePickerFragment.java
@@ -28,6 +28,7 @@ public class FilePickerFragment extends AbstractFilePickerFragment {
protected static final int PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 1;
protected boolean showHiddenItems = false;
+ private File mRequestedPath = null;
public FilePickerFragment() {
}
@@ -55,7 +56,7 @@ public boolean areHiddenItemsShown(){
* @return true if app has been granted permission to write to the SD-card.
*/
@Override
- protected boolean hasPermission() {
+ protected boolean hasPermission(@NonNull File path) {
return PackageManager.PERMISSION_GRANTED ==
ContextCompat.checkSelfPermission(getContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE);
@@ -65,13 +66,14 @@ protected boolean hasPermission() {
* Request permission to write to the SD-card.
*/
@Override
- protected void handlePermission() {
+ protected void handlePermission(@NonNull File path) {
// Should we show an explanation?
// if (shouldShowRequestPermissionRationale(
// Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// Explain to the user why we need permission
// }
+ mRequestedPath = path;
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
}
@@ -97,7 +99,9 @@ public void onRequestPermissionsResult(int requestCode,
} else { // if (requestCode == PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE) {
if (PackageManager.PERMISSION_GRANTED == grantResults[0]) {
// Do refresh
- refresh();
+ if (mRequestedPath != null) {
+ refresh(mRequestedPath);
+ }
} else {
Toast.makeText(getContext(), R.string.nnf_permission_external_write_denied,
Toast.LENGTH_SHORT).show();
@@ -303,8 +307,7 @@ public void onNewFolder(@NonNull final String name) {
File folder = new File(mCurrentPath, name);
if (folder.mkdir()) {
- mCurrentPath = folder;
- refresh();
+ refresh(folder);
} else {
Toast.makeText(getActivity(), R.string.nnf_create_folder_error,
Toast.LENGTH_SHORT).show();
@@ -322,7 +325,7 @@ public void onNewFolder(@NonNull final String name) {
* @return True if item should be added to the list, false otherwise
*/
protected boolean isItemVisible(final File file) {
- if(!showHiddenItems && file.isHidden()){
+ if (!showHiddenItems && file.isHidden()) {
return false;
}
return (isDir(file) || (mode == MODE_FILE || mode == MODE_FILE_AND_DIR));
diff --git a/sample/build.gradle b/sample/build.gradle
index a3b3760f..eacc3616 100644
--- a/sample/build.gradle
+++ b/sample/build.gradle
@@ -47,4 +47,7 @@ dependencies {
// FTP browser sample
compile 'commons-net:commons-net:3.3'
+
+ // Root example
+ compile 'eu.chainfire:libsuperuser:1.0.0.+'
}
diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml
index 4e1e97c4..c80c3bb9 100644
--- a/sample/src/main/AndroidManifest.xml
+++ b/sample/src/main/AndroidManifest.xml
@@ -62,6 +62,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{
private final DropboxAPI dbApi;
- private FolderCreator folderCreator;
private ProgressBar progressBar;
private RecyclerView recyclerView;
@@ -114,10 +113,12 @@ public void onClick(final View v) {
/**
* If we are loading, then hide the list and show the progress bar instead.
+ *
+ * @param nextPath path to list files for
*/
@Override
- protected void refresh() {
- super.refresh();
+ protected void refresh(DropboxAPI.Entry nextPath) {
+ super.refresh(nextPath);
if (isLoading) {
progressBar.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.INVISIBLE);
diff --git a/sample/src/main/java/com/nononsenseapps/filepicker/sample/ftp/FtpPickerFragment.java b/sample/src/main/java/com/nononsenseapps/filepicker/sample/ftp/FtpPickerFragment.java
index b2e64a6f..c87d860e 100644
--- a/sample/src/main/java/com/nononsenseapps/filepicker/sample/ftp/FtpPickerFragment.java
+++ b/sample/src/main/java/com/nononsenseapps/filepicker/sample/ftp/FtpPickerFragment.java
@@ -320,8 +320,7 @@ protected FtpFile doInBackground(String... names) {
@Override
protected void onPostExecute(FtpFile folder) {
if (folder != null) {
- mCurrentPath = folder;
- refresh();
+ refresh(folder);
} else {
Toast.makeText(getContext(), R.string.nnf_create_folder_error, Toast.LENGTH_SHORT).show();
}
diff --git a/sample/src/main/java/com/nononsenseapps/filepicker/sample/root/SUErrorFragment.java b/sample/src/main/java/com/nononsenseapps/filepicker/sample/root/SUErrorFragment.java
new file mode 100644
index 00000000..207a688d
--- /dev/null
+++ b/sample/src/main/java/com/nononsenseapps/filepicker/sample/root/SUErrorFragment.java
@@ -0,0 +1,36 @@
+package com.nononsenseapps.filepicker.sample.root;
+
+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.v4.app.FragmentManager;
+import android.support.v7.app.AlertDialog;
+
+/**
+ * A dialog which tells the user that no SU binary is available
+ */
+public class SUErrorFragment extends DialogFragment {
+
+ private static final String TAG = "SUErrorFragment";
+
+ public static void showDialog(@NonNull final FragmentManager fm) {
+ SUErrorFragment d = new SUErrorFragment();
+ d.show(fm, TAG);
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setMessage("No read permisson, root unavailable")
+ .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ }
+ });
+ return builder.create();
+ }
+}
diff --git a/sample/src/main/java/com/nononsenseapps/filepicker/sample/root/SUPickerActivity.java b/sample/src/main/java/com/nononsenseapps/filepicker/sample/root/SUPickerActivity.java
new file mode 100644
index 00000000..74f85f53
--- /dev/null
+++ b/sample/src/main/java/com/nononsenseapps/filepicker/sample/root/SUPickerActivity.java
@@ -0,0 +1,30 @@
+package com.nononsenseapps.filepicker.sample.root;
+
+import android.os.Environment;
+import android.support.annotation.Nullable;
+
+import com.nononsenseapps.filepicker.AbstractFilePickerActivity;
+import com.nononsenseapps.filepicker.AbstractFilePickerFragment;
+
+import java.io.File;
+
+public class SUPickerActivity extends AbstractFilePickerActivity {
+
+ public SUPickerActivity() {
+ super();
+ }
+
+ @Override
+ protected AbstractFilePickerFragment getFragment(@Nullable String startPath,
+ int mode,
+ boolean allowMultiple,
+ boolean allowCreateDir) {
+ AbstractFilePickerFragment fragment = new SUPickerFragment();
+ // startPath is allowed to be null. In that case, default folder should be SD-card and
+ // not "/"
+ fragment.setArgs(
+ startPath != null ? startPath : Environment.getExternalStorageDirectory().getPath(),
+ mode, allowMultiple, allowCreateDir);
+ return fragment;
+ }
+}
diff --git a/sample/src/main/java/com/nononsenseapps/filepicker/sample/root/SUPickerActivity2.java b/sample/src/main/java/com/nononsenseapps/filepicker/sample/root/SUPickerActivity2.java
new file mode 100644
index 00000000..a3499518
--- /dev/null
+++ b/sample/src/main/java/com/nononsenseapps/filepicker/sample/root/SUPickerActivity2.java
@@ -0,0 +1,7 @@
+package com.nononsenseapps.filepicker.sample.root;
+
+/**
+ * Just for second theme
+ */
+public class SUPickerActivity2 extends SUPickerActivity {
+}
diff --git a/sample/src/main/java/com/nononsenseapps/filepicker/sample/root/SUPickerFragment.java b/sample/src/main/java/com/nononsenseapps/filepicker/sample/root/SUPickerFragment.java
new file mode 100644
index 00000000..2e4049df
--- /dev/null
+++ b/sample/src/main/java/com/nononsenseapps/filepicker/sample/root/SUPickerFragment.java
@@ -0,0 +1,71 @@
+package com.nononsenseapps.filepicker.sample.root;
+
+import android.support.annotation.NonNull;
+import android.util.Log;
+
+import com.nononsenseapps.filepicker.FilePickerFragment;
+
+import java.io.File;
+import java.util.List;
+
+import eu.chainfire.libsuperuser.Shell;
+
+/**
+ * An example picker which calls out to LibSU to get Root-permissions to view otherwise hidden files.
+ */
+public class SUPickerFragment extends FilePickerFragment {
+
+ @Override
+ protected boolean hasPermission(@NonNull File path) {
+ // Return the combination of normal file permissions and SU permissions
+ return super.hasPermission(path) & (!needSUPermission(path) | hasSUPermission());
+ }
+
+ @Override
+ protected void handlePermission(@NonNull File path) {
+ // Only call super if we don't have normal file permissions
+ if (!super.hasPermission(path)) {
+ super.handlePermission(path);
+ }
+ // Only if we need SU permissions
+ if (needSUPermission(path) && !hasSUPermission()) {
+ handleSUPermission();
+ }
+ }
+
+ private boolean haveReadPermission(@NonNull File file) {
+ List result =
+ Shell.SH.run("test -r " + file.getAbsolutePath() + " && echo \"rootsuccess\"");
+ return result != null && !result.isEmpty() && "rootsuccess".equals(result.get(0));
+ }
+
+ private boolean needSUPermission(@NonNull File path) {
+ return !haveReadPermission(path);
+ }
+
+ private boolean isSUAvailable() {
+ return Shell.SU.available();
+ }
+
+ private boolean hasSUPermission() {
+ if (isSUAvailable()) {
+ List result = Shell.SU.run("ls -l /");
+ if (result != null && !result.isEmpty()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void handleSUPermission() {
+ if (isSUAvailable()) {
+ // request
+ String suVersion = Shell.SU.version(false);
+ String suVersionInternal = Shell.SU.version(true);
+ Log.d("libsuperuser: ", "suVersion:"+suVersion+" suVersionInternal:"+suVersionInternal);
+ } else {
+ // Notify that no root access available
+ SUErrorFragment.showDialog(getFragmentManager());
+ }
+ }
+}
diff --git a/sample/src/main/res/layout/activity_no_nonsense_file_picker.xml b/sample/src/main/res/layout/activity_no_nonsense_file_picker.xml
index 6f11c9f7..97e978b4 100644
--- a/sample/src/main/res/layout/activity_no_nonsense_file_picker.xml
+++ b/sample/src/main/res/layout/activity_no_nonsense_file_picker.xml
@@ -145,6 +145,17 @@
android:gravity="center"
android:text="Pick Dropbox" />
+
+