I'm trying to provide my users with the ability to use either external or internal storage. I'm displaying both images and videos (of a scientific nature). When storing the media on the SD card, all is fine. But when I store the media internally, only the images will display. No matter what I try I get various errors when trying to load and display the media stored under the applicationcontext.getFilesDir().
Is there a trick to setting a videoview's content to such a file?
Can a ContentResolver help me?
On a related note, is it considered bad form to assume that external storage exists?
Thanks in advance,
Sid
Below is one version that fails with "Cannot play video. Sorry, this video cannot be played". But I have many other modes of failure. I can copy the internal video to temp storage (external) and play it, so this copy to internal does indeed create a valid movie. It only fails when I try to play it directly from the internal storage.
videoFile = new File(this.getFilesDir() + File.separator + "test.mp4");
InputStream data = res.openRawResource(R.raw.moviegood);
try {
OutputStream myOutputStream = new FileOutputStream(videoFile);
byte[] buffer = new byte[8192];
int length;
while ( (length = data.read(buffer)) > 0 ) {
myOutputStream.write(buffer);
}
//Close the streams
myOutputStream.flush();
myOutputStream.close();
data.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
vview.setKeepScreenOn(true);
vview.setVideoPath(videoFile.getAbsolutePath());
vview.start();
MediaPlayer requires that the file being played has world-readable permissions. You can view the permissions of the file with the following command in adb shell:
You will probably see "-rw------", which means that only the owner (your app, not MediaPlayer) has read/write permissions.
Note: Your phone must be rooted in order to use the ls command without specifying the file (in the internal memory).
If your phone is rooted, you can add world-read permissions in adb shell with the following command:
If you need to modify these permissions programmatically (requires rooted phone!), you can use the following command in your app code:
Which is basically a linux command. See https://help.ubuntu.com/community/FilePermissions for more on chmod.
EDIT: Found another simple approach here (useful for those without rooted phones). Since the application owns the file, it can create a file descriptor and pass that to mediaPlayer.setDataSource():
This approach avoids the permission issue completely.
You can't just play it directly.
You need to implement a ContentProvider then pass the defined Uri to setVideoUri(uri) method.
For detail check this tutorial
I posted a custom VideoView implementation there.
The VideoView implementation has the
setVideoFD(FileDescriptor fd)
method and solves this issue.I came across this thread with the same problem, I'm downloading my videos from the web to the internal storage, turns out when saving you can specify the RW mode, i.e change from
PRIVATE
toWORLD_READABLE
You can use:
if the file is world readable
Or you can use a content provider