Да, как вы думаете, это проблема в VideoView
, подобные проблемы возникают и в MediaPlayer
, и я сталкивался с такими же и странными проблемами, как и вы, у меня были проблемы, когда видео воспроизводилось только на 3G, а не на Wi- Фи. Обычно это происходит на устройствах 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();
}
Некоторые модификации и адаптации, я думаю, придется сделать для этого кода, и это может быть не лучший подход, но мне он помог, и я не смог найти никакой альтернативы.
person
Ovidiu Latcu
schedule
15.02.2012