android:sharedUserId=“android.uid.system” Obtaining Files from SDCard











up vote
0
down vote

favorite












I have a scenario in Android (SDK 19/KitKat 4.4.2) where my application is to be signed as a system level application (App 1) using android:sharedUserId="android.uid.system" in the Manifest.xml. This means that this application is unable to write or read from SD cards, be they external or built into the device.



If I needed to obtain a large file from the SDCard and read it into my application, what is the best approach to do this?



My goal is simply to obtain image files from the SDCard. However, even images can be relatively big if they're uncompressed bitmaps.



I've tried the following approaches:




  1. Creating a new application that is not signed as the system user (App2). Starting a service that exists in this App2 from App1, then reading in the file from the SD card from here, then obtaining the byte of the file, and sending it over via AIDL to App1 in chunks. This works in terms of reading the file from the SDCard and sending it over, however AIDL has a cap of 1mb for each transaction and is also very slow to a point where I should probably limit the size of images allowed to be given to the application to make this feature usable. Not the most ideal in my opinion.


  2. I've tried using FileProvider in App 2 (UID: 10007), however in this scenario I need to not open any graphical interface to select the file I want and a target application. I need to just send it over immediately to App 1 (UID: 10047) or obtain it immediately from App1. I'm not sure if it's possible to use FileProvider without those gui steps. I tried just creating the Uri from App2 then sending the Uri to App1 over AIDL, then giving permissions via context.grantUriPermissions(packageName,uri,READ/WRITE), but always end up with a security error where App1 does not have permission to read the uri App2 is providing.



java.lang.SecurityException: No permission grant found for UID 10047 and Uri content://com.test.sdcard/folder/img.png



Where UID 10047 is App 1 and UID 10007 is App 2.



Any alternative solutions to this problem?










share|improve this question




























    up vote
    0
    down vote

    favorite












    I have a scenario in Android (SDK 19/KitKat 4.4.2) where my application is to be signed as a system level application (App 1) using android:sharedUserId="android.uid.system" in the Manifest.xml. This means that this application is unable to write or read from SD cards, be they external or built into the device.



    If I needed to obtain a large file from the SDCard and read it into my application, what is the best approach to do this?



    My goal is simply to obtain image files from the SDCard. However, even images can be relatively big if they're uncompressed bitmaps.



    I've tried the following approaches:




    1. Creating a new application that is not signed as the system user (App2). Starting a service that exists in this App2 from App1, then reading in the file from the SD card from here, then obtaining the byte of the file, and sending it over via AIDL to App1 in chunks. This works in terms of reading the file from the SDCard and sending it over, however AIDL has a cap of 1mb for each transaction and is also very slow to a point where I should probably limit the size of images allowed to be given to the application to make this feature usable. Not the most ideal in my opinion.


    2. I've tried using FileProvider in App 2 (UID: 10007), however in this scenario I need to not open any graphical interface to select the file I want and a target application. I need to just send it over immediately to App 1 (UID: 10047) or obtain it immediately from App1. I'm not sure if it's possible to use FileProvider without those gui steps. I tried just creating the Uri from App2 then sending the Uri to App1 over AIDL, then giving permissions via context.grantUriPermissions(packageName,uri,READ/WRITE), but always end up with a security error where App1 does not have permission to read the uri App2 is providing.



    java.lang.SecurityException: No permission grant found for UID 10047 and Uri content://com.test.sdcard/folder/img.png



    Where UID 10047 is App 1 and UID 10007 is App 2.



    Any alternative solutions to this problem?










    share|improve this question


























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      I have a scenario in Android (SDK 19/KitKat 4.4.2) where my application is to be signed as a system level application (App 1) using android:sharedUserId="android.uid.system" in the Manifest.xml. This means that this application is unable to write or read from SD cards, be they external or built into the device.



      If I needed to obtain a large file from the SDCard and read it into my application, what is the best approach to do this?



      My goal is simply to obtain image files from the SDCard. However, even images can be relatively big if they're uncompressed bitmaps.



      I've tried the following approaches:




      1. Creating a new application that is not signed as the system user (App2). Starting a service that exists in this App2 from App1, then reading in the file from the SD card from here, then obtaining the byte of the file, and sending it over via AIDL to App1 in chunks. This works in terms of reading the file from the SDCard and sending it over, however AIDL has a cap of 1mb for each transaction and is also very slow to a point where I should probably limit the size of images allowed to be given to the application to make this feature usable. Not the most ideal in my opinion.


      2. I've tried using FileProvider in App 2 (UID: 10007), however in this scenario I need to not open any graphical interface to select the file I want and a target application. I need to just send it over immediately to App 1 (UID: 10047) or obtain it immediately from App1. I'm not sure if it's possible to use FileProvider without those gui steps. I tried just creating the Uri from App2 then sending the Uri to App1 over AIDL, then giving permissions via context.grantUriPermissions(packageName,uri,READ/WRITE), but always end up with a security error where App1 does not have permission to read the uri App2 is providing.



      java.lang.SecurityException: No permission grant found for UID 10047 and Uri content://com.test.sdcard/folder/img.png



      Where UID 10047 is App 1 and UID 10007 is App 2.



      Any alternative solutions to this problem?










      share|improve this question















      I have a scenario in Android (SDK 19/KitKat 4.4.2) where my application is to be signed as a system level application (App 1) using android:sharedUserId="android.uid.system" in the Manifest.xml. This means that this application is unable to write or read from SD cards, be they external or built into the device.



      If I needed to obtain a large file from the SDCard and read it into my application, what is the best approach to do this?



      My goal is simply to obtain image files from the SDCard. However, even images can be relatively big if they're uncompressed bitmaps.



      I've tried the following approaches:




      1. Creating a new application that is not signed as the system user (App2). Starting a service that exists in this App2 from App1, then reading in the file from the SD card from here, then obtaining the byte of the file, and sending it over via AIDL to App1 in chunks. This works in terms of reading the file from the SDCard and sending it over, however AIDL has a cap of 1mb for each transaction and is also very slow to a point where I should probably limit the size of images allowed to be given to the application to make this feature usable. Not the most ideal in my opinion.


      2. I've tried using FileProvider in App 2 (UID: 10007), however in this scenario I need to not open any graphical interface to select the file I want and a target application. I need to just send it over immediately to App 1 (UID: 10047) or obtain it immediately from App1. I'm not sure if it's possible to use FileProvider without those gui steps. I tried just creating the Uri from App2 then sending the Uri to App1 over AIDL, then giving permissions via context.grantUriPermissions(packageName,uri,READ/WRITE), but always end up with a security error where App1 does not have permission to read the uri App2 is providing.



      java.lang.SecurityException: No permission grant found for UID 10047 and Uri content://com.test.sdcard/folder/img.png



      Where UID 10047 is App 1 and UID 10007 is App 2.



      Any alternative solutions to this problem?







      android system android-4.4-kitkat aidl






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 8 at 19:14









      Kling Klang

      32.2k156287




      32.2k156287










      asked Nov 8 at 18:36









      Jetompki

      215




      215
























          1 Answer
          1






          active

          oldest

          votes

















          up vote
          1
          down vote













          A system app can't read from external storage? That's news to me, but anyway.



          You can always just create a pipe and pass the read end back over the IPC mechanism of your choice (ContentProvider.call() for example). The service-side starts a thread and writes the file to the write end, and passes the read end back to the client. Something like this on the service side:



            ParcelFileDescriptor fds;
          try {
          fds = ParcelFileDescriptor.createPipe();
          } catch (IOException e) {
          e.printStackTrace();
          return false;
          }

          final ParcelFileDescriptor readFd = fds[0];
          final ParcelFileDescriptor writeFd = fds[1];

          // TODO: start a thread to write file to writeFd

          Bundle result = new Bundle();
          extras.putParcelable(EXTRA_READ_FD, readFd);

          return result; // Return from call() to client


          Obviously there is a lot of boilerplate code left as an exercise for the reader.






          share|improve this answer





















          • Struggling with this approach. Could you illustrate an example with how you write data into the writeEnd, then read the data back using the readEnd? I was following this stackoverflow.com/questions/18212152/… which seems similar to what you suggest, but I encountered the error mentioned with java.io.IOException: read failed: EBADF (Bad file number)
            – Jetompki
            Nov 8 at 23:18










          • Nevermind, managed to figure it out using the getFileDescriptor(byte data) snippet from here. stackoverflow.com/questions/51902834/…
            – Jetompki
            Nov 9 at 16:53










          • I have a concern regarding the start of the thread on the service side, and the reading of the Descriptor on the client side. In the snippet you provide, it seems that the client can retrieve the readEnd before there is actually any data to be read, given that you spawn a thread to write to the writeEnd. I tried implementing a delay (thread.sleep) in the thread to write on the service side, but it seems that my client is able to read the data fine regardless (albeit delayed) despite that I start my read on the client side as soon as that result in your snippet is returned. Why does this work?
            – Jetompki
            Nov 9 at 21:50










          • If nothing is written to the read end (yet), the IO will block. The pipe is still open. Think of it like making a network request and the server hasn't returned any data yet. The network request doesn't fail just because there's no data to read.
            – Jeffrey Blattman
            Nov 9 at 21:55











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53214114%2fandroidshareduserid-android-uid-system-obtaining-files-from-sdcard%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          1
          down vote













          A system app can't read from external storage? That's news to me, but anyway.



          You can always just create a pipe and pass the read end back over the IPC mechanism of your choice (ContentProvider.call() for example). The service-side starts a thread and writes the file to the write end, and passes the read end back to the client. Something like this on the service side:



            ParcelFileDescriptor fds;
          try {
          fds = ParcelFileDescriptor.createPipe();
          } catch (IOException e) {
          e.printStackTrace();
          return false;
          }

          final ParcelFileDescriptor readFd = fds[0];
          final ParcelFileDescriptor writeFd = fds[1];

          // TODO: start a thread to write file to writeFd

          Bundle result = new Bundle();
          extras.putParcelable(EXTRA_READ_FD, readFd);

          return result; // Return from call() to client


          Obviously there is a lot of boilerplate code left as an exercise for the reader.






          share|improve this answer





















          • Struggling with this approach. Could you illustrate an example with how you write data into the writeEnd, then read the data back using the readEnd? I was following this stackoverflow.com/questions/18212152/… which seems similar to what you suggest, but I encountered the error mentioned with java.io.IOException: read failed: EBADF (Bad file number)
            – Jetompki
            Nov 8 at 23:18










          • Nevermind, managed to figure it out using the getFileDescriptor(byte data) snippet from here. stackoverflow.com/questions/51902834/…
            – Jetompki
            Nov 9 at 16:53










          • I have a concern regarding the start of the thread on the service side, and the reading of the Descriptor on the client side. In the snippet you provide, it seems that the client can retrieve the readEnd before there is actually any data to be read, given that you spawn a thread to write to the writeEnd. I tried implementing a delay (thread.sleep) in the thread to write on the service side, but it seems that my client is able to read the data fine regardless (albeit delayed) despite that I start my read on the client side as soon as that result in your snippet is returned. Why does this work?
            – Jetompki
            Nov 9 at 21:50










          • If nothing is written to the read end (yet), the IO will block. The pipe is still open. Think of it like making a network request and the server hasn't returned any data yet. The network request doesn't fail just because there's no data to read.
            – Jeffrey Blattman
            Nov 9 at 21:55















          up vote
          1
          down vote













          A system app can't read from external storage? That's news to me, but anyway.



          You can always just create a pipe and pass the read end back over the IPC mechanism of your choice (ContentProvider.call() for example). The service-side starts a thread and writes the file to the write end, and passes the read end back to the client. Something like this on the service side:



            ParcelFileDescriptor fds;
          try {
          fds = ParcelFileDescriptor.createPipe();
          } catch (IOException e) {
          e.printStackTrace();
          return false;
          }

          final ParcelFileDescriptor readFd = fds[0];
          final ParcelFileDescriptor writeFd = fds[1];

          // TODO: start a thread to write file to writeFd

          Bundle result = new Bundle();
          extras.putParcelable(EXTRA_READ_FD, readFd);

          return result; // Return from call() to client


          Obviously there is a lot of boilerplate code left as an exercise for the reader.






          share|improve this answer





















          • Struggling with this approach. Could you illustrate an example with how you write data into the writeEnd, then read the data back using the readEnd? I was following this stackoverflow.com/questions/18212152/… which seems similar to what you suggest, but I encountered the error mentioned with java.io.IOException: read failed: EBADF (Bad file number)
            – Jetompki
            Nov 8 at 23:18










          • Nevermind, managed to figure it out using the getFileDescriptor(byte data) snippet from here. stackoverflow.com/questions/51902834/…
            – Jetompki
            Nov 9 at 16:53










          • I have a concern regarding the start of the thread on the service side, and the reading of the Descriptor on the client side. In the snippet you provide, it seems that the client can retrieve the readEnd before there is actually any data to be read, given that you spawn a thread to write to the writeEnd. I tried implementing a delay (thread.sleep) in the thread to write on the service side, but it seems that my client is able to read the data fine regardless (albeit delayed) despite that I start my read on the client side as soon as that result in your snippet is returned. Why does this work?
            – Jetompki
            Nov 9 at 21:50










          • If nothing is written to the read end (yet), the IO will block. The pipe is still open. Think of it like making a network request and the server hasn't returned any data yet. The network request doesn't fail just because there's no data to read.
            – Jeffrey Blattman
            Nov 9 at 21:55













          up vote
          1
          down vote










          up vote
          1
          down vote









          A system app can't read from external storage? That's news to me, but anyway.



          You can always just create a pipe and pass the read end back over the IPC mechanism of your choice (ContentProvider.call() for example). The service-side starts a thread and writes the file to the write end, and passes the read end back to the client. Something like this on the service side:



            ParcelFileDescriptor fds;
          try {
          fds = ParcelFileDescriptor.createPipe();
          } catch (IOException e) {
          e.printStackTrace();
          return false;
          }

          final ParcelFileDescriptor readFd = fds[0];
          final ParcelFileDescriptor writeFd = fds[1];

          // TODO: start a thread to write file to writeFd

          Bundle result = new Bundle();
          extras.putParcelable(EXTRA_READ_FD, readFd);

          return result; // Return from call() to client


          Obviously there is a lot of boilerplate code left as an exercise for the reader.






          share|improve this answer












          A system app can't read from external storage? That's news to me, but anyway.



          You can always just create a pipe and pass the read end back over the IPC mechanism of your choice (ContentProvider.call() for example). The service-side starts a thread and writes the file to the write end, and passes the read end back to the client. Something like this on the service side:



            ParcelFileDescriptor fds;
          try {
          fds = ParcelFileDescriptor.createPipe();
          } catch (IOException e) {
          e.printStackTrace();
          return false;
          }

          final ParcelFileDescriptor readFd = fds[0];
          final ParcelFileDescriptor writeFd = fds[1];

          // TODO: start a thread to write file to writeFd

          Bundle result = new Bundle();
          extras.putParcelable(EXTRA_READ_FD, readFd);

          return result; // Return from call() to client


          Obviously there is a lot of boilerplate code left as an exercise for the reader.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 8 at 19:32









          Jeffrey Blattman

          16.4k564114




          16.4k564114












          • Struggling with this approach. Could you illustrate an example with how you write data into the writeEnd, then read the data back using the readEnd? I was following this stackoverflow.com/questions/18212152/… which seems similar to what you suggest, but I encountered the error mentioned with java.io.IOException: read failed: EBADF (Bad file number)
            – Jetompki
            Nov 8 at 23:18










          • Nevermind, managed to figure it out using the getFileDescriptor(byte data) snippet from here. stackoverflow.com/questions/51902834/…
            – Jetompki
            Nov 9 at 16:53










          • I have a concern regarding the start of the thread on the service side, and the reading of the Descriptor on the client side. In the snippet you provide, it seems that the client can retrieve the readEnd before there is actually any data to be read, given that you spawn a thread to write to the writeEnd. I tried implementing a delay (thread.sleep) in the thread to write on the service side, but it seems that my client is able to read the data fine regardless (albeit delayed) despite that I start my read on the client side as soon as that result in your snippet is returned. Why does this work?
            – Jetompki
            Nov 9 at 21:50










          • If nothing is written to the read end (yet), the IO will block. The pipe is still open. Think of it like making a network request and the server hasn't returned any data yet. The network request doesn't fail just because there's no data to read.
            – Jeffrey Blattman
            Nov 9 at 21:55


















          • Struggling with this approach. Could you illustrate an example with how you write data into the writeEnd, then read the data back using the readEnd? I was following this stackoverflow.com/questions/18212152/… which seems similar to what you suggest, but I encountered the error mentioned with java.io.IOException: read failed: EBADF (Bad file number)
            – Jetompki
            Nov 8 at 23:18










          • Nevermind, managed to figure it out using the getFileDescriptor(byte data) snippet from here. stackoverflow.com/questions/51902834/…
            – Jetompki
            Nov 9 at 16:53










          • I have a concern regarding the start of the thread on the service side, and the reading of the Descriptor on the client side. In the snippet you provide, it seems that the client can retrieve the readEnd before there is actually any data to be read, given that you spawn a thread to write to the writeEnd. I tried implementing a delay (thread.sleep) in the thread to write on the service side, but it seems that my client is able to read the data fine regardless (albeit delayed) despite that I start my read on the client side as soon as that result in your snippet is returned. Why does this work?
            – Jetompki
            Nov 9 at 21:50










          • If nothing is written to the read end (yet), the IO will block. The pipe is still open. Think of it like making a network request and the server hasn't returned any data yet. The network request doesn't fail just because there's no data to read.
            – Jeffrey Blattman
            Nov 9 at 21:55
















          Struggling with this approach. Could you illustrate an example with how you write data into the writeEnd, then read the data back using the readEnd? I was following this stackoverflow.com/questions/18212152/… which seems similar to what you suggest, but I encountered the error mentioned with java.io.IOException: read failed: EBADF (Bad file number)
          – Jetompki
          Nov 8 at 23:18




          Struggling with this approach. Could you illustrate an example with how you write data into the writeEnd, then read the data back using the readEnd? I was following this stackoverflow.com/questions/18212152/… which seems similar to what you suggest, but I encountered the error mentioned with java.io.IOException: read failed: EBADF (Bad file number)
          – Jetompki
          Nov 8 at 23:18












          Nevermind, managed to figure it out using the getFileDescriptor(byte data) snippet from here. stackoverflow.com/questions/51902834/…
          – Jetompki
          Nov 9 at 16:53




          Nevermind, managed to figure it out using the getFileDescriptor(byte data) snippet from here. stackoverflow.com/questions/51902834/…
          – Jetompki
          Nov 9 at 16:53












          I have a concern regarding the start of the thread on the service side, and the reading of the Descriptor on the client side. In the snippet you provide, it seems that the client can retrieve the readEnd before there is actually any data to be read, given that you spawn a thread to write to the writeEnd. I tried implementing a delay (thread.sleep) in the thread to write on the service side, but it seems that my client is able to read the data fine regardless (albeit delayed) despite that I start my read on the client side as soon as that result in your snippet is returned. Why does this work?
          – Jetompki
          Nov 9 at 21:50




          I have a concern regarding the start of the thread on the service side, and the reading of the Descriptor on the client side. In the snippet you provide, it seems that the client can retrieve the readEnd before there is actually any data to be read, given that you spawn a thread to write to the writeEnd. I tried implementing a delay (thread.sleep) in the thread to write on the service side, but it seems that my client is able to read the data fine regardless (albeit delayed) despite that I start my read on the client side as soon as that result in your snippet is returned. Why does this work?
          – Jetompki
          Nov 9 at 21:50












          If nothing is written to the read end (yet), the IO will block. The pipe is still open. Think of it like making a network request and the server hasn't returned any data yet. The network request doesn't fail just because there's no data to read.
          – Jeffrey Blattman
          Nov 9 at 21:55




          If nothing is written to the read end (yet), the IO will block. The pipe is still open. Think of it like making a network request and the server hasn't returned any data yet. The network request doesn't fail just because there's no data to read.
          – Jeffrey Blattman
          Nov 9 at 21:55


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53214114%2fandroidshareduserid-android-uid-system-obtaining-files-from-sdcard%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          這個網誌中的熱門文章

          Xamarin.form Move up view when keyboard appear

          Post-Redirect-Get with Spring WebFlux and Thymeleaf

          Anylogic : not able to use stopDelay()