2013-10-14 4 views
0

Мне нужно, чтобы приложение Android могло воспроизводить видео с момента времени t1 в другое время t2. В принципе, это видео - это своего рода «спрайт» в моем приложении (это кодировка с базовым уровнем видео в формате .mp4 h264).Воспроизведение видео между двумя раз в Android

Итак, я попробовал следующее. Кнопка «следующая» воспроизводит видео между t1 и t2. Чтобы проверить, прибыло ли видео в t2, я использую обработчик с вызовом postDelayed каждые 20 мс. Если текущее положение видео больше, чем t2, я останавливаю видео. В противном случае я снова проверю через 20 мс.

Но это не работает. По какой-то причине я не понимаю, текущая позиция видео, которую я читал в postDelayed, внезапно происходит от времени до нескольких секунд. На моем экране видео воспроизводится нормально.

Некоторый код:

// MainActivity 
// setting up the video 
vidView = (VideoView) findViewById(R.id.myVid); 
vidView.setVideoURI(Uri.parse("android.resource://" + getPackageName() + "/raw/myvid"));  

// wiring up Bt next  
Button nextBt = (Button) findViewById(R.id.next); 
nextBt.setOnClickListener(new View.OnClickListener() { 

    @Override 
    public void onClick(View v) { 
      playVideo(); 
    } 
}); 

И метод playVideo:

private void playVideo() { 

    // t1 and t2 are defined within MainActivity class 
t1 = (int) (Math.random() * (80000)); 
t2 = t1 + (int) (Math.random() * (5000)); 

    // we start at t1 
vidView.seekTo(t1); 

// We check video position in 20 ms 
mHandler.postDelayed(new Runnable() { 
    public void run() { 

     int currentTime = vidView.getCurrentPosition(); 

     Log.i("currentTime", String.valueOf(currentTime)); 
     Log.i("T2", String.valueOf(t2)); 

     // Ok, we can pause the video 
     if(currentTime > t2 - 20) { 

      vidView.pause();   

     } 
     // We check again in 20ms 
     else { 
      mHandler.postDelayed(this, 20); 
     } 
    } 
}, 20); 
vidView.start(); 

} 

LogCat дает мне (в данном примере, T1 = 47286 и T2 = 51478)

10-14 11:31:56.603: I/currentTime(3359): 47286 // first call to postDelayed, fine 
10-14 11:31:56.603: I/T2(3359): 51478 

10-14 11:31:56.623: I/currentTime(3359): 47286 // second call to postDelayed, still ok 
10-14 11:31:56.623: I/T2(3359): 51478 

10-14 11:31:56.653: I/currentTime(3359): 50000 // What? How the video current time can already be 3 seconds later? 
10-14 11:31:56.653: I/T2(3359): 51478 

Можете ли вы рассказать мне, что не так с моим кодом? Спасибо!

ответ

0

Вместо того, чтобы постоянно проверять, почему вы просто не устанавливаете обработчик, чтобы остановить его в определенное позднее время? Вам не нужно проверять, было ли это «прибыло» на T2 - вы знаете, когда хотите остановить его, поэтому просто планируйте его остановить.

Runnable stopVideoTask = new Runnable(){ 
    @Override 
    public void run() { 
     vidView.pause(); 
    } 
}; 

int t2 = (int) (Math.random() * 5000); 
vidView.seekTo(t1); 
vidView.start(); 
mHandler.postDelayed(stopVideoTask, t2); 

видео остановится после Math.random() * 5000 секунд игры.

+0

Я хочу, чтобы это было как можно точнее. Проблема с вашей идеей заключается в том, что видео требуется время, чтобы достичь своей точки поиска, а также начать играть. Эти времена зависят от устройства и видеокодирования. Я решил сделать проверку каждые 20 мс (не во время воспроизведения всего видео, а в последнюю секунду воспроизведения) было бы более точным. – JuCachalot

+0

Добавьте «onPreparedListener» к видео и опубликуйте только обработчик 'onPrepared' - это устранит проблему с запуском. 'getCurrentPosition' не гарантируется быть точным и, безусловно, называть его каждые 20 мс, кажется мне плохой идеей. –

+0

Я пробовал вашу идею, но она по-прежнему не работает, как мне бы хотелось. Я использовал «MediaPlayer» + «SufaceView», чтобы иметь возможность отправлять обработчик события 'onSeekComplete'. В основном это работает, но это недостаточно точно: видео приостановлено с ошибкой времени между 200 и 1500 мс. – JuCachalot

Смежные вопросы