开发者

Can a videoview play a video stored on internal storage?

开发者 https://www.devze.com 2023-01-03 05:02 出处:网络
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

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 ContentRe开发者_运维问答solver 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:

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.


You can use:

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

if the file is world readable

Or you can use a content provider


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);
    }
}


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 to WORLD_READABLE

URL url = new URL(_url);
InputStream input = null;
FileOutputStream output = null;

try {
String outputName = "video.mp4";

input = url.openConnection().getInputStream();
output = c.openFileOutput(outputName, Context.MODE_WORLD_READABLE);

int read;
byte[] data = new byte[5120]; //5MB byte array
while ((read = input.read(data)) != -1)
output.write(data, 0, read);

return true;

} finally {
if (output != null)
   output.close();
if (input != null)
   input.close();
    }
}


You can't just play it directly.

You need to implement a ContentProvider then pass the defined Uri to setVideoUri(uri) method.

0

精彩评论

暂无评论...
验证码 换一张
取 消