Android videoview 可以播放存储在内部存储器上的视频吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3038474/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can a videoview play a video stored on internal storage?
提问by shellman
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().
我正在尝试为我的用户提供使用外部或内部存储的能力。我正在显示图像和视频(具有科学性质)。将媒体存储在 SD 卡上时,一切正常。但是当我在内部存储媒体时,只会显示图像。无论我尝试什么,在尝试加载和显示存储在 applicationcontext.getFilesDir() 下的媒体时都会遇到各种错误。
Is there a trick to setting a videoview's content to such a file?
将视频视图的内容设置为这样的文件有什么技巧吗?
Can a ContentResolver help me?
ContentResolver 可以帮助我吗?
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();
回答by gtkandroid
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:
MediaPlayer 要求正在播放的文件具有全球可读的权限。您可以在 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.
您可能会看到“-rw------”,这意味着只有所有者(您的应用程序,而不是 MediaPlayer)具有读/写权限。
Note: Your phone must be rooted in order to use the ls command without specifying the file (in the internal memory).
注意:您的手机必须root 才能使用ls 命令而不指定文件(在内存中)。
If your phone is rooted, you can add world-read permissions in adb shell with the following command:
如果您的手机已root,则可以使用以下命令在 adb shell 中添加全局读取权限:
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:
如果您需要以编程方式修改这些权限(需要root手机!),您可以在您的应用程序代码中使用以下命令:
Runtime.getRuntime().exec("chmod o+r /data/data/com.mypackage/myfile");
Which is basically a linux command. See https://help.ubuntu.com/community/FilePermissionsfor more on chmod.
这基本上是一个linux命令。有关chmod 的更多信息,请参阅https://help.ubuntu.com/community/FilePermissions。
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():
编辑:在这里找到了另一种简单的方法(对于没有root手机的人很有用)。由于应用程序拥有该文件,它可以创建一个文件描述符并将其传递给 mediaPlayer.setDataSource():
FileInputStream fileInputStream = new FileInputStream("/data/data/com.mypackage/myfile");
mediaPlayer.setDataSource(fileInputStream.getFD());
This approach avoids the permission issue completely.
这种方法完全避免了权限问题。
回答by HocineHamdi
You can use:
您可以使用:
videoView.setVideoURI(Uri.parse(file.getAbsolutePath()));
if the file is world readable
如果文件是世界可读的
Or you can use a content provider
或者您可以使用内容提供程序
回答by Jawad Zeb
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);
}
}
回答by tuandroid
回答by tutts
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
我在这个线程遇到了同样的问题,我正在将我的视频从网络下载到内部存储,结果在保存时您可以指定 RW 模式,即更改PRIVATE
为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();
}
}
回答by HocineHamdi
You can't just play it directly.
你不能直接播放它。
You need to implement a ContentProvider then pass the defined Uri to setVideoUri(uri) method.
您需要实现一个 ContentProvider,然后将定义的 Uri 传递给 setVideoUri(uri) 方法。