3

I have android application which uses a lot of c++ native code. Application needs to work with files located on sdcard(read, create, append). But Kitkat+ denied writing to sdcard for 3rd party applications. Android 5 introduced new API which allows that again.

How to use the new SD card access API presented for Android 5.0 (Lollipop)?

All examples and documentation what I found are mostly for Java side. Examples for native code don't exist or are very unclear. So I want ask few questions.

The link above contains valuable example how to get DocumentFile which can return ParcelFileDescriptor. From this object I am able to receive native file descriptor - ParcelFileDescriptor.getFd(). It's integer which I am sending to c++ code through jni.

In c++ I am opening file with fdopen(fd).

My questions are :

  1. Is fdopen function correct way how to open the file with new api? Or the DocumentFile already opens the file and I should only use fd in further operations.
  2. It's enough to close the file descriptor inside native code with fclose? or should I close it on java side with ParcelFileDescriptor.detachFd(). Or both.

Thank you

EDIT : I getFD and detachFD works. But I never found answer how to correctly replace ftruncate, which needs write access too, and I did not found ftruncate version which takes file descriptor like a input

user1063364
  • 791
  • 6
  • 21

2 Answers2

0

1) yes, use file descriptors and fdopen 2)

  1. Open the ParcelFileDescriptor.
  2. getFd().
  3. Pass the Fd to native code.
  4. Close the ParcelFileDescriptor. (this is closing your java reference)

Fd is just an int representing a linux id for a file. In native:

  1. Fdopen
  2. Do stuff
  3. Fclose (note this is closing your native file pointer)

The two closes are doing different things.

Note: You still need the SAF permission for the file or a higher root.

Anthony
  • 7,638
  • 3
  • 38
  • 71
  • how can I fix the same issue for ftruncate? There is no version of ftruncate what accepts file descriptor – user1063364 Sep 18 '17 at 06:37
  • The only way would be to use the cache as swap space and transfer using SAF. I initially had to do that with the MTP methods since they didn't have FD, either. Submit a bug report, in three years they'll fix it, they did for MTP. SAF was one of the most ill conceived and executed frameworks I have ever seen. They broke half their code and just plain didn't care for years. – Anthony Sep 18 '17 at 12:41
  • Over night I wrote my own ftruncate version using fseek and copying data from one file to another. But...my app is emulator which needs performance and emulated ftruncate is slow. When I am talking about it, jumping to java for file descriptor is very slow too. – user1063364 Sep 19 '17 at 05:49
-1

Try Below Links:

Android - writing/saving files from native code only: Android - writing/saving files from native code only

Android NDK Write File: Android NDK Write File

File Operations in Android NDK: File Operations in Android NDK

Community
  • 1
  • 1
  • Hi, thank you. These link are very useful. But unfortunately are not actual if the filesystem is protected with SAF https://developer.android.com/guide/topics/providers/document-provider.html – user1063364 Jul 12 '15 at 14:23
  • 1
    Currently I use ParcelFileDescriptor.detachFd() and I send it to native code. File is then closed with fclose() function. But I am getting this warning: W/ParcelFileDescriptor﹕ Peer expected signal when closed; unable to deliver after detach.... – user1063364 Jul 13 '15 at 14:58