Может ли videoview воспроизводить видео, хранящееся во внутренней памяти? - PullRequest
19 голосов
/ 14 июня 2010

Я пытаюсь предоставить своим пользователям возможность использовать внешнее или внутреннее хранилище. Я показываю изображения и видео (научного характера). При хранении носителя на SD-карте все нормально. Но когда я храню носитель внутри, будут отображаться только изображения. Независимо от того, что я пытаюсь, я получаю различные ошибки при попытке загрузить и отобразить мультимедиа, хранящиеся в applicationcontext.getFilesDir ().

Есть ли хитрость для установки содержимого видеовиде в такой файл?

Может ли ContentResolver помочь мне?

На связанной ноте, считается ли плохим тоном предполагать, что внешнее хранилище существует?

Заранее спасибо,

Sid

Ниже приведена одна версия, которая дает сбой с «Не удается воспроизвести видео. Извините, это видео не может быть воспроизведено». Но у меня есть много других способов отказа. Я могу скопировать внутреннее видео во временное хранилище (внешнее) и воспроизвести его, поэтому эта копия во внутреннее видео действительно создает действительный фильм. Сбой возможен только при попытке воспроизвести его прямо из внутреннего хранилища.

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();

Ответы [ 6 ]

25 голосов
/ 29 марта 2011

MediaPlayer требует, чтобы воспроизводимый файл имел права на чтение для всех.Вы можете просмотреть права доступа к файлу с помощью следующей команды в оболочке adb:

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

Вы, вероятно, увидите «-rw ------», что означает, что только владелец (ваше приложение,не MediaPlayer) имеет права на чтение / запись.

Примечание. Чтобы использовать команду ls без указания файла (во внутренней памяти), ваш телефон должен быть рутован.

Если ваш телефонroot, вы можете добавить права на чтение в оболочке adb с помощью следующей команды:

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

Если вам нужно программно изменить эти разрешения (требуется рутированный телефон!), вы можете использовать следующую команду в своем приложениикод:

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

Это в основном команда linux.См. https://help.ubuntu.com/community/FilePermissions для получения дополнительной информации о chmod.

РЕДАКТИРОВАТЬ: нашел другой простой подход здесь (полезно для тех, у кого нет рутованных телефонов).Поскольку приложению принадлежит файл, оно может создать дескриптор файла и передать его в mediaPlayer.setDataSource ():

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

Этот подход полностью исключает проблему с разрешениями.

2 голосов
/ 06 января 2015

Подробнее проверить этот урок

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);
    }
}
2 голосов
/ 10 июля 2012

Вы можете использовать:

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

, если файл доступен для чтения всем пользователям

Или вы можете использовать контент-провайдер

1 голос
/ 26 апреля 2012

Я сталкивался с этой темой с той же проблемой, я загружаю свои видео из Интернета во внутреннее хранилище, оказывается при сохранении можно указать режим 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();
    }
}
1 голос
/ 11 ноября 2011

Я разместил пользовательскую реализацию VideoView там .

Реализация VideoView имеет метод setVideoFD(FileDescriptor fd) и решает эту проблему.

0 голосов
/ 09 июня 2016

Вы не можете просто воспроизвести его напрямую.

Вам необходимо реализовать ContentProvider, а затем передать определенный Uri в метод setVideoUri (uri).

...