首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >下载视频并播放

下载视频并播放
EN

Stack Overflow用户
提问于 2015-12-19 21:18:19
回答 2查看 10.3K关注 0票数 13

我想实现在线视频播放功能以及下载它。我的意思是,下载和播放应该使用相同的下载流,这样可以保存视频以供离线使用,并防止单独播放和下载的两倍数据成本。

到目前为止,我已经用asyncTask实现了视频下载,并在OnPostExecute上播放。代码如下:

代码语言:javascript
复制
public class MainActivity extends AppCompatActivity {


private Button btnPlay;
private MediaPlayer player;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    outFilePath = getExternalFilesDir("/") + "/video.mp4";
    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });

    prepareVideoView();

}

private VideoView videoView;
String videoPath = "http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_5mb.mp4";
String outFilePath = "";//

private void prepareVideoView() {
    MediaController mediaController = new MediaController(this);
    videoView = (VideoView) findViewById(R.id.videoView);
    mediaController.setAnchorView(videoView);
    videoView.setMediaController(mediaController);
    btnPlay = (Button) findViewById(R.id.btnPlayVideo);
    btnPlay.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            new VideoDownloader().execute(videoPath);
        }
    });

    videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(MediaPlayer mp) {
            player = mp;

            player.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
                @Override
                public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
                    Log.w("download","size changed");
                }
            });
        }
    });
}
File outFile;
class VideoDownloader extends AsyncTask<String, Integer, Void> {

    @Override
    protected Void doInBackground(String... params) {


        outFile = new File(outFilePath);
        FileOutputStream out = null;
        BufferedInputStream input = null;
        try {
            out = new FileOutputStream(outFile,true);

            try {
                URL url = new URL(videoPath);

                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.connect();
                if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
                    throw new RuntimeException("response is not http_ok");
                }
                int fileLength = connection.getContentLength();

                input = new BufferedInputStream(connection.getInputStream());
                byte data[] = new byte[2048];
                long readBytes = 0;
                int len;
                boolean flag = true;
                int readb = 0;
                while ((len = input.read(data)) != -1) {
                    out.write(data,0,len);
                    readBytes += len;
   // Following commented code is to play video along with downloading but not working.
/*                      readb += len;
                    if(readb > 1000000)
                    {
                        out.flush();
                        playVideo();
                        readb = 0;
                    }
*/
                    Log.w("download",(readBytes/1024)+"kb of "+(fileLength/1024)+"kb");
                }



            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (out != null)
                    out.flush();
                    out.close();
                if(input != null)
                    input.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        Log.w("download", "Done");
       playVideo();

    }
}

private void playVideo() {

    videoView.setVideoPath(outFile.getAbsolutePath());
    videoView.start();
}
}

上面的代码可以正常下载并播放。在DoInBackground的注释中有一行代码,我试图实现我的目标,但它显示“无法播放视频”。有人知道解决方案吗?请帮帮我。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-05-17 15:46:33

Milos Fec回答的帮助下,我解决了这个问题。我不得不创建两个线程,一个用于下载,另一个用于通过socketServer流式传输下载的内容,同时还要注意下载的数据和正在播放的数据的同步。

我已经将整个代码作为一个库放到了github check here上。

EDIT:这个库不能处理所有类型的视频,在这些类型的视频中,视频服务器通过将视频分成块来限制下载,诸如此类。

我只用mp4测试过它。这个库需要一个公共链接。

我在Android开发的早期就做过这方面的工作,只是为了学习本地服务器和远程服务器之间的同步。在这个库中有很大的改进空间,我没有做任何事情,因为有其他选项可以满足相同的要求,而我也没有从其他东西中获得足够的时间。

票数 6
EN

Stack Overflow用户

发布于 2016-01-08 22:58:54

您可以创建将保存流的本地代理。

创建两个后台线程:下载线程流式线程

streaming线程中,创建ServerSocket并流式传输刚刚下载的数据。

在VideoView中,打开ServerSocket的本地主机url。

你将需要处理缓冲,同步线程等。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34371224

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档