17

From here I know a way to write a file and be accessible to other app and other intent, but now that the Context.MODE_WORLD_READABLE is deprecated how can I safely accomplish this?

FileOutputStream out = myActivity.openFileOutput(fileTo, Context.MODE_WORLD_READABLE);

Okay more info:

I'm using this:

intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, "video/*");

And the uri will be the one that I will write to a sdcard location. And the video will come from the application so problem is, if this is now not allowed, how can I write the file and view it.

Community
  • 1
  • 1
Marl
  • 1,492
  • 2
  • 22
  • 37

3 Answers3

12

And the uri will be the one that I will write to a sdcard location.

That is already MODE_WORLD_WRITABLE by default. Also note that the code you have listed (openFileOutput()) does not write to external storage (what you incorrectly call "sdcard"). openFileOutput() is for internal storage.

And the video will come from the application so problem is, if this is now not allowed, how can I write the file and view it.

If you are really writing the file to external storage, just use a Uri pointing to that file.

If you are writing the file to internal storage, create a ContentProvider to serve that file, and use a Uri pointing to that ContentProvider. Here is a sample application with a ContentProvider that extracts a PDF file from assets/ on first run, then serves up that file via openFile() so it can be viewed by a PDF viewer.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Thanks. That hits the spot. :D – Marl Dec 14 '12 at 04:20
  • 1
    If a video file has been saved as a file to internal storage (using the location given by `getCacheDir`), are you saying that the ContentProvider could somehow serve a URI to a VideoView that is then playable? Because the direct URI to the internally saved video does not work (I guess because a video file needs to be world readable in order to be played by a video view, but is not world readable if in the application's private internal cache). – Daniel Smith Dec 28 '12 at 19:08
  • @DanielSmith: "are you saying that the ContentProvider could somehow serve a URI to a VideoView that is then playable? " -- video is tricky, because usually the player needs a seekable stream (can move forwards and backwards), and a stream published by a `ContentProvider` is not seekable. I am not aware of any video formats that can be played with a forward-only stream, though I have not researched that point. – CommonsWare Dec 28 '12 at 19:35
  • @CommonsWare: So... is it impossible to play a video stored on the internal cache? There are so many SO questions regarding the topic, but none seem to have working solutions. My current working solution stores videos temporarily on the external cache, but they can still be pulled using `adb pull ...`, and I'd prefer if these videos were secured by the internal private cache. Thoughts? – Daniel Smith Dec 28 '12 at 19:51
  • 2
    @DanielSmith: "So... is it impossible to play a video stored on the internal cache?" -- if you make the file world-readable (via `openFileOutput()`, or `setReadable(true)` on API Level 9+), it should be playable. I have heard of people setting up HTTP daemons to play the video from internal storage, though that seems painful. And since anyone who wants to can get to internal storage through rooting, it's not like internal storage is an impregnable fortress. – CommonsWare Dec 28 '12 at 20:08
10

Save your video in your internal memory using:

openFileOutput("test.mp4", "MODE_PRIVATE");

Then do this:

String path = context.getFilesDir().getAbsolutePath() + "/test.mp4"; // path to the root of internal memory.
File f = new File(path);
f.setReadable(true, false);
Intent playIntent ....
playIntent.setType("video/*");
playIntent.setData(Uri.fromFile(f));

Good Luck.

hasan
  • 23,815
  • 10
  • 63
  • 101
  • Thank you this helped me, didn't want to use sdcard for a temp file, note this is Api 9 or higher, so ended up using mode_world_readable for Api 8, and this for 9 and higher. – Martin Sykes Jun 30 '13 at 18:23
  • of-course the best choice is ContentProvider, in some cases this will not work. for example, players can't access the srt files saved in the same place of the video file and used the same name even if we setReadable for the srt files. – hasan Jul 02 '13 at 14:08
  • @hasan83 if i write a file using FileOutputStream to data/data/com.****.***/myfolder,its not allowing me to read the file like above any reason? – NitZRobotKoder Jan 27 '15 at 08:29
3

It seems to look like the docs are clear about it.

This constant was deprecated in API level 17.

Creating world-readable files is very dangerous, and likely to cause security holes in applications. It is strongly discouraged; instead, applications should use more formal mechanism for interactions such as ContentProvider, BroadcastReceiver, and Service. There are no guarantees that this access mode will remain on a file, such as when it goes through a backup and restore. File creation mode: allow all other applications to have read access to the created file.

Andro Selva
  • 53,910
  • 52
  • 193
  • 240