Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a videoview play a video stored on internal storage?

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();
like image 638
shellman Avatar asked Jun 14 '10 15:06

shellman


4 Answers

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:

ls -al /data/data/com.mypackage/myfile

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:

chmod o+r /data/data/com.mypackage/myfile

If you need to modify these permissions programmatically (requires rooted phone!), you can use the following command in your app code:

Runtime.getRuntime().exec("chmod o+r /data/data/com.mypackage/myfile");

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():

FileInputStream fileInputStream = new FileInputStream("/data/data/com.mypackage/myfile");
mediaPlayer.setDataSource(fileInputStream.getFD());

This approach avoids the permission issue completely.

like image 108
gtkandroid Avatar answered Oct 18 '22 02:10

gtkandroid


You can use:

videoView.setVideoURI(Uri.parse(file.getAbsolutePath()));

if the file is world readable

Or you can use a content provider

like image 34
HocineHamdi Avatar answered Oct 18 '22 00:10

HocineHamdi


For detail check this tutorial

public class AndroidVideoViewExample extends Activity {

    private VideoView myVideoView;
    private int position = 0;
    private ProgressDialog progressDialog;
    private MediaController mediaControls;

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // set the main layout of the activity
        setContentView(R.layout.activity_main);

        //set the media controller buttons
        if (mediaControls == null) {
            mediaControls = new MediaController(AndroidVideoViewExample.this);
        }

        //initialize the VideoView
        myVideoView = (VideoView) findViewById(R.id.video_view);

        // create a progress bar while the video file is loading
        progressDialog = new ProgressDialog(AndroidVideoViewExample.this);
        // set a title for the progress bar
        progressDialog.setTitle("JavaCodeGeeks Android Video View Example");
        // set a message for the progress bar
        progressDialog.setMessage("Loading...");
        //set the progress bar not cancelable on users' touch
        progressDialog.setCancelable(false);
        // show the progress bar
        progressDialog.show();

        try {
            //set the media controller in the VideoView
            myVideoView.setMediaController(mediaControls);

            //set the uri of the video to be played
            myVideoView.setVideoURI(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.kitkat));

        } catch (Exception e) {
            Log.e("Error", e.getMessage());
            e.printStackTrace();
        }

        myVideoView.requestFocus();
        //we also set an setOnPreparedListener in order to know when the video file is ready for playback
        myVideoView.setOnPreparedListener(new OnPreparedListener() {

            public void onPrepared(MediaPlayer mediaPlayer) {
                // close the progress bar and play the video
                progressDialog.dismiss();
                //if we have a position on savedInstanceState, the video playback should start from here
                myVideoView.seekTo(position);
                if (position == 0) {
                    myVideoView.start();
                } else {
                    //if we come from a resumed activity, video playback will be paused
                    myVideoView.pause();
                }
            }
        });

    }

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);
        //we use onSaveInstanceState in order to store the video playback position for orientation change
        savedInstanceState.putInt("Position", myVideoView.getCurrentPosition());
        myVideoView.pause();
    }

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        //we use onRestoreInstanceState in order to play the video playback from the stored position 
        position = savedInstanceState.getInt("Position");
        myVideoView.seekTo(position);
    }
}
like image 28
Zar E Ahmer Avatar answered Oct 18 '22 01:10

Zar E Ahmer


I posted a custom VideoView implementation there.

The VideoView implementation has the setVideoFD(FileDescriptor fd) method and solves this issue.

like image 1
tuandroid Avatar answered Oct 18 '22 02:10

tuandroid