我想实现在线视频播放功能以及下载它。我的意思是,下载和播放应该使用相同的下载流,这样可以保存视频以供离线使用,并防止单独播放和下载的两倍数据成本。
到目前为止,我已经用asyncTask实现了视频下载,并在OnPostExecute上播放。代码如下:
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的注释中有一行代码,我试图实现我的目标,但它显示“无法播放视频”。有人知道解决方案吗?请帮帮我。
发布于 2017-05-17 15:46:33
在Milos Fec回答的帮助下,我解决了这个问题。我不得不创建两个线程,一个用于下载,另一个用于通过socketServer流式传输下载的内容,同时还要注意下载的数据和正在播放的数据的同步。
我已经将整个代码作为一个库放到了github check here上。
EDIT:这个库不能处理所有类型的视频,在这些类型的视频中,视频服务器通过将视频分成块来限制下载,诸如此类。
我只用mp4测试过它。这个库需要一个公共链接。
我在Android开发的早期就做过这方面的工作,只是为了学习本地服务器和远程服务器之间的同步。在这个库中有很大的改进空间,我没有做任何事情,因为有其他选项可以满足相同的要求,而我也没有从其他东西中获得足够的时间。
发布于 2016-01-08 22:58:54
您可以创建将保存流的本地代理。
创建两个后台线程:下载线程和流式线程。
在streaming线程中,创建ServerSocket并流式传输刚刚下载的数据。
在VideoView中,打开ServerSocket的本地主机url。
你将需要处理缓冲,同步线程等。
https://stackoverflow.com/questions/34371224
复制相似问题