1.创建下载监听器DownloadListener
public interface DownloadListener {
public void onProgress(int progress);
public void onFailed();
public void onCanceled();
public void onSuccess(Uri uri);
}
2.使用AsyncTask实现异步下载操作
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.support.v4.content.FileProvider;
import android.support.v4.media.MediaBrowserCompat;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class DownloadTask extends AsyncTask {
private static final int TYPE_FAILED = 1000;
private static final int TYPE_CANCELED = 2000;
private static final int TYPE_SUCCESS = 3000;
private DownloadListener downloadListener;
private boolean isCanceled = false;
private int downloadProgress = 0;
private Context context = null;
private Uri fileUri;
public DownloadTask(Context context, DownloadListener downloadListener) {
this.downloadListener = downloadListener;
this.context = context;
}
@Override
protected void onPreExecute() {}
@Override
protected Integer doInBackground(String... params) {
int type = 0;
HttpURLConnection connection = null;
BufferedInputStream bis = null;
OutputStream os = null;
InputStream is = null;
try {
URL downloadUrl = new URL(params[0]);
connection = (HttpURLConnection) downloadUrl.openConnection();
connection.setRequestMethod("GET");
connection.setReadTimeout(20000);
connection.setConnectTimeout(20000);
connection.setRequestProperty("Accept-Encoding", "identity");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.connect();
if (connection.getResponseCode() == 200 ) {
String path = connection.getURL().getFile();
String fileName = path.substring(path.lastIndexOf(File.separatorChar) + 1); // 文件名称
path = context.getExternalFilesDir("download").getAbsolutePath(); // 文件保存路径
// 清理文件夹下的文件
for (File f : new File(path).listFiles()) {
f.delete();
}
// 创建文件
String filePath = path + "/" + fileName; // 文件的路径
File file = new File(filePath);
file.createNewFile();
is = connection.getInputStream();
bis = new BufferedInputStream(is);
os = new FileOutputStream(file);
byte[] bytes = new byte[1024];
long currentLength = 0;
int size = 0;
while ( (size = bis.read(bytes)) != -1) {
if (isCanceled) {
type = TYPE_CANCELED;
} else {
currentLength += size;
os.write(bytes, 0, size);
// getContentLength()获取文件大小,当值大于Integer.MAX_VALUE时,返回-1
publishProgress((int)(100*currentLength/connection.getContentLength()));
}
}
fileUri = file2Uri(file);
type = TYPE_SUCCESS;
}
} catch (MalformedURLException e) {
e.printStackTrace();
type = TYPE_FAILED;
} catch (IOException e) {
e.printStackTrace();
type = TYPE_FAILED;
} finally {
if (null != connection) {
connection.disconnect();
}
try {
if (null != is) {
is.close();
}
if (null != os) {
os.close();
}
if (null != bis) {
bis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return type;
}
@Override
protected void onProgressUpdate(Integer... values) {
if (values[0] > downloadProgress) {
downloadProgress = values[0];
downloadListener.onProgress(downloadProgress);
}
}
@Override
protected void onPostExecute(Integer integer) {
switch (integer) {
case TYPE_FAILED:
downloadListener.onFailed();
break;
case TYPE_CANCELED:
downloadListener.onCanceled();
break;
case TYPE_SUCCESS:
downloadListener.onSuccess(fileUri);
break;
default:
break;
}
}
public void cancelDownload() {
isCanceled = true;
}
/**
* File对象并转化成Uri返回
* @return
*/
private Uri file2Uri(File file) {
Uri uri = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uri = FileProvider.getUriForFile(context, "cn.com.pirate.demo.fileprovier", file);
} else {
uri = Uri.fromFile(file);
}
return uri;
}
}
3.在服务中操作DownloadTask
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.FileProvider;
import android.util.Log;
import java.io.File;
public class DownloadService extends BaseService {
private static final int NOTIFICATION_ID = 1000;
private static final int DOWNLOAD_SUCCESS = 101;
private final Context context = this;
private DownloadTask downloadTask = null;
private DownloadBinder downloadBinder = new DownloadBinder();
private DownloadListener downloadListener = new DownloadListener() {
@Override
public void onProgress(int progress) {
startForeground(NOTIFICATION_ID, getNotification(null, progress));
}
@Override
public void onFailed() {
}
@Override
public void onCanceled() {
}
@Override
public void onSuccess(Uri uri) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// 赋予FLAG_GRANT_READ_URI_PERMISSION,FLAG_GRANT_WRITE_URI_PERMISSION权限,否则7.0以上版本无法安装
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.setDataAndType(uri, "application/vnd.android.package-archive");
startActivity(intent);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(NOTIFICATION_ID, getNotification(pendingIntent, DOWNLOAD_SUCCESS));
notificationManager.cancel(NOTIFICATION_ID);
}
};
public class DownloadBinder extends Binder {
public void download(String downloadUrl) {
if (null != downloadUrl && null == downloadTask) {
downloadTask = new DownloadTask(context, downloadListener);
downloadTask.execute(downloadUrl);
}
}
public void cancel () {
if (null != downloadTask) {
downloadTask.cancelDownload();
}
}
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return downloadBinder;
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
}
private Notification getNotification(PendingIntent pendingIntent, int progress) {
Notification notification = new NotificationCompat.Builder(this)
.setContentIntent(pendingIntent)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher_round))
.setWhen(System.currentTimeMillis())
.setContentTitle(getResources().getString(R.string.app_name) + "更新")
.setContentText(progress == DOWNLOAD_SUCCESS ? "应用下载已完成,请点击安装" : "当前已经下载 " + progress + " %")
.setProgress(100, progress, false)
.build();
return notification;
}
public static void start(Context context) {
Intent intent = new Intent(context, DownloadService.class);
context.startService(intent);
}
public static void stop(Context context) {
Intent intent = new Intent(context, DownloadService.class);
context.stopService(intent);
}
public static boolean bind(Context context, ServiceConnection conn) {
Intent intent = new Intent(context, DownloadService.clzss);
context.bindService(intent, conn ,BIND_AUTO_CREATE);
return true;
}
public static boolean unbind(Context context, ServiceConnection conn) {
context.unbindService(conn);
return false;
}}
4.调用下载功能
import android.content.ComponentName;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private static final String downloadUrl = "apk的下载地址"
private boolean isbind = false;
private DownloadService.DownloadBinder downloadBinder;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
downloadBinder = (DownloadService.DownloadBinder)service;
}
@Override
public void onServiceDisconnected(ComponentName name) {}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
DownloadService.start(this);
isbind = DownloadService.bind(this, conn);
}
}