2010-06-14 50 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)方法。

相關問題