19

我正在尝试为我的用户提供使用外部或内部存储的能力。我正在显示图像和视频(具有科学性质)。将媒体存储在 SD 卡上时,一切正常。但是当我在内部存储媒体时,只会显示图像。无论我尝试什么,在尝试加载和显示存储在 applicationcontext.getFilesDir() 下的媒体时都会遇到各种错误。

将视频视图的内容设置为这样的文件有技巧吗?

ContentResolver 可以帮助我吗?

在相关说明中,假设存在外部存储是否被认为是不好的形式?

提前致谢,

席德

以下是一个失败的版本,显示“无法播放视频。抱歉,无法播放此视频”。但我还有很多其他的失败模式。我可以将内部视频复制到临时存储(外部)并播放它,所以这个复制到内部确实会创建一个有效的电影。只有当我尝试直接从内部存储播放它时它才会失败。

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();
4

6 回答 6

25

MediaPlayer 要求正在播放的文件具有世界可读的权限。您可以在 adb shell 中使用以下命令查看文件的权限:

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

您可能会看到“-rw------”,这意味着只有所有者(您的应用程序,而不是 MediaPlayer)具有读/写权限。

注意:您的手机必须 root 才能使用 ls 命令而不指定文件(在内部存储器中)。

如果您的手机已root,您可以使用以下命令在 adb shell 中添加 world-read 权限:

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

如果您需要以编程方式修改这些权限(需要 root 手机!),您可以在您的应用代码中使用以下命令:

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

这基本上是一个linux命令。有关 chmod 的更多信息,请参阅https://help.ubuntu.com/community/FilePermissions

编辑:在这里找到了另一种简单的方法(对那些没有根电话的人有用)。由于应用程序拥有该文件,它可以创建一个文件描述符并将其传递给 mediaPlayer.setDataSource():

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

这种方法完全避免了权限问题。

于 2011-03-29T16:00:23.217 回答
2

您可以使用:

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

如果文件是世界可读的

或者您可以使用内容提供商

于 2012-07-09T23:20:39.127 回答
2

有关详细信息,请查看本教程

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);
    }
}
于 2015-01-06T07:21:39.193 回答
1

我在那里发布了一个自定义 VideoView 实现。

VideoView 实现有setVideoFD(FileDescriptor fd)方法并解决了这个问题。

于 2011-11-11T19:09:59.833 回答
1

我遇到了同样问题的这个线程,我正在将我的视频从网络下载到内部存储,结果保存时你可以指定 RW 模式,即从更改PRIVATEWORLD_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();
    }
}
于 2012-04-26T13:12:03.023 回答
0

不能直接播放。

您需要实现一个 ContentProvider 然后将定义的 Uri 传递给 setVideoUri(uri) 方法。

于 2016-06-08T21:36:20.777 回答