ok请求依赖
compile 'com.squareup.okhttp3:okhttp:3.9.1'
compile 'com.google.code.gson:gson:2.8.1'
权限
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
接口:用来监听下载进度等
package com.example.text;
/**
* Created by xsj on 2017/12/28.
*/
public interface DownloadListener {
void startDownload();
void pauseDownload();
void finishDownload();
void downloadProgress(long progress);
}
网络请求Util类
package com.example.text;
import android.util.Log;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
/**
* Created by xsj on 2017/12/28.
*/
public class DownloadUtils {
//单列模式
private static volatile DownloadUtils instance;
private final OkHttpClient client;
private File file;
private String filePath;
private File downloadFile;
private long startPosition;
private Call call;
public static DownloadUtils getInstance() {
if (null == instance) {
synchronized (DownloadUtils.class) {
if (instance == null) {
instance = new DownloadUtils();
}
}
}
return instance;
}
public DownloadUtils() {
client = new OkHttpClient.Builder().build();
}
//初始化路径
public void initDownload(String path){
file = new File(path);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdir();
}
if (!file.exists()) {
file.mkdir();
}
filePath = file.getAbsolutePath();
Log.e("TAG", "initDownload: " + filePath);
}
public void startDownload(String url, final DownloadListener listener) {
//得到apk的名字
if (url.contains(".")) {
String typeName = url.substring(url.lastIndexOf(".") + 1);
if (url.contains("/")) {
String name = url.substring(url.lastIndexOf("/") + 1, url.lastIndexOf("."));
String fn = name + "." + typeName;
downloadFile = new File(file, fn);
Log.e("TAG","下载地址:"+downloadFile);
}
}
startPosition = 0;
//判断文件是否存在,如果存在,拿到长度
if (downloadFile.exists()) {
startPosition = downloadFile.length();
}
Request request = new Request.Builder()
.addHeader("RANGE", "bytes=" + startPosition + "-")
.url(url)
.build();
call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
listener.startDownload();
ResponseBody body = response.body();
InputStream inputStream = body.byteStream();
//总长
long totalLength = body.contentLength() + startPosition;
byte[] buf = new byte[1024];
int length = 0;
long totalNum = startPosition;
while ((length = inputStream.read(buf)) != -1) {
//主要需要的类
RandomAccessFile raf = new RandomAccessFile(downloadFile, "rw");
raf.seek(totalNum);
raf.write(buf, 0, length);
//接口返回数据百分比
listener.downloadProgress(totalNum * 100 / totalLength);
totalNum += length;
}
listener.finishDownload();
body.close();
}
});
}
//暂停
public void pauseDownload( final DownloadListener listener) {
listener.pauseDownload();
if (call != null && call.isExecuted()) {
call.cancel();
}
}
}
Activity的代码文件
package com.example.text;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.io.File;
public class MainActivity extends AppCompatActivity implements View.OnClickListener,DownloadListener{
private TextView tv;
private String downloadUrl = "http://dlsw.baidu.com/sw-search-sp/soft/4b/17170/Install_WLMessenger14.0.8117.416.1393467029.exe";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button start= (Button) findViewById(R.id.start);
Button stop= (Button)findViewById(R.id.stop);
tv = (TextView) findViewById(R.id.tv);
start.setOnClickListener(this);
stop.setOnClickListener(this);
//查看是否挂载
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File storageDirectory = Environment.getExternalStorageDirectory();
String absolutePath = storageDirectory.getAbsolutePath();
String path=absolutePath+"/Download/";
Log.e("TAG", "下载路径: " + path);
//初始化路径
DownloadUtils.getInstance().initDownload(path);
}
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.start:
DownloadUtils.getInstance().startDownload(downloadUrl, this);
break;
case R.id.stop:
DownloadUtils.getInstance().pauseDownload(this);
break;
}
}
@Override
public void startDownload() {
Log.e("TAG","开始");
}
@Override
public void pauseDownload() {
Log.e("TAG","暂停");
}
@Override
public void finishDownload() {
Log.e("TAG","结束");
}
@Override
public void downloadProgress(final long progress) {
runOnUiThread(new Runnable() {
@Override
public void run() {
tv.setText(progress+"");
}
});
}
}
布局文件
<?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.text.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tv"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开始"
android:id="@+id/start"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="结束"
android:id="@+id/stop"
/>
</LinearLayout>