流式传输到VideoView只能在使用三星手机时在Wifi上播放

Oh *_*Boy 12 streaming android android-videoview

我使用以下库将YouTube视频流式传输到Android应用程序.

http://code.google.com/p/android-youtube-player/source/browse/trunk/OpenYouTubeActivity/src/com/keyes/youtube/OpenYouTubePlayerActivity.java?r=3

我成功地通过3G和Wifi在HTC和摩托罗拉手机上播放视频.但是,在三星Galaxy(Epic 4G)和三星Galaxy II手机上,我只能使用Wifi播放.3G给了我这个错误:"无法播放视频.抱歉,此视频无法播放."

我尝试过强制低质量的YouTube流媒体,但这并没有帮助.我在日志中看到Start()两种情况都被调用(3G/Wifi).这是VideoView的问题吗?有解决方法吗?

编辑2

这些视频来自YouTube API.我尝试使用嵌入式和普通流,以及可用的最低质量流(每个视频不同).此外,我不认为这是一个编码问题,因为相同的视频使用Wifi正确播放.

编辑1

无论使用Wifi还是不使用3G,我都会收到以下输出.

01-30 15:22:38.305: E/MediaPlayer(3831): error (1, -1)
01-30 15:22:38.305: E/MediaPlayer(3831): callback application
01-30 15:22:38.305: E/MediaPlayer(3831): back from callback
01-30 15:22:38.309: E/MediaPlayer(3831): Error (1,-1)
Run Code Online (Sandbox Code Playgroud)

根据这个链接,这些错误意味着以下(我认为):

/*
 Definition of first error event in range (not an actual error code).
 */
const PVMFStatus PVMFErrFirst = (-1);
/*
 Return code for general failure
 */
const PVMFStatus PVMFFailure = (-1);
/*

/*
 Return code for general success
 */
const PVMFStatus PVMFSuccess = 1;
/*
Run Code Online (Sandbox Code Playgroud)

进一步增加了混乱.

Ovi*_*tcu 4

是的,正如您所想,这是 中的一个问题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
     }
}
Run Code Online (Sandbox Code Playgroud)

所以这是最简单的部分,检测正在运行的设备在流式传输视频时是否存在问题。现在,我所做的(也可能对您有所帮助)是将来自 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

}
Run Code Online (Sandbox Code Playgroud)

最后,GetYoutubeFile线程当然是在onCreate()方法中启动的:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //init views,player,etc
    new GetYoutubeFile().start();
}
Run Code Online (Sandbox Code Playgroud)

我认为必须对这段代码进行一些修改和改编,这可能不是最好的方法,但它对我有帮助,而且我找不到任何替代方法。