public class DownLoadVideo {
private static final String TAG = "DownLoadVideo↓↓↓↓↓↓↓↓↓↓↓↓↓↓";
private static ExecutorService executorService = Executors.newFixedThreadPool(6);//线程池,每次最多6个线程同时运行
public synchronized static boolean downLoadVideo(Context context,String fileName,String downloadUrl){
Log.i(TAG, "start download");
File videoFile = XDMFiles.videoFile(context);//下载文件所放目录
new AsyncLoadFile(context,videoFile).execute(fileName,downloadUrl);
return true ;
}
/** 下载 **/
private static class AsyncLoadFile extends AsyncTask<String,Void,Boolean>{
private Context context ;
private File file ;
private String downName ;
private String downloadUrl ;
private File localFileName ;
public AsyncLoadFile(Context _context,File _file){
this.context = _context ;
this.file = _file ;
}
@Override
protected Boolean doInBackground(String... params) {
Log.d(TAG,params[0]);
downName = params[0];
downloadUrl = params[1];
try {
// 构造URL
URL url = new URL(downloadUrl);
// 打开连接
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.setConnectTimeout(15 * 1000);
con.setRequestProperty("Connection", "Keep-Alive");
con.setRequestProperty("Charset", "UTF-8");
//获得文件的长度
long contentLength = con.getContentLength();
Log.d(TAG+"downloadLength:",contentLength+"");
Log.d(TAG,"videoDownloadPath-"+downloadUrl);
localFileName = new File(file,downName);
if(!localFileName.exists()) localFileName.createNewFile();
Log.d(TAG, "videoLocalAddress-" + downloadUrl);
checkFileSize(localFileName,contentLength,context);
RandomAccessFile file = new RandomAccessFile(localFileName.getAbsolutePath(),"rwd");
file.setLength(contentLength);//设置本地文件的长度
long partLength = 1024*1024*6 ;//每个线程下载文件的长度为6M,最后一个不满6M
int threadNumber = (int) ((contentLength/partLength) +1);
DownLoadRunnable tasks[] = new DownLoadRunnable[threadNumber];
for(int i=0 ;i<threadNumber;i++){
tasks[i] = new DownLoadRunnable(downloadUrl,localFileName,partLength,i+1,contentLength);
executorService.submit(tasks[i]);
}
executorService.submit(new Runnable() {
private boolean finished = false;
@Override
public void run() {
while (!finished){
int finishedNumber = 0 ;
for(int i=0 ;i<threadNumber;i++){
if(tasks[i].isFinished()){
finishedNumber++;
Log.i(TAG,"download is finished"+"--"+finishedNumber);
}
if(finishedNumber == threadNumber){
finished=true ;
Video video = new Video();
video.setVideoName(downName);
video.setVideoURL(downloadUrl);
video.setVideoLocalAddress(localFileName.toString());
DBHelpers dbHelpers = new DBHelpers(context);
dbHelpers.saveVideo(video);
Log.i(TAG,"download is finished,it is over!");
executorService.shutdown();
}
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});//判断问下是否下载完毕,下载完毕后把文件的所属信息写入数据库
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
@Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
}
}
/***
* 检查内存是否够用
* @param file
* @param videoSize
* @param context
*/
public static void checkFileSize(File file,long videoSize,Context context){
if(FileSizeUtil.formatFileSizeM(FileSizeUtil.getFileAvailableExternalMemorySize(file.getPath())-videoSize)<50){
DBHelpers db = new DBHelpers(context);
ArrayList<Video> list = (ArrayList<Video>) db.findAllVideo();
Video video = list.get(0);
for(int i=1 ;i<list.size();i++){
if(list.get(i).getTime()<video.getTime()) video = list.get(i);
}
String localAddress = video.getVideoLocalAddress();
if(localAddress != null){
File files = new File(localAddress);
files.delete();
db.delVideo(video.getVideoName());
}
checkFileSize(file,videoSize,context);
}
}
/***
* 开始下载每段文件
*/
private static class DownLoadRunnable implements Runnable {
private String downloadUrl ;
private long partLength ;
private File file ;
private int part ;
private long contentLength ;
private boolean finished = false ;
private BufferedInputStream bis = null;
private RandomAccessFile raf = null;
public DownLoadRunnable(String _downloadUrl,File _file ,long _partLength ,int _part,long _contentLength){
this.downloadUrl = _downloadUrl;
this.partLength = _partLength ;
this.file = _file ;
this.part = _part ;
this.contentLength = _contentLength ;
}
public boolean isFinished(){
return finished ;
}
@Override
public void run() {
try {
Log.i(TAG,"start download part---" + Thread.currentThread().getName());
URL url = new URL(downloadUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setAllowUserInteraction(true);
conn.setRequestMethod("GET");
conn.setConnectTimeout(15 * 1000);
conn.setReadTimeout(30000 * 1000);
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Charset", "UTF-8");
conn.setRequestProperty("Accept-Encoding", "gzip, deflate");
//设置当前线程下载的起点、终点
long startPos = partLength * (part - 1);//开始位置
long endPos ;
if((contentLength/partLength)+1 == part){
endPos = contentLength ;
}else {
endPos = part * partLength - 1;//结束位置
}
conn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos);
Log.d(TAG,Thread.currentThread().getName() + "partLength-"+partLength + ";start-" + startPos + ";end-" + endPos);
conn.connect();
int size = 8192 ;
byte[] buffer = new byte[size];
bis = new BufferedInputStream(conn.getInputStream());
raf = new RandomAccessFile(file.getAbsolutePath(), "rwd");
raf.seek(startPos);
int len;
int localFileLength = 0 ;
while ((len = bis.read(buffer, 0, size)) != -1) {
raf.write(buffer, 0, len);
localFileLength += len;
}
Log.i(TAG, "end---"+Thread.currentThread().getName()+":"+localFileLength+":"+len+":"+startPos+":"+endPos + ":" + raf.length());
bis.close();
raf.close();
finished = true ;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}