import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.Locale;
import java.util.concurrent.Executors;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.ByteString;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, MyService.class);
startService(intent);
}
/**
* OkHttp实现断点续传
*/
public void downloadRange(View view) {
view.setEnabled(false);
Toast.makeText(this, "开始下载", Toast.LENGTH_SHORT).show();
// downFromBreakPoint();
Executors.newCachedThreadPool().execute(new Runnable() {
@Override
public void run() {
try {
downMultipleThread();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* 多线程下载
*/
private void downMultipleThread() throws Exception {
// 请求基本信息
final String url = "https://alissl.ucdl.pp.uc.cn/fs08/2019/07/05/1/110_17e4089aa3a4b819b08069681a9de74b.apk";
File directory = Environment.getExternalStorageDirectory();
final File file = new File(directory, "a20190715.apk");
// 通过HEAD请求获取文件大小
final OkHttpClient client = new OkHttpClient();
Request headRequest = new Request.Builder()
.url(url)
.head()
.build();
Call headerCall = client.newCall(headRequest);
Response headResponse = headerCall.execute();
long contentLength = headResponse.body().contentLength();
System.out.println("contentLength " + contentLength);
// 计算每个线程需要下载的范围
int number = 3;
long part = contentLength / number;
for (int i = 0; i < number; i++) {
final String key = "range" + i;
SharedPreferences preferences = getPreferences(Context.MODE_PRIVATE);
final long start = preferences.getLong(key, i * part);
long end = (i + 1) * part - 1;
if (i == (number - 1)) {
end = contentLength;
}
System.out.println(start + " - " + end);
final String range = String.format(Locale.CHINESE, "bytes=%d-%d", start, end);
Executors.newCachedThreadPool().execute(new Runnable() {
@Override
public void run() {
try {
System.out.println("开始:" + Thread.currentThread().getName());
Request request = new Request.Builder()
.url(url)
.header("range", range)
.get()
.build();
Call call = client.newCall(request);
cancelDelay(call, 2000);
Response response = call.execute();
RandomAccessFile accessFile = new RandomAccessFile(file, "rw");
SharedPreferences preferences = getPreferences(Context.MODE_PRIVATE);
accessFile.seek(start);
InputStream inputStream = response.body().byteStream();
byte[] bytes = new byte[1024];
int len = inputStream.read(bytes);
while (len != -1) {
accessFile.write(bytes, 0, len);
preferences.edit().putLong(key, accessFile.getFilePointer()).apply();
len = inputStream.read(bytes);
}
System.out.println(response.body().contentLength());
System.out.println("结束:" + Thread.currentThread().getName());
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
/**
* 从断点处继续下载
*/
private void downFromBreakPoint() {
Executors.newCachedThreadPool().execute(new Runnable() {
@Override
public void run() {
try {
downloadByOkHttp();
} catch (IOException e) {
e.printStackTrace();
System.out.println(e.getMessage());
}
}
});
}
public void downloadByOkHttp() throws IOException {
// 文件下载地址
String url = "https://alissl.ucdl.pp.uc.cn/fs08/2019/07/05/1/110_17e4089aa3a4b819b08069681a9de74b.apk";
// 创建下载文件对象
File directory = Environment.getExternalStorageDirectory();
File file = new File(directory, "20190715.apk");
RandomAccessFile accessFile = new RandomAccessFile(file, "rw");
// 断点续传:重新开始下载的位置
String range = String.format(Locale.CHINESE, "bytes=%d-", file.length());
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.header("range", range)
.build();
// 使用OkHttp请求服务器
final Call call = client.newCall(request);
Response response = call.execute();
// cancelDelay(call,1000);
// 连接服务器成功
ResponseBody body = response.body();
System.out.println("文件大小:" + body.contentLength());
String header = response.header("Content-Range");
System.out.println(header);
// 移动文件指针到断点续传的位置
accessFile.seek(file.length());
// 开始断点续传
InputStream inputStream = body.byteStream();
byte[] bytes = new byte[1024];
int len = inputStream.read(bytes);
while (len != -1) {
accessFile.write(bytes, 0, len);
System.out.println("已下载字节:" + file.length());
len = inputStream.read(bytes);
}
System.out.println("文件下载完毕:" + accessFile.getFilePointer());
}
public void cancelDelay(final Call call, long delayMillis) {
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
@Override
public void run() {
call.cancel();
}
}, delayMillis);
}
}
网友评论