Stack Overflow archive
1 scoreaccepted

RootTools.deleteFileOrDirectory always returns false

score
1
question views
355
license
CC BY-SA 3.0

RootTools isn't the greatest. Personally, I suggest going with libsuperuser.

There are plenty of reasons why your file isn't being deleting. If you look at RootTools, it doesn't add quotes around the path. So, if your file contains whitespace then it will not be deleted.

From RootTools:

java
Command command = new Command(0, false, "rm -r " + target);
Shell.startRootShell().add(command);
commandWait(Shell.startRootShell(), command);

It should be:

java
Command command = new Command(0, false, "rm -r \"" + target + "\"");
Shell.startRootShell().add(command);
commandWait(Shell.startRootShell(), command);

Edit:

The path returned by Environment.getExternalStorageDir() cannot be read in a shell. You will need to change the path before sending the command to the shell.

To fix this your can add the following static factory method to your project:

java
/**
 * The external storage path is not readable by shell or root. This replaces {@link
 * Environment#getExternalStorageDirectory()} with the environment variable "EXTERNAL_STORAGE".
 *
 * @param file
 *         The file to check.
 * @return The original file (if it does not start with {@link
 * Environment#getExternalStorageDirectory()}
 * or a file with the correct path.
 */
@SuppressLint("SdCardPath")
public static File getFileForShell(File file) {
    String externalStorage = Environment.getExternalStorageDirectory().getAbsolutePath();
    if (!file.getAbsolutePath().startsWith(externalStorage)) {
        return file;
    }
    String legacyStorage = System.getenv("EXTERNAL_STORAGE");
    String path;
    if (legacyStorage != null) {
        path = file.getAbsolutePath().replaceFirst(externalStorage, legacyStorage);
    } else {
        path = file.getAbsolutePath().replaceFirst(externalStorage, "/sdcard");
    }
    return new File(path);
}

Then, when you call RootTools.deleteFileOrDirectory(String target, boolean remountAsRw); change the file path:

java
String path = getFileForShell(file).getAbsolutePath();
RootTools.deleteFileOrDirectory(path, true);

You don't need root access to delete files on internal storage. You need the permission android.permission.WRITE_EXTERNAL_STORAGE declared in your manifest.


libsuperuser

To check if root access is available and show the root permission prompt, you could call the following method:

java
boolean isRooted = Shell.SU.available();

The library, libsuperuser, is not intended to do all the things RootTools attempts to do. If you choose to use libsuperuser you will need to send the commands to the shell.

An example of deleting a file with libsuperuser:

java
void delete(File file) {
    String command;
    if (file.isDirectory()) {
        command = "rm -r \"" + file.getAbsolutePath() + "\"";
    } else {
        command = "rm \"" + file.getAbsolutePath() + "\"";
    }
    Shell.SU.run(command);
}

Note that this does not mount the file system read/write or check if rm is available on the device (something RootTools does when you invoke deleteFileOrDirectory).


This is a lengthy answer. If you have further questions I would suggest reading the documentation for either library project.

Originally posted on Stack Overflow. Public user contributions are licensed under Creative Commons Attribution-ShareAlike.