2010-06-14 133 views
18

我正试图为我的用户提供使用外部或内部存储的能力。我正在显示图像和视频(具有科学性)。将介质存储在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(); 
+0

请格式化问题/代码,否则很难阅读。 你会得到什么样的例外?如果你在你的catch子句中记录栈跟踪,这将会有所帮助。 无论如何,你是否找到了从内部存储器播放视频的方法?我正在寻找相同的,并得到一个错误,如“java.io.IOException:准备失败。” – 2010-08-04 09:14:15

+0

我在http://code.google.com/p/android/issues/detail?id=10197 – 2010-08-04 19:54:29

+0

提交了一个错误报告感谢您报告错误。我很久以前就放弃了内部存储。客户的预算不允许我花更多的时间来处理这个问题。 – shellman 2010-09-06 17:16:58

回答

24

MediaPlayer要求正在播放的文件具有世界可读的权限。您可以查看文件的权限与亚行外壳下面的命令:

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

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

注意:为了使用ls命令而不指定文件(位于内部存储器中),您的电话必须扎根。

如果您的手机扎根,你可以在亚行外壳加上世界读取权限使用以下命令:

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

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

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

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

编辑:找到另一个简单的方法here(对于没有固定电话的人很有用)。由于应用程序拥有的文件,它可以创建一个文件描述符并传递到mediaPlayer.setDataSource():

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

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

+0

感谢gtkandroid, 这非常有道理。 (从使用一盒软盘安装操作系统的日子,我是一个旧时代的Linux人)。 由于我们的应用程序已经发布到市场上,并且是一个国家科学基金会资助的项目,旨在覆盖最大的受众群体,我认为坚持使用SD卡存储对我们来说是很好的选择。 干杯, Sid – shellman 2011-03-30 17:12:23

+0

模式WORLD_READABLE使这项工作。 Thanks gtkandroid – FoamyGuy 2011-03-30 20:12:58

+0

@Tim mode WORLD_READABLE非常适用于使用FileOutputStream创建文件,但对于使用MediaRecorder的用户而言,这不是一个选项。 – gtkandroid 2011-04-05 23:32:08

1

我发布了一个自定义的VideoView实现there

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

+0

VideoView有问题..它不能正常工作 – sheetal 2012-07-24 06:17:00

1

我遇到了这个线程与同样的问题,我正在下载我的视频从网络到内部存储,保存时你可以指定RW模式,我。E切换从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(); 
    } 
} 
2

您可以使用:

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

如果该文件是世界可读

或者你可以使用一个内容提供商

1

对于细节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); 
    } 
} 
0

您不能直接播放它。

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