ユーザーに外部ストレージまたは内部ストレージのいずれかを使用する機能を提供しようとしています。私は(科学的な性質の)画像とビデオの両方を表示しています。メディアをSDカードに保存する場合は、すべて問題ありません。しかし、メディアを内部に保存すると、画像のみが表示されます。何をしようとしても、applicationcontext.getFilesDir()の下に保存されているメディアをロードして表示しようとすると、さまざまなエラーが発生します。
ビデオビューのコンテンツをそのようなファイルに設定するコツはありますか?
ContentResolverは私を助けることができますか?
関連する注記として、外部ストレージが存在すると想定することは悪い形式と見なされますか?
前もって感謝します、
シド
以下は、「ビデオを再生できません。申し訳ありませんが、このビデオを再生できません」で失敗するバージョンの1つです。しかし、私には他にも多くの失敗モードがあります。内部ビデオを一時ストレージ(外部)にコピーして再生できるので、この内部ビデオのコピーは確かに有効なムービーを作成します。内部ストレージから直接再生しようとすると失敗するだけです。
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();
MediaPlayerでは、再生するファイルに誰でも読み取り可能な権限が必要です。 adb Shellで次のコマンドを使用して、ファイルのアクセス許可を表示できます。
ls -al /data/data/com.mypackage/myfile
おそらく「-rw ------」が表示されます。これは、所有者(MediaPlayerではなくアプリ)のみが読み取り/書き込み権限を持っていることを意味します。
注:(内部メモリ内の)ファイルを指定せずにlsコマンドを使用するには、電話機をルート化する必要があります。
お使いの携帯電話がルート化されている場合は、次のコマンドを使用して、adbシェルにワールド読み取り権限を追加できます。
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 を参照してください。
編集:別の簡単なアプローチを見つけました ここ (root化された電話を持たない人に便利です)。アプリケーションはファイルを所有しているため、ファイル記述子を作成してそれをmediaPlayer.setDataSource()に渡すことができます。
FileInputStream fileInputStream = new FileInputStream("/data/data/com.mypackage/myfile");
mediaPlayer.setDataSource(fileInputStream.getFD());
このアプローチは、許可の問題を完全に回避します。
次を使用できます。
videoView.setVideoURI(Uri.parse(file.getAbsolutePath()));
ファイルが誰でも読み取り可能かどうか
または、コンテンツプロバイダーを使用できます
詳細については このチュートリアルを確認してください
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);
}
}
カスタムVideoView実装を投稿しました そこに 。
VideoViewの実装にはsetVideoFD(FileDescriptor fd)
メソッドがあり、この問題を解決します。
同じ問題でこのスレッドに遭遇しました。ビデオをWebから内部ストレージにダウンロードしています。保存すると、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();
}
}
直接プレイすることはできません。
ContentProviderを実装してから、定義済みのURIをsetVideoUri(uri)メソッドに渡す必要があります。