Может ли видеовидео воспроизводить видео, хранящееся на внутреннем хранилище?
Я пытаюсь предоставить своим пользователям возможность использовать внешнее или внутреннее хранилище. Я показываю как изображения, так и видео (научного характера). При хранении носителя на 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();
Ответы
Ответ 1
MediaPlayer требует, чтобы файл, который был воспроизведен, имеет доступные для чтения разрешения. Вы можете просмотреть разрешения файла со следующей командой в оболочке adb:
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.
EDIT: нашел еще один простой подход здесь (полезно для тех, у кого нет корневых телефонов). Поскольку приложение владеет файлом, оно может создать дескриптор файла и передать его в mediaPlayer.setDataSource():
FileInputStream fileInputStream = new FileInputStream("/data/data/com.mypackage/myfile");
mediaPlayer.setDataSource(fileInputStream.getFD());
Этот подход полностью исключает проблему разрешения.
Ответ 2
Вы можете использовать:
videoView.setVideoURI(Uri.parse(file.getAbsolutePath()));
если файл доступен для чтения в мире
Или вы можете использовать поставщика контента
Ответ 3
Я разместил пользовательскую реализацию VideoView там.
Реализация VideoView имеет метод setVideoFD(FileDescriptor fd)
и решает эту проблему.
Ответ 4
Я столкнулся с этим вопросом с той же проблемой, я загружаю свои видео из Интернета во внутреннее хранилище, получается при сохранении, вы можете указать режим 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();
}
}
Ответ 5
Подробнее проверить этот учебник
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);
}
}
Ответ 6
Вы не можете просто воспроизвести его напрямую.
Вам необходимо реализовать ContentProvider, а затем передать определенный метод Uri to setVideoUri (uri).