import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.provider.Settings;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import androidx.core.content.FileProvider;
/**
* @author swt
* @date 2021/3/22
* @describe 断点下载,安装
*/
public class DownloadUtil2 {
private Activity mActivity;
private static final String TAG = "DownloadUtil";
private static DownloadUtil2 instance;
private NotificationManager notificationManager;
private Notification.Builder notification;
private NotificationCompat.Builder notification1;
private int end = Integer.MAX_VALUE;
int start = 0;
int sum = 0;
/**
* 是否在现在
*/
static boolean isDown = true;
private int currentProgress = 0;
private Context context;
/**
* 本地路径
*/
private String path;
/**
* 下载地址
*/
private String downloadPath;
private MyThread mMyThread;
/**
* 通知的channel id
*/
private final static String NOTIFICATION_CHANNEL_ID = "download_apk";
/**
* 通知的id
*/
private final static int NOTIFICATION_ID = 0X001;
/**
* 点击之后广播的request code
*/
private final static int REQUEST_CODE = 0X002;
/**
* 删除广播
*/
private final static int REQUEST_DEL_CODE = 0X003;
/**
* 成功
*/
private final static int SUCCESS_CODE = 1;
/**
* 失败
*/
private final static int FAIL_CODE = 0;
/**
* 发送handler 时间,超过1s 再发送,防止一直发送handler
*/
private long currentTimer = 0;
public void setActivity(Activity activity) {
mActivity = activity;
}
public static DownloadUtil2 getInstance() {
if (instance == null) {
instance = new DownloadUtil2();
}
return instance;
}
public void downloadApk(Context context, String url, String path) {
this.path = path;
this.context = context;
this.downloadPath = url;
try {
File file = new File(path);
if (file.exists()) {
file.delete();
}
} catch (Exception e) {
}
startDownload();
}
/**
* 开始下载
*/
public void startDownload() {
getUrlSize(downloadPath);
isDown = true;
// if(mMyThread==null){
mMyThread = new MyThread(downloadPath, path);
// }
mMyThread.start();
}
@SuppressLint("HandlerLeak")
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:
try {
int progress = 100 * msg.arg1 / msg.arg2;
Log.d("当前进度", progress + ";" + msg.arg1 + "/" + msg.arg2 + isDown);
//进度
if (progress == 100) {
start = 0;
sum = 0;
installApk(context);
}
showNotice(progress);
} catch (Exception e) {
Log.d(TAG, e.toString());
}
break;
case 2:
Log.d("####", "run: 进度条设置");
break;
}
}
};
/**
* @param code 1 下载成功 2 下载失败
*/
private void sendMessage(int code, String msg, String path) {
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("code", code);
jsonObject.put("message", msg);
jsonObject.put("path", path);
} catch (JSONException e) {
e.printStackTrace();
}
String json = jsonObject.toString();
String newJson = json.replace("\\/", "/");
Log.d(TAG, newJson);
// UnityPlayer.UnitySendMessage("(SDK_CONNECT)", "downloadApkCallback", newJson);
}
public void setPauseOrStar() {
Log.d(TAG, "当前是否在下载" + isDown);
if (!isDown) {
startDownload();
} else {
new Thread(new Runnable() {
@Override
public void run() {
isDown = false;
showNotice(currentProgress);
Log.d("####", "暂停或者完成1+" + isDown + Thread.currentThread().getName());
}
}).start();
}
}
/**
* 查询是否有安装权限
*/
public boolean checkInstallPermission(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
boolean install = context.getPackageManager().canRequestPackageInstalls();
if (install) {
return true;
} else {
getInstallPermission(context);
return false;
}
} else {
return true;
}
}
/**
* 获取安装权限
*/
@RequiresApi(api = Build.VERSION_CODES.O)
public void getInstallPermission(Context context) {
Uri packageURI = Uri.parse("package:" + context.getPackageName());
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI);
if (mActivity != null) {
mActivity.startActivityForResult(intent, 321);
} else {
context.startActivity(intent);
}
}
public void installApk(Context context) {
if (!checkInstallPermission(context)) {
return;
}
File dstFile = new File(path);
Log.d(TAG, dstFile.getPath());
Intent intent = new Intent(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= 24) {
Uri uri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", dstFile);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(uri, "application/vnd.android.package-archive");
} else {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.fromFile(dstFile), "application/vnd.android.package-archive");
}
context.startActivity(intent);
}
/**
* 获取文件大小
*/
public void getUrlSize(final String string) {
new Thread(new Runnable() {
@Override
public void run() {
URL url = null;
try {
url = new URL(string);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.connect();
end = connection.getContentLength();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
class MyThread extends Thread {
String path;
String filePath;
MyThread(String path, String filePath) {
this.path = path;
this.filePath = filePath;
createNotice(context);
}
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public void run() {
super.run();
try {
URL url = new URL(path);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
connection.setRequestProperty("Range", "bytes=" + start + "-" + end);
connection.connect();
Log.d("####", "run: 下载总总量111" + end);
RandomAccessFile file = new RandomAccessFile(filePath, "rw");
Log.d("####", "run: 创建文件");
file.seek(sum);
Log.d("####", "run: 设置下标");
InputStream inputStream = null;
Log.d("####", "run:getResponseCode===" + connection.getResponseCode());
if (connection.getResponseCode() == 206) {
Log.d("####", "run: 进入");
inputStream = connection.getInputStream();
byte[] bytes = new byte[1024];
int len = 0;
while ((len = inputStream.read(bytes)) != -1) {
file.write(bytes, 0, len);
sum += len;
Log.d("####", "run: 下载量" + sum);
if (isDown) {
if (System.currentTimeMillis() - currentTimer > 500) {
Message obtain1 = Message.obtain();
obtain1.what = 1;
obtain1.arg1 = sum / 1000;
obtain1.arg2 = end / 1000;
handler.sendMessage(obtain1);
currentTimer = System.currentTimeMillis();
}
} else {
Log.d("####", "暂停或者完成");
}
if (sum == end) {
Message obtain1 = Message.obtain();
obtain1.what = 1;
obtain1.arg1 = sum / 1000;
obtain1.arg2 = end / 1000;
currentTimer = System.currentTimeMillis();
isDown = false;
handler.sendMessage(obtain1);
}
if (!isDown) {
start = sum;
break;
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 显示通知栏
*/
private void showNotice(int progress) {
Log.d(TAG, "当前是否在下载" + isDown + "进度:" + progress);
currentProgress = progress;
if (Build.VERSION.SDK_INT >= 26) {
setNoticeData1(progress);
} else {
//当sdk版本小于26
setNoticeData2(progress);
}
}
/**
* 和下边方法一样
*/
private void setNoticeData1(int progress) {
if (notification != null) {
Notification no = notification.build();
no.contentView = createNoticeView();
no.contentView.setProgressBar(R.id.progressBar, 100, progress, false);
no.contentView.setTextViewText(R.id.tv_progress, progress + "%");
no.contentView.setImageViewResource(R.id.iv_statue, isDown ? R.drawable.ic_notice_pause : R.drawable.ic_notice_play);
no.contentView.setTextViewText(R.id.tv_tip, progress == 100 ? "下载完成" : "正在下载");
if (progress == 100) {
no.contentView.setImageViewResource(R.id.iv_statue, R.drawable.ic_notice_finish);
}
//暂停
Intent pause = new Intent(context, NotificationClickReceiver.class);
pause.putExtra("progress", progress);
pause.putExtra("action", "pause");
PendingIntent pausePendingIntent = PendingIntent.getBroadcast(context, 22, pause, PendingIntent.FLAG_UPDATE_CURRENT);
no.contentView.setOnClickPendingIntent(R.id.iv_statue, pausePendingIntent);
//删除
Intent del = new Intent(context, NotificationClickReceiver.class);
del.putExtra("progress", 11);
del.putExtra("action", "del");
//删除
PendingIntent delPendingIntent = PendingIntent.getBroadcast(context, 0, del, PendingIntent.FLAG_UPDATE_CURRENT);
no.contentView.setOnClickPendingIntent(R.id.iv_del, delPendingIntent);
if (progress == 100) {
no.contentView.setImageViewResource(R.id.iv_statue, R.drawable.ic_notice_finish);
Intent clickIntent = new Intent(context, NotificationClickReceiver.class);
clickIntent.putExtra("progress", progress);
clickIntent.putExtra("action", "pause_or_restart");
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context, REQUEST_CODE,
clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notification.setContentIntent(pendingIntent);
}
if (notificationManager != null) {
notificationManager.notify(NOTIFICATION_ID, no);
}
}
}
/**
* 和上边方法一样
*/
private void setNoticeData2(int progress) {
if (notification1 != null) {
Notification no = notification1.build();
no.contentView = createNoticeView();
no.contentView.setProgressBar(R.id.progressBar, 100, progress, false);
no.contentView.setTextViewText(R.id.tv_progress, progress + "%");
no.contentView.setImageViewResource(R.id.iv_statue, isDown ? R.drawable.ic_notice_pause : R.drawable.ic_notice_play);
no.contentView.setTextViewText(R.id.tv_tip, progress == 100 ? "下载完成" : "正在下载");
if (progress == 100) {
no.contentView.setImageViewResource(R.id.iv_statue, R.drawable.ic_notice_finish);
}
//暂停
Intent pause = new Intent(context, NotificationClickReceiver.class);
pause.putExtra("progress", progress);
pause.putExtra("action", "pause");
PendingIntent pausePendingIntent = PendingIntent.getBroadcast(context, 22, pause, PendingIntent.FLAG_UPDATE_CURRENT);
no.contentView.setOnClickPendingIntent(R.id.iv_statue, pausePendingIntent);
//删除
Intent del = new Intent(context, NotificationClickReceiver.class);
del.putExtra("progress", 11);
del.putExtra("action", "del");
//删除
PendingIntent delPendingIntent = PendingIntent.getBroadcast(context, 0, del, PendingIntent.FLAG_UPDATE_CURRENT);
no.contentView.setOnClickPendingIntent(R.id.iv_del, delPendingIntent);
if (progress == 100) {
no.contentView.setImageViewResource(R.id.iv_statue, R.drawable.ic_notice_finish);
Intent clickIntent = new Intent(context, NotificationClickReceiver.class);
clickIntent.putExtra("progress", progress);
clickIntent.putExtra("action", "pause_or_restart");
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context, REQUEST_CODE,
clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notification1.setContentIntent(pendingIntent);
}
if (notificationManager != null) {
notificationManager.notify(NOTIFICATION_ID, no);
}
}
}
/**
* 创建初始化通知栏
*/
private void createNotice(Context context) {
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= 26) {
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "猴text", importance);
notificationManager.createNotificationChannel(channel);
notification = new Notification.Builder(context, NOTIFICATION_CHANNEL_ID)
.setCategory(Notification.CATEGORY_MESSAGE)
.setContentTitle("猴text")
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.umeng_push_notification_default_large_icon))
.setSmallIcon(R.drawable.umeng_push_notification_default_large_icon)
.setAutoCancel(false);
notification.build().contentView = createNoticeView();
} else {
notification1 = new NotificationCompat.Builder(context)
.setContentTitle("text")
.setDefaults(NotificationCompat.FLAG_ONLY_ALERT_ONCE)
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.umeng_push_notification_default_large_icon)
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.umeng_push_notification_default_large_icon))
.setAutoCancel(false);
notification1.build().contentView = createNoticeView();
}
}
private RemoteViews createNoticeView() {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.notice_layout);
return remoteViews;
}
/**
* 删除当前任务
*/
public void delTask() {
//进度清零
start = 0;
sum = 0;
isDown = false;
//删除任务,关闭通知
notificationManager.cancelAll();
}
}
方法调用
downloadApk(context,download_url,file_path);