1

I'm trying to open a file that I've downloaded on one app, in another viewer, such as the stock gallery or a PDF viewer. Here is how I save the file:

FileOutputStream fos = null;

try {
      fos = from.openFileOutput(name, Context.MODE_WORLD_READABLE);
      fos.write(data); //data is my byte[]
      fos.flush();
      fos.close();
}catch...

// at this point the file IS written to the path. I can SFTP to my [rooted] device
// and can download the file, it's valid, it opens on my computer.

File outputFile = new File(from.getFilesDir().getAbsolutePath() + "/" + name);
if(!outputFile.exists()){
  //show some error message
  //we are NOT entering here, just a programmatic check that it exists.
  return;
}
String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension("." + extension.toUpperCase()); //extension is file extension as String
//if it doesn't work, I set it manually to some valid one by looking at the extension myself.
Intent intent = new Intent();
intent.setDataAndType(Uri.parse(outputFile.getAbsolutePath()), mime);
intent.setAction(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

I can see the open dialog (and it's correct, e.g. gallery is displayed for a PNG file, or Adobe Reader if it's PDF etc), and the activity opens correctly. However, they can't access the file. Why can't they access the file?

Can Poyrazoğlu
  • 33,241
  • 48
  • 191
  • 389
  • 4
    `MODE_WORLD_READABLE` has been deprecated, and it was never a good idea in the first place. `FLAG_GRANT_READ_URI_PERMISSION` has nothing to do with file permissions, but rather with `ContentProvider` permissions. I suggest that you add [a `FileProvider`](http://developer.android.com/reference/android/support/v4/content/FileProvider.html) to serve up the file. – CommonsWare May 17 '15 at 12:45
  • You are storing the app in app's private memory.i think you have to store the file in SD card, so that other apps can access it. Memory , private to your app, cannot be accessed by other apps. – dora May 17 '15 at 12:51
  • @CommonsWare I've ended up with `FileProvider`, thanks. – Can Poyrazoğlu May 17 '15 at 14:11

2 Answers2

1

There are several ways to store data in Android, and as I can see, by default the storage in internal memory is "private" to your app (as I think you are doing) so it won't be as simple to access from another app.

The solution seems to be using "External memory" (which can be the internal storage of the mobile or removable SD card)
Here you have the official guide to Android Storage, where you can find some examples of this kind of storage:

angrykoala
  • 3,774
  • 6
  • 30
  • 55
1

The official way of sharing streams with third-party apps, where those streams come from internal storage of your app, is via FileProvider. FileProvider is an implementation of ContentProvider that handles sharing these streams for you.

FileProvider will work with most well-written Android apps. Sometimes, the app you share or send the content will fail with FileProvider, as the people who wrote that app were lazy and assumed that everything came from MediaStore and you can always map a Uri to a file. That's not the case. To help with compatibility with those broken clients, I have a LegacyCompatCursorWrapper that you can blend into your FileProvider, that provides a canned implementation of Stefan Rusek's solution for this problem.

Community
  • 1
  • 1
CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491