多線程下載apk在網(wǎng)上有很多的例子,我們可以找到很多,在這里我提供一種例子來實現(xiàn)更新版本apk
首先添加網(wǎng)絡(luò)權(quán)限;
下面寫個net包
新建FileDownloadThread類
package com.example.zhoukao_zidingyiyuan_moredownload.net;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.URL;
import java.net.URLConnection;
/**
* 作者:author
* 時間 :
* 說明:
*/
public class FileDownloadThread extends Thread {
private static final String TAG = FileDownloadThread.class.getSimpleName();
/** 當(dāng)前下載是否完成 */
private boolean isCompleted = false;
/** 當(dāng)前下載文件長度 */
private int downloadLength = 0;
/** 文件保存路徑 */
private File file;
/** 文件下載路徑 */
private URL downloadUrl;
/** 當(dāng)前下載線程ID */
private int threadId;
/** 線程下載數(shù)據(jù)長度 */
private int blockSize;
/**
*
* @param url:文件下載地址
* @param file:文件保存路徑
* @param blocksize:下載數(shù)據(jù)長度
* @param threadId:線程ID
*/
public FileDownloadThread(URL downloadUrl, File file, int blocksize,
int threadId) {
this.downloadUrl = downloadUrl;
this.file = file;
this.threadId = threadId;
this.blockSize = blocksize;
}
@Override
public void run() {
BufferedInputStream bis = null;
RandomAccessFile raf = null;
try {
URLConnection conn = downloadUrl.openConnection();
conn.setAllowUserInteraction(true);
int startPos = blockSize * (threadId - 1);//開始位置
int endPos = blockSize * threadId - 1;//結(jié)束位置
//設(shè)置當(dāng)前線程下載的起點、終點
conn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos);
System.out.println(Thread.currentThread().getName() + " bytes="
+ startPos + "-" + endPos);
byte[] buffer = new byte[1024];
bis = new BufferedInputStream(conn.getInputStream());
raf = new RandomAccessFile(file, "rwd");
raf.seek(startPos);
int len;
while ((len = bis.read(buffer, 0, 1024)) != -1) {
raf.write(buffer, 0, len);
downloadLength += len;
}
isCompleted = true;
Log.d(TAG, "current thread task has finished,all size:"
+ downloadLength);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (raf != null) {
try {
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 線程文件是否下載完畢
*/
public boolean isCompleted() {
return isCompleted;
}
/**
* 線程下載文件長度
*/
public int getDownloadLength() {
return downloadLength;
}
}
通過接口回調(diào)在Activity里面點擊條目跳轉(zhuǎn)到另一個Activity(跳轉(zhuǎn)時intent傳 視頻的網(wǎng)址接口)
RvAdapter rvAdapter = new RvAdapter(MoreActivity.this, list);
mRv.setAdapter(rvAdapter);
rvAdapter.setOnItemClickListener(new RvAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int positon) {
String urlmovie = list.get(positon).getVedio_url();
Toast.makeText(MoreActivity.this,urlmovie,Toast.LENGTH_SHORT).show();
Intent intent = new Intent(MoreActivity.this,DownloadActivity.class);
intent.putExtra("urlmovie",urlmovie);
Log.i("------", "onItemClick: "+urlmovie);
startActivity(intent);
}
});
DownloadActivity
package com.example.zhoukao_zidingyiyuan_moredownload;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.MediaController;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.VideoView;
import com.example.zhoukao_zidingyiyuan_moredownload.net.FileDownloadThread;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import butterknife.BindView;
import butterknife.ButterKnife;
public class DownloadActivity extends AppCompatActivity implements View.OnClickListener{
private static final String TAG = DownloadActivity.class.getSimpleName();
@BindView(R.id.download_btn)
Button downloadBtn;
@BindView(R.id.download_progress)
ProgressBar downloadProgress;
@BindView(R.id.download_message)
TextView downloadMessage;
@BindView(R.id.other_vdv)
VideoView otherVdv;
private TextView mMessageView;
/**
* 顯示下載進(jìn)度ProgressBar
*/
private ProgressBar mProgressbar;
private String name;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_download);
ButterKnife.bind(this);
Intent intent = getIntent();
//傳值
name = intent.getStringExtra("urlmovie");
Log.i("name***", "onCreate: "+name);
findViewById(R.id.download_btn).setOnClickListener(this);
mMessageView = (TextView) findViewById(R.id.download_message);
mProgressbar = (ProgressBar) findViewById(R.id.download_progress);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.download_btn) {
Toast.makeText(DownloadActivity.this,"onclick",Toast.LENGTH_SHORT).show();
doDownload();
}
}
/**
* 使用Handler更新UI界面信息
*/
@SuppressLint("HandlerLeak")
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
mProgressbar.setProgress(msg.getData().getInt("size"));
float temp = (float) mProgressbar.getProgress()
/ (float) mProgressbar.getMax();
int progress = (int) (temp * 100);
if (progress == 100) {
Toast.makeText(DownloadActivity.this, "下載完成!", Toast.LENGTH_LONG).show();
MediaController media= new MediaController(DownloadActivity.this);
Uri uri = Uri.parse(name);
otherVdv.setVideoURI(uri);
otherVdv.setMediaController(media);
otherVdv.start();
}
mMessageView.setText("下載進(jìn)度:" + progress + " %");
}
};
/**
* 下載準(zhǔn)備工作,獲取SD卡路徑、開啟線程
*/
private void doDownload() {
// 獲取SD卡路徑
String path = Environment.getExternalStorageDirectory()
+ "/amosdownload/";
File file = new File(path);
// 如果SD卡目錄不存在創(chuàng)建
if (!file.exists()) {
file.mkdir();
}
// 設(shè)置progressBar初始化
mProgressbar.setProgress(0);
// 簡單起見,我先把URL和文件名稱寫死,其實這些都可以通過HttpHeader獲取到
String downloadUrl = name;
String fileName = "shipin.mp4";
int threadNum = 5;
String filepath = path + fileName;
Log.d(TAG, "download file path:" + filepath);
downloadTask task = new downloadTask(downloadUrl, threadNum, filepath);
task.start();
}
/**
* 多線程文件下載
*
* @author yangxiaolong
* @2014-8-7
*/
class downloadTask extends Thread {
private String downloadUrl;// 下載鏈接地址
private int threadNum;// 開啟的線程數(shù)
private String filePath;// 保存文件路徑地址
private int blockSize;// 每一個線程的下載量
public downloadTask(String downloadUrl, int threadNum, String fileptah) {
this.downloadUrl = downloadUrl;
this.threadNum = threadNum;
this.filePath = fileptah;
}
@Override
public void run() {
FileDownloadThread[] threads = new FileDownloadThread[threadNum];
try {
URL url = new URL(downloadUrl);
Log.d(TAG, "download file http path:" + downloadUrl);
URLConnection conn = url.openConnection();
// 讀取下載文件總大小
int fileSize = conn.getContentLength();
if (fileSize <= 0) {
System.out.println("讀取文件失敗");
return;
}
// 設(shè)置ProgressBar最大的長度為文件Size
mProgressbar.setMax(fileSize);
// 計算每條線程下載的數(shù)據(jù)長度
blockSize = (fileSize % threadNum) == 0 ? fileSize / threadNum
: fileSize / threadNum + 1;
Log.d(TAG, "fileSize:" + fileSize + " blockSize:" + blockSize);
File file = new File(filePath);
for (int i = 0; i < threads.length; i++) {
// 啟動線程,分別下載每個線程需要下載的部分
threads[i] = new FileDownloadThread(url, file, blockSize,
(i + 1));
threads[i].setName("Thread:" + i);
threads[i].start();
}
boolean isfinished = false;
int downloadedAllSize = 0;
while (!isfinished) {
isfinished = true;
// 當(dāng)前所有線程下載總量
downloadedAllSize = 0;
for (int i = 0; i < threads.length; i++) {
downloadedAllSize += threads[i].getDownloadLength();
if (!threads[i].isCompleted()) {
isfinished = false;
}
}
// 通知handler去更新視圖組件
Message msg = new Message();
msg.getData().putInt("size", downloadedAllSize);
mHandler.sendMessage(msg);
// Log.d(TAG, "current downloadSize:" + downloadedAllSize);
Thread.sleep(1000);// 休息1秒后再讀取下載進(jìn)度
}
Log.d(TAG, " all of downloadSize:" + downloadedAllSize);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
最后給出DownloadActivity 的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.zhoukao_zidingyiyuan_moredownload.DownloadActivity">
<Button
android:id="@+id/download_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="80dp"
android:text="Download"
android:visibility="visible" />
<ProgressBar
android:id="@+id/download_progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progressDrawable="@drawable/progressbar_horizontal_1"
android:layout_marginTop="20dp"
android:indeterminate="false"
android:indeterminateOnly="false"
android:maxHeight="20dp"
android:minHeight="20dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:progress="0"
android:secondaryProgress="0" />
<TextView
android:id="@+id/download_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal|center_vertical"
android:text="下載進(jìn)度:0%" />
<VideoView
android:id="@+id/other_vdv"
android:layout_width="match_parent"
android:layout_height="300dp" />
</LinearLayout>
drawable里面的布局進(jìn)度條:
progressbar_horizontal_1.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- background -->
<item
android:id="@android:id/background"
android:drawable="@drawable/progress_patch_galy">
</item>
<!-- progress -->
<item android:id="@android:id/progress">
<clip>
<nine-patch android:src="@drawable/progress_patch_green" />
</clip>
</item>
<!-- second progress -->
<item android:id="@android:id/secondaryProgress">
<clip>
<nine-patch android:src="@drawable/progresspatch_blue" />
</clip>
</item>
</layer-list>
RetrofitUtils
@Streaming
@POST("{fileName}")
Call<ResponseBody> downloadFile(@Path("fileName") String fileName, @Header("Range") String range);
@Streaming
@POST("{fileName}")
Call<ResponseBody> getFileLength(@Path("fileName") String fileName);