Да, как вы думаете, это проблема в VideoView
, аналогичные проблемы также появляются в MediaPlayer
, и я столкнулся с похожими и странными проблемами, как и у вас, у меня были проблемы только при воспроизведении видео на 3G, а не на Wi-Fi. Обычно это происходит на устройствах 2.1 и некоторых 2.2, но не на более высоких уровнях API, как я видел до сих пор.
Так что я могу порекомендовать сделать следующее:
Сначала проверьте, может ли работающее устройство иметь проблемы, например:
//Define a static list of known devices with issues
static List sIssueDevices=Arrays.asList(new String[]{"HTC Desire","LG-P500","etc"});
if(Build.VERSION.SDK_INT<9){
if(sIssueDevices.contains(Build.Device){
//This device may have issue in streaming, take appropriate actions
}
}
Так что это была самая простая часть, чтобы определить, могут ли работающее устройство иметь проблемы при потоковой передаче видео. Теперь то, что я сделал и, возможно, также помогу вам, это скопировать видео с Youtube в файл на SDCard
и установить этот файл как source
для вашего VideoView
. Я напишу несколько фрагментов кода, чтобы увидеть, как мой подход был:
private class GetYoutubeFile extends Thread{
private String mUrl;
private String mFile;
public GetYotubeFile(String url,String file){
mUrl=url;
mFile=file;
}
@Override
public void run() {
super.run();
try {
File bufferingDir=new File(Environment.getExternalStorageDirectory()
+"/YoutubeBuff");
File bufferFile=new File(bufferingDir.getAbsolutePath(), mFile);
//bufferFile.createNewFile();
BufferedOutputStream bufferOS=new BufferedOutputStream(
new FileOutputStream(bufferFile));
URL url=new URL(mUrl);
URLConnection connection=url.openConnection();
connection.setRequestProperty("User-Agent", "Mozilla");
connection.connect();
InputStream is=connection.getInputStream();
BufferedInputStream bis=new BufferedInputStream(is,2048);
byte[] buffer = new byte[16384];
int numRead;
boolean started=false;
while ((numRead = bis.read(buffer)) != -1 && !mActivityStopped) {
//Log.i("Buffering","Read :"+numRead);
bufferOS.write(buffer, 0, numRead);
bufferOS.flush();
mBuffPosition += numRead;
if(mBuffPosition>120000 &&!started){
Log.e("Player","BufferHIT:StartPlay");
setSourceAndStartPlay(bufferFile);
started=true;
}
}
Log.i("Buffering","Read -1?"+numRead+" stop:"+mActivityStopped);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void setSourceAndStartPlay(File bufferFile) {
try {
mPlayer.setVideoPath(bufferFile.getAbsolutePath());
mPlayer.prepare();
mPlayer.start();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Другая проблема возникнет, когда VideoView
перестанет воспроизводиться до конца файла, поскольку в файле недостаточно буферизовано. Для этого вам нужно установить onCompletionListener()
и, если вы не в конце видео, вы должны снова начать воспроизведение видео с последней позиции:
public void onCompletion(MediaPlayer mp) {
mPlayerPosition=mPlayer.getCurrentPosition();
try {
mPlayer.reset();
mPlayer.setVideoPath(
new File("mnt/sdcard/YoutubeBuff/"+mBufferFile).getAbsolutePath());
mPlayer.seekTo(mPlayerPosition);
mPlayer.start();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
В конце, конечно, поток GetYoutubeFile
запускается в методе onCreate()
:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//init views,player,etc
new GetYoutubeFile().start();
}
Некоторые модификации и адаптации, я думаю, должны быть сделаны для этого кода, и, возможно, это не лучший подход, но он помог мне, и я не смог найти никакой альтернативы.