我想实现在线视频播放功能并下载它。我的意思是应该使用相同的下载流进行下载和播放,以便保存视频以供离线使用,并防止分别单独播放和下载两倍的数据费用。
到目前为止,我已使用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
中的评论中有一些代码,我试图实现我的目标,但它说&#34;无法播放视频&#34;。
谁知道解决方案?请帮帮我。
答案 0 :(得分:8)
您可以创建将保存流的本地代理。
创建两个后台主题:下载主题和流式主题。
在流媒体广告中创建 ServerSocket 并流式传输刚刚下载的数据。
在VideoView中打开ServerSocket的localhost url。
您需要处理缓冲,同步线程等。
答案 1 :(得分:5)
在Milos Fec
的回答的帮助下,我解决了这个问题。
我必须创建两个用于下载的线程1和用于通过socketServer下载内容的流式传输,同时负责下载的数据和正在播放的数据的同步。
我已将整个代码作为库放在github check here
上