Android的 - 从应用程序的私有文件夹加载视频 [英] Android - Load video from private folder of app
问题描述
我有一个问题,我一直在试图找到一个很长一段时间的解决方案。我的情况是这样的:
我有一个应用程序,下载压缩的视频,他们解压在应用程序的私有文件夹,更具体的子文件夹。例如位于 /data/data/my.app.package.name.here/files/assets/assets-955。
在此文件夹中的视频解压缩。在解压缩过程顺利完成,因为我可以拉运行模拟器上的应用程序时要查看视频没有问题。
然后我有一个访问该文件夹的另一项活动,找到视频文件,并尝试打开它。在这一点上,我得到一个错误,对不起,该视频无法播放,出现以下错误堆栈:
01-30 17:36:17.770:D / ContentDemoActivity(6757):文件:/data/data/xxxx/files/assets/assets-955/bank_2.mp4
01-30 17:36:17.830:I / MediaPlayer的(6757):prepareAsync称为状态4
01-30 17:36:17.830:E / MediaPlayer的(6757):错误(1,-2147483648)
01-30 17:36:17.860:E / MediaPlayer的(6757):错误(1,-2147483648)
01-30 17:36:17.860:D / VideoView(6757):错误:1,-2147483648
01-30 17:36:19.370:E / MediaPlayer的(6757)时,停止所谓的状态0
01-30 17:36:19.370:E / MediaPlayer的(6757):错误(-38,0)
01-30 17:36:19.370:W / MediaPlayer的(6757):媒体播放器走了与未处理事件
在code与我试图播放的视频是pretty的基础:
MVIEW =(VideoView)findViewById(R.id.videoView);
mMediaPlayer =新的MediaPlayer();
mView.requestFocus();
mHolder = mView.getHolder();
Log.d(标签,填充内容资产的路径:+ mAssetsPath);
文件F =新的文件(mAssetsPath);
文件[]文件= f.listFiles();
Log.d(标签,文件:+文件[0]的ToString());
mView.setVideoURI(Uri.parse(文件[0]的ToString()));
mView.setMediaController(新的MediaController(本));
和活动的布局有一个普通的VideoView,没有什么花哨那里。
最奇怪的是,用于测试目的我用同样的视频,这次从原始文件夹中加载它,它运行顺利,没有问题。在这种情况下,虽然我不得不与加载它:
开放的视频= Uri.parse(android.resource://+ getPackageName()+/+ R.raw.bank_2);
mVideoView.setVideoURI(视频)
mVideoView.start();
我会与下载的视频做同样的,但似乎没有要在API的功能,将让我从应用程序的私有文件夹加载视频URI。
我已经找到各种解决方案通过使用文件描述符,听众为videoView,标志表明MODE_WORLD_READABLE,pre-计算videoView等的尺寸,但他们都没有积极成果。
简单地说,我的问题是:
- 为什么我会按照我在网上发现了这些错误是与视频文件的编码问题相关的错误?
- 什么是我的情况下,VideoView或surfaceView? 要使用最好的东西
- 这是一个理想的方法来加载从应用程序的私有文件夹的视频,并能够播放呢?
感谢。
修改
CommonsWare的建议后,我去下面的实现:
文件f =新的文件(mAssetsPath);
文件[]文件= f.listFiles();
Log.d(标签,文件:+文件[0]的ToString());
URI URI = URI.create(文件://+(文件[0]的ToString()));
档案文件=新的文件(URI);
尝试 {
Log.d(标记,1);
ParcelFileDescriptor包裹= ParcelFileDescriptor.open(文件,ParcelFileDescriptor.MODE_READ_WRITE);
Log.d(标签,2);
mMediaPlayer.setDataSource(parcel.getFileDescriptor());
Log.d(标签,3);
mMediaPlayer.start();
Log.d(标签,4);
}赶上(FileNotFoundException异常E){
e.printStackTrace();
}赶上(抛出:IllegalArgumentException E){
e.printStackTrace();
}赶上(IllegalStateException异常E){
e.printStackTrace();
}赶上(IOException异常E){
e.printStackTrace();
}
Log.d(标签,5);
不幸的是,这一次我得到了以下错误:
十二月1号至31日:40:11.480:D / ContentDemoActivity(15896):文件:/data/data/com.houseofradon.meb/files/assets/assets-955/bank_2 .MP4
12月1号至31日:40:11.480:D / ContentDemoActivity(15896):1
12月1号至31日:40:11.480:D / ContentDemoActivity(15896):2
12月1号至31日:40:11.500:D / ContentDemoActivity(15896):3
12月1号至31日:40:11.500:E / MediaPlayer的(15896):启动名为状态2
12月1号至31日:40:11.500:E / MediaPlayer的(15896):错误(-38,0)
12月1号至31日:40:11.500:D / ContentDemoActivity(15896):4
12月1号至31日:40:11.500:D / ContentDemoActivity(15896):5
12月1号至31日:40:11.530:E / MediaPlayer的(15896):错误(-38,0)
媒体播放器启动时
那么,事情发生。错误code -38似乎并不意味着具体的东西,因为我发现<一href="https://github.com/android/platform_external_opencore/blob/master/pvmi/pvmf/include/pvmf_return_$c$cs.h"相对=nofollow>此处。
任何想法,我缺少的是什么呢?
编辑#2
我现在用一个媒体播放器和一个SurfaceView做的全过程伴随着surfaceHolder听众。这里是code:
mMediaPlayer =新的MediaPlayer();
mSurfaceView =(SurfaceView)findViewById(R.id.surface);
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(本);
公共无效surfaceChanged(SurfaceHolder持有人,INT格式,诠释的宽度,高度INT){
Log.d(标签,surfaceChanged);
尝试 {
mMediaPlayer.setDisplay(mHolder);
Log.d(标记7);
mMediaPlayer.start();
Log.d(标签,8);
}赶上(IllegalStateException异常E){
e.printStackTrace();
}
Log.d(标签,9);
}
公共无效surfaceCreated(SurfaceHolder持有者){
Log.d(标签,surfaceCreated);
文件F =新的文件(mAssetsPath);
文件[]文件= f.listFiles();
Log.d(标签,文件:+文件[0]的ToString());
URI URI = URI.create(文件://+(文件[0]的ToString()));
档案文件=新的文件(URI);
尝试 {
Log.d(标记,1);
ParcelFileDescriptor包裹= ParcelFileDescriptor.open(文件,ParcelFileDescriptor.MODE_READ_WRITE);
Log.d(标签,2);
mMediaPlayer.setDataSource(parcel.getFileDescriptor());
Log.d(标签,3);
mMediaPlayer.setVolume(100,100);
Log.d(标签,4);
mMediaPlayer prepare()。
Log.d(标签,5);
}赶上(FileNotFoundException异常E){
e.printStackTrace();
}赶上(抛出:IllegalArgumentException E){
e.printStackTrace();
}赶上(IllegalStateException异常E){
e.printStackTrace();
}赶上(IOException异常E){
e.printStackTrace();
}
Log.d(标签,6);
}
我可以听视频的音频,但画面只是一个简单的黑色。我也得到一个错误几乎是在视频播放结束时,说:
01-31 14:26:01.300:W / AudioSystem(17165):AudioFlinger服务器死了!
01-31 14:26:01.300:W / IMediaDeathNotifier(17165):媒体服务器死亡
01-31 14:26:01.300:E / MediaPlayer的(17165):错误(100,0)
01-31 14:26:01.300:E / MediaPlayer的(17165):错误(100,0)
我使用的是实际的设备,三星Galaxy Tab 10.1。任何想法?
为什么我会根据我发现这这些错误在线是与视频文件的编码问题?
相关错误
由于在自己的进程的媒体播放引擎运行,并且它没有权限读取文件。</ P>
什么是我的情况下使用的最好的东西,一个VideoView或surfaceView?
A VideoView
包含 SurfaceView
。无论您使用 VideoView
或MediaPlayer的组合和 SurfaceView
是由你。
这是加载从应用程序的私有文件夹的视频,并能够发挥它的理想方法?
无论是创建一个能容纳你的本地文件,并使用提供乌里
,而不是的ContentProvider
的乌里
到本地文件,或者创建使用本地文件 openFileOutput()
和 MODE_WORLD_READABLE
。
I have a problem that I have been trying to find a solution for a long time. My situation is as follows:
I have an app that downloads zipped videos and unzips them at the application's private folder and more specifically at a subfolder. For example at /data/data/my.app.package.name.here/files/assets/assets-955.
Inside this folder the video is unzipped. The unzipping process is completed successfully since I can pull and view the video without problems when running the app on the emulator.
I then have another activity that is accessing this folder, finds the video file and tries to open it. At this point I get an error that "Sorry, this video cannot be played" with the following error stack:
01-30 17:36:17.770: D/ContentDemoActivity(6757): File: /data/data/xxxx/files/assets/assets-955/bank_2.mp4
01-30 17:36:17.830: I/MediaPlayer(6757): prepareAsync called in state 4
01-30 17:36:17.830: E/MediaPlayer(6757): error (1, -2147483648)
01-30 17:36:17.860: E/MediaPlayer(6757): Error (1,-2147483648)
01-30 17:36:17.860: D/VideoView(6757): Error: 1,-2147483648
01-30 17:36:19.370: E/MediaPlayer(6757): stop called in state 0
01-30 17:36:19.370: E/MediaPlayer(6757): error (-38, 0)
01-30 17:36:19.370: W/MediaPlayer(6757): mediaplayer went away with unhandled events
The code with which I am trying to play the video is pretty basic:
mView = (VideoView) findViewById(R.id.videoView);
mMediaPlayer = new MediaPlayer();
mView.requestFocus();
mHolder = mView.getHolder();
Log.d(tag, "Populating content. Assets path: " + mAssetsPath);
File f = new File(mAssetsPath);
File[] files = f.listFiles();
Log.d(tag, "File: " + files[0].toString());
mView.setVideoURI(Uri.parse(files[0].toString()));
mView.setMediaController(new MediaController(this));
and the layout of the activity has a plain VideoView, nothing fancy there.
The strangest thing is that for testing purposes I used the same video, this time loading it from the "raw" folder and it runs smoothly without problem. In that case though I had to load it with:
Uri video = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.bank_2);
mVideoView.setVideoURI(video);
mVideoView.start();
I would do the same with the downloaded videos but there doesn't seem to be any function at the API that will allow me to load a video Uri from the application's private folder.
I have found various solutions by using file descriptors, listeners for the videoView, flags indicating MODE_WORLD_READABLE, pre-calculation of the dimensions of the videoView, etc but none of them had positive results.
In a nutshell, my questions are:
- Why do I get those errors which according to what I have found online are errors that are related with problematic encoding of the video file ?
- What is the best things to use in my case, a VideoView or a surfaceView ?
- Which is the ideal method to load a video from the application's private folder and be able to play it?
Thanks.
EDIT
After CommonsWare suggestion, I went with the following implementation:
File f = new File(mAssetsPath);
File[] files = f.listFiles();
Log.d(tag, "File: " + files[0].toString());
URI uri = URI.create("file://" + (files[0].toString()));
File file = new File(uri);
try {
Log.d(tag, "1");
ParcelFileDescriptor parcel = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_WRITE);
Log.d(tag, "2");
mMediaPlayer.setDataSource(parcel.getFileDescriptor());
Log.d(tag, "3");
mMediaPlayer.start();
Log.d(tag, "4");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Log.d(tag, "5");
Unfortunately, this time I get the following errors:
01-31 12:40:11.480: D/ContentDemoActivity(15896): File: /data/data/com.houseofradon.meb/files/assets/assets-955/bank_2.mp4
01-31 12:40:11.480: D/ContentDemoActivity(15896): 1
01-31 12:40:11.480: D/ContentDemoActivity(15896): 2
01-31 12:40:11.500: D/ContentDemoActivity(15896): 3
01-31 12:40:11.500: E/MediaPlayer(15896): start called in state 2
01-31 12:40:11.500: E/MediaPlayer(15896): error (-38, 0)
01-31 12:40:11.500: D/ContentDemoActivity(15896): 4
01-31 12:40:11.500: D/ContentDemoActivity(15896): 5
01-31 12:40:11.530: E/MediaPlayer(15896): Error (-38,0)
So, something happens when the media player starts. Error code -38 doesn't seem to mean anything specific as I found here.
Any idea what I am missing ???
EDIT #2
I now use a mediaPlayer and a SurfaceView to do the whole process along with a surfaceHolder listener. Here is the code:
mMediaPlayer = new MediaPlayer();
mSurfaceView = (SurfaceView) findViewById(R.id.surface);
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.d(tag, "surfaceChanged");
try {
mMediaPlayer.setDisplay(mHolder);
Log.d(tag, "7");
mMediaPlayer.start();
Log.d(tag, "8");
} catch (IllegalStateException e) {
e.printStackTrace();
}
Log.d(tag, "9");
}
public void surfaceCreated(SurfaceHolder holder) {
Log.d(tag, "surfaceCreated");
File f = new File(mAssetsPath);
File[] files = f.listFiles();
Log.d(tag, "File: " + files[0].toString());
URI uri = URI.create("file://" + (files[0].toString()));
File file = new File(uri);
try {
Log.d(tag, "1");
ParcelFileDescriptor parcel = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_WRITE);
Log.d(tag, "2");
mMediaPlayer.setDataSource(parcel.getFileDescriptor());
Log.d(tag, "3");
mMediaPlayer.setVolume(100, 100);
Log.d(tag, "4");
mMediaPlayer.prepare();
Log.d(tag, "5");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Log.d(tag, "6");
}
I can listen to the audio of the video but the picture is just a plain black color. I also get an error almost at the end of the video playback that says:
01-31 14:26:01.300: W/AudioSystem(17165): AudioFlinger server died!
01-31 14:26:01.300: W/IMediaDeathNotifier(17165): media server died
01-31 14:26:01.300: E/MediaPlayer(17165): error (100, 0)
01-31 14:26:01.300: E/MediaPlayer(17165): Error (100,0)
I am using an actual device, Samsung Galaxy Tab 10.1. Any ideas ?
Why do I get those errors which according to what I have found online are errors that are related with problematic encoding of the video file ?
Because the media playback engine runs in its own process, and it does not have rights to read your file.
What is the best things to use in my case, a VideoView or a surfaceView ?
A VideoView
contains a SurfaceView
. Whether you use VideoView
or a combination of MediaPlayer and SurfaceView
is up to you.
Which is the ideal method to load a video from the application's private folder and be able to play it?
Either create a ContentProvider
that can serve up your local file and use the provider Uri
instead of the Uri
to a local file, or create the local file using openFileOutput()
and MODE_WORLD_READABLE
.
这篇关于Android的 - 从应用程序的私有文件夹加载视频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!