package xn.update; import android.annotation.SuppressLint; import android.app.DownloadManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.net.Uri; import android.os.AsyncTask; import android.os.Environment; import android.util.Log; import com.blankj.utilcode.util.AppUtils; import com.blankj.utilcode.util.FileUtils; import com.blankj.utilcode.util.GsonUtils; import com.blankj.utilcode.util.LogUtils; import com.blankj.utilcode.util.SPUtils; import com.blankj.utilcode.util.ThreadUtils; import org.json.JSONException; import java.io.File; import java.io.IOException; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import okhttp3.Response; import xn.update.constant.AppConstant; import xn.update.http.HttpTool; import xn.update.http.bean.response.UpdateTask; public enum UpdateTool { INSTANCE; private UpdateTask.Task task; @SuppressLint("SdCardPath") private final String apkPath = "/sdcard/Download/apk/"; private final String apkName = "app.apk"; private DownloadManager downloadManager; private long downloadId; private long lastRunTime; private final AtomicBoolean isUploading = new AtomicBoolean(false); public void checkUpdate(Context context) { // 若是3分钟都没下载完成,则认为下载失败 long runTime = (System.currentTimeMillis() - lastRunTime); if (lastRunTime > 0 && runTime > 1000 * 60 * 3) { isUploading.set(false); } // 空闲中 if (!isUploading.get() && SPUtils.getInstance().getBoolean(AppConstant.AUTO_UPDATE, true)) { lastRunTime = System.currentTimeMillis(); isUploading.set(true); if (null == downloadManager) { downloadManager = (DownloadManager) context.getApplicationContext().getSystemService(Context.DOWNLOAD_SERVICE); } ThreadUtils.executeByCached(new ThreadUtils.SimpleTask() { @SuppressLint({"UnspecifiedRegisterReceiverFlag", "SdCardPath"}) @Override public Boolean doInBackground() throws Throwable { try { Response response = HttpTool.INSTANCE.update(); if (response.isSuccessful()) { String json = response.body().string(); UpdateTask updateTask = GsonUtils.fromJson(json, UpdateTask.class); if (updateTask.getCode() == 200) { List updateTaskData = updateTask.getData(); if (null != updateTaskData && !updateTaskData.isEmpty()) { task = updateTaskData.get(0); FileUtils.createOrExistsDir(apkPath); FileUtils.deleteAllInDir(apkPath); if (!AppUtils.getAppPackageName().equals(task.getStartLaunchPackage())) { SPUtils.getInstance().put(AppConstant.KeySP.MASTER_PACKAGE_NAME, task.getStartLaunchPackage()); } DownloadManager.Request request = new DownloadManager.Request(Uri.parse(Tool.INSTANCE.checkUrl(task.getApkUrl()))); request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "apk/" + apkName); request.setMimeType("application/vnd.android.package-archive"); request.setVisibleInDownloadsUi(false); request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN); context.registerReceiver(downloadApkReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); downloadId = downloadManager.enqueue(request); LogUtils.d("发起下载", downloadId); return true; } } else { LogUtils.e(updateTask.getMessage()); } } } catch (Exception e) { LogUtils.e(Log.getStackTraceString(e)); } return false; } @Override public void onSuccess(Boolean result) { isUploading.set(result); } }); } else { LogUtils.d("正在升级中..."); } } private final BroadcastReceiver downloadApkReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); LogUtils.d("下载成功", downloadId, task); if (downloadId == id) { if (null != task) { AsyncTask.execute(() -> { try { HttpTool.INSTANCE.updateCallBack(task.getTaskId(), task.getDeviceCode(), true, false); } catch (IOException | JSONException e) { LogUtils.e(Log.getStackTraceString(e)); } // 升级其它App if (!task.getStartLaunchPackage().equals(AppUtils.getAppPackageName())) { Tool.INSTANCE.cmd("pm uninstall" + task.getStartLaunchPackage()); } else { SPUtils.getInstance().put("isSelfUpdate", true, true); SPUtils.getInstance().put("SelfUpdate", GsonUtils.toJson(task), true); } Tool.INSTANCE.cmd("pm install -d -g " + apkPath + apkName); Tool.INSTANCE.openApp(task.getStartLaunchPackage()); try { HttpTool.INSTANCE.updateCallBack(task.getTaskId(), task.getDeviceCode(), true, true); } catch (IOException | JSONException e) { LogUtils.e(Log.getStackTraceString(e)); } isUploading.set(false); }); } } } }; /** * 解析未安装的APK文件 * * @param context 上下文 * @param apkPath APK文件路径 */ public void parseApkFile(Context context, String apkPath) { PackageManager pm = context.getPackageManager(); PackageInfo packageInfo = pm.getPackageArchiveInfo(apkPath, PackageManager.GET_PERMISSIONS | PackageManager.GET_META_DATA); if (packageInfo != null) { // 获取应用信息 ApplicationInfo appInfo = packageInfo.applicationInfo; // 修复资源路径问题 appInfo.sourceDir = apkPath; appInfo.publicSourceDir = apkPath; // 获取基本信息 String packageName = packageInfo.packageName; String versionName = packageInfo.versionName; int versionCode = packageInfo.versionCode; // 获取权限 String[] permissions = packageInfo.requestedPermissions; // 获取APK大小 File apkFile = new File(apkPath); long apkSize = apkFile.length(); // 打印信息 Log.d("APK-INFO", "包名: " + packageName); Log.d("APK-INFO", "版本: " + versionName + "(" + versionCode + ")"); Log.d("APK-INFO", "大小: " + (apkSize / 1024) + "KB"); if (permissions != null) { for (String perm : permissions) { Log.d("APK-INFO", "权限: " + perm); } } } } }