Search code examples
javaandroidfileandroid-file

Make new file next to Uri


I just started helping with an established android project, and am at a loss as to how to wrangle the system into doing what I want. Please keep in mind I am very new to android still, so apologies if part of this question doesn't make sense, or I say things wrong.

The project uses a ContentResolver to traverse the DCIM folder of a usb OTG stick or internal storage. What I am given is the Uri of each video file found. I need to open and get a raw file descriptor number of that file, then make a new file next to it for writing (with a name like originalvideo.mp4.trim.mp4, doesn't have to be pretty), and get a raw file descriptor number for that as well.

The project makes ffmpeg calls on these files, and to avoid permissions errors with the OTG stick (since Google updated OTG permissions to be incredibly restrictive), we can only use file descriptors obtained from Java. This is a royal pain in the neck, but after weeks of poking around it is the only way we have found to make this work, so we're sticking with it.

This is what currently happens inside the traversal loops:

final Uri documentUri = DocumentsContract.buildDocumentUriUsingTree(rootUri, docId);
ParcelFileDescriptor fd = getContentResolver().openFileDescriptor(documentUri, "r");

if (fd != null) {
    int ret = NativeLib.testFd( fd.getFd( ) );
}

The path names I get from the Uri look like this: /tree/primary:DCIM/document/primary:DCIM/V0480060.MP4 and I am at a loss as to how to make and open a new file next to that one like this: /tree/primary:DCIM/document/primary:DCIM/V0480060.MP4.trim.mp4. I have tried converting the Uri to a file, I have tried editing the path before creating a file, but both throw IOExceptions, saying No such file or directory. No duh, I'm trying to create it.

This is the closest I have come to getting it to work:

File f = new File( documentUri.getPath() + ".trim.mp4" );

if( !f.exists() )
    f.createNewFile();

ParcelFileDescriptor fn = ParcelFileDescriptor.open( f, ParcelFileDescriptor.MODE_WRITE_ONLY );

But even that throws an IOExcept.

Thank you for any help you can offer.


Solution

  • The path names I get from the Uri look like this: /tree/primary:DCIM/document/primary:DCIM/V0480060.MP4

    A Uri is not a file. If the scheme of the Uri happens to be file, then the path of the Uri will be a filesystem path. Otherwise, it is an opaque string.

    I am at a loss as to how to make and open a new file next to that one like this

    rootUri is a Uri pointing to a document tree. So, given that:

    Step #1: Wrap that in a DocumentFile, via fromTreeUri()

    Step #2: Create another document in the same tree, using createFile()

    Step #3: Use the Uri that you get from createFile() in the same fashion as you are using documentUri

    Now, bear in mind that you do not have strict control over the filename. Probably the DocumentsProvider handling USB OTG will use the "display name" that you pass into createFile() as the filename. That is not a requirement. The point behind the Storage Access Framework (DocumentsContract, etc.) is to get away from thinking in terms of files and filenames.