我希望能够实现在线视频播放功能以及下载。我的意思是,应该使用相同的下载流来下载和播放视频,以便视频可以保存以供离线使用,并避免分别播放和下载时的两倍数据成本。
到目前为止,我已经使用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
中有一些被注释掉的代码行,我试图通过它来实现我的目标,但它显示“无法播放视频”。
有人知道解决方法吗?请帮帮我。
playVideo()
方法使用带有setVideoPath()
的文件。换句话说,playVideo()
仅适用于磁盘上完全下载的视频。你需要将单个帧和音频传递给媒体播放器进行流式传输,然后在查看后将这些字节简单地传递到文件中以进行缓存以供离线使用。 - MeetTitan