Android - speed up file deletion using Storage Access Framework

Viewed 1266

Since Android 11 will be not possible manipulate with files in public location without SAF. In the past I implemented two choices for working with files on android, if is file NOT located on sdcard then I use standard c++ api, very fast way. If is located on sdcard then I use SAF API - I call java methods with JNI. It worked fine, because if someone needed fast access then were files placed on internal storage, if someone ran out of space then was preferred storage space on sdcard at cost of performance. However Android 11 changes everything and first choice is killed. I can't place files to private folder, because is deleted during uninstallation. My question is about file deletion, because this is in my case biggest speed bottle neck. Just now I delete file this way :

With SAF : DocumentsContract.deleteDocument

With standard c++ API : unlink

While unlink takes almost none time, SAF takes 150ms for deleting small, only few kB big file.

This comparison was tested on sdcard in private folder with unlink in which I have full access and in public folder with DocumentsContract.deleteDocument.

Is DocumentsContract.deleteDocument the only way how to delete file using SAF or is there faster way which can bring back lost performance?

EDIT :

I add more information. I rooted and added sdcard fix, so I can now write to sdcard directly. My application is emulator, I do not delete big folder, this is not my case, emulator deletes here and there various count of files with small size. Here is real log and how I use it :

Standard c++ IO api

unlink(file);

SAF api c++

jstring string=jvmEnv->NewStringUTF(file);
int result = jvmEnv->CallIntMethod( jvmCallbackThread, JavaDeleteFile, string);
jvmEnv->DeleteLocalRef(string);

java

public int callbackDeleteFile(String path) {
    return SAFUtils.delete(path);
}

public static int delete(String path)
{
    try {            
        Uri uri = pathsCache.get(path);
        if (uri == null) {
            buildUri(path, true);
            uri = Uri.parse(builder1.toString());
            pathsCache.put(path, uri);
        }

        if (DocumentsContract.deleteDocument(resolver, uri)) {
            return 0;
        }
    } catch(Exception e) {
        e.printStackTrace();
    }

    return -1;
}

On java side I get/build uri, after that I call DocumentContract, uri manipulation takes around 1ms, bottleneck is DocumentContract.deleteDocument

2019-10-03 09:20:29.478 before uri get/build
2019-10-03 09:20:29.478 after uri get/build
2019-10-03 09:20:29.674 after DocumentContract.deleteDocument

Log with SAF :

SAF log means, jump from c++ to java, call DocumentContract.deleteDocument and back to c++

2019-10-03 08:19:10.039 : SAF DeleteFile /storage/0000-0000/TEST/TEMP/RAW10.ALF, before delete
2019-10-03 08:19:10.253 : SAF DeleteFile /storage/0000-0000/TEST/TEMP/RAW10.ALF, after delete

2019-10-03 08:19:10.254 : SAF DeleteFile /storage/0000-0000/TEST/TEMP/RAW10.MOD, before delete
2019-10-03 08:19:10.475 : SAF DeleteFile /storage/0000-0000/TEST/TEMP/RAW10.MOD, after delete

2019-10-03 08:19:12.602 : SAF DeleteFile /storage/0000-0000/TEST/TEMP/LOC_GODS.DAT, before delete
2019-10-03 08:19:12.786 : SAF DeleteFile /storage/0000-0000/TEST/TEMP/LOC_GODS.DAT, after delete

2019-10-03 08:19:12.829 : SAF DeleteFile /storage/0000-0000/TEST/TEMP/UNP.$$$, before delete
2019-10-03 08:19:12.990 : SAF DeleteFile /storage/0000-0000/TEST/TEMP/UNP.$$$, after delete

2019-10-03 08:19:13.076 : SAF DeleteFile /storage/0000-0000/TEST/TEMP/LOC_DEIT.DAT, before delete
2019-10-03 08:19:13.221 : SAF DeleteFile /storage/0000-0000/TEST/TEMP/LOC_DEIT.DAT, after delete

Log with unlink

pure c++ side

2019-10-03 08:58:03.008 : UNLINK /storage/0000-0000/TEST/TEMP/RAW10.ALF, before unlink
2019-10-03 08:58:03.009 : UNLINK /storage/0000-0000/TEST/TEMP/RAW10.ALF, after unlink

2019-10-03 08:58:03.010 : UNLINK /storage/0000-0000/TEST/TEMP/RAW10.MOD, before unlink
2019-10-03 08:58:03.010 : UNLINK /storage/0000-0000/TEST/TEMP/RAW10.MOD, after unlink

2019-10-03 08:58:05.084 : UNLINK /storage/0000-0000/TEST/TEMP/LOC_GODS.DAT, before unlink
2019-10-03 08:58:05.085 : UNLINK /storage/0000-0000/TEST/TEMP/LOC_GODS.DAT, after unlink

2019-10-03 08:58:05.099 : UNLINK /storage/0000-0000/TEST/TEMP/UNP.$$$, before unlink
2019-10-03 08:58:05.099 : UNLINK /storage/0000-0000/TEST/TEMP/UNP.$$$, after unlink

2019-10-03 08:58:05.116 : UNLINK /storage/0000-0000/TEST/TEMP/LOC_DEIT.DAT, before unlink
2019-10-03 08:58:05.116 : UNLINK /storage/0000-0000/TEST/TEMP/LOC_DEIT.DAT, after unlink
0 Answers
Related