wuhb преди 2 години
родител
ревизия
9e57989496
променени са 1 файла, в които са добавени 390 реда и са изтрити 0 реда
  1. 390 0
      app/src/main/java/com/qy/agv/update/UpdateManager.java

+ 390 - 0
app/src/main/java/com/qy/agv/update/UpdateManager.java

@@ -0,0 +1,390 @@
+package com.qy.agv.update;
+
+import android.annotation.SuppressLint;
+import android.app.AlertDialog.Builder;
+import android.app.Dialog;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources.NotFoundException;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.StrictMode;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import androidx.annotation.RequiresApi;
+import androidx.core.content.FileProvider;
+
+import com.qy.agv.R;
+import com.qy.agv.util.ProjectUtils;
+import com.qy.agv.util.StringUtils;
+import com.qy.agv.util.ToastUtils;
+import com.qy.agv.util.VersionUtils;
+
+import org.apache.log4j.Logger;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.MulticastSocket;
+import java.net.SocketTimeoutException;
+import java.net.URL;
+import java.text.DecimalFormat;
+import java.util.HashMap;
+import java.util.List;
+
+public class UpdateManager {
+
+	private static final String TAG = "UpdateManager";
+	private static String FILE_NAME = "byjr_slam.apk";
+	/* 下载中 */
+	private static final int DOWNLOAD = 1;
+	/* 下载结束 */
+	private static final int DOWNLOAD_FINISH = 2;
+	/* 下载结束 */
+	private static final int ERROR = 3;
+	/* 保存解析的XML信息 */
+	HashMap<String, String> mHashMap;
+	/* 下载保存路径 */
+	private String mSavePath;
+	/* 记录进度条数量 */
+	private int progress;
+	/* 是否取消更新 */
+	private boolean cancelUpdate = false;
+
+	private Context mContext;
+
+	// 下载文件大小
+	private String fileSize;
+	// 已下载文件大小
+	private String tmpFileSize;
+
+	/* 更新进度条 */
+	private ProgressBar mProgress;
+	private TextView mProgressText;
+	private Dialog mDownloadDialog;
+	private Dialog mShowDialog;
+	public static Logger mylog =Logger.getLogger(UpdateManager.class);
+	public String next_version;
+
+	/* 通知栏 */
+	private NotificationManager updateNotificationManager = null;
+	private Notification updateNotification = null;
+
+	/* 通知栏跳转Intent */
+	private Intent updateIntent = null;
+	private PendingIntent updatePendingIntent = null;
+
+	private final Handler mHandler = new Handler(Looper.myLooper()) {
+		@SuppressLint("HandlerLeak")
+		@RequiresApi(api = Build.VERSION_CODES.O)
+		public void handleMessage(Message msg) {
+			switch (msg.what) {
+				// 正在下载
+				case DOWNLOAD:
+					// 设置进度条位置
+					if(mProgress!=null){
+						mProgress.setProgress(progress);
+						mProgressText.setText(tmpFileSize + "/" + fileSize);
+					}
+					break;
+				case DOWNLOAD_FINISH:
+					// 安装文件
+//					install();
+					ToastUtils.showToastL(mContext, "下载完成,开始安装");
+					installApk();
+					break;
+				case ERROR:
+					// 构造对话框
+					ToastUtils.showToast(mContext,"文件下载失败: "+ msg.obj.toString());
+//					try {
+//						checkUpdate();
+//					}catch (Exception ex){
+//						ex.printStackTrace();
+//					}
+					break;
+				default:
+					break;
+			}
+		}
+	};
+
+	public UpdateManager(Context context) {
+		this.mContext = context;
+	}
+
+	public UpdateManager(Context context, HashMap<String,String> mHashMap) {
+		this.mContext = context;
+		this.mHashMap = mHashMap;
+	}
+
+	/**
+	 * 检测软件更新
+	 *
+	 * @throws Exception
+	 * @throws NotFoundException
+	 */
+//	@RequiresApi(api = Build.VERSION_CODES.O)
+	public void checkUpdate() throws Exception {
+		if (isUpdate()) {
+			if(!StringUtils.isEmpty(next_version)){
+				ToastUtils.showToastL(mContext, "更新到版本"+next_version);
+			}else{
+				ToastUtils.showToastL(mContext, "正在更新");
+			}
+			ProjectUtils.init();
+			showDownloadDialog();
+//			downloadApk();
+		}
+	}
+
+	/**
+	 * 检查软件是否有更新版本
+	 *
+	 * @return
+	 * @throws Exception
+	 */
+	@SuppressLint("NewApi")
+	public boolean isUpdate() throws Exception {
+		// 获取当前软件版本
+		try {
+			int versionCode = VersionUtils.getVersionCode(mContext);
+			UpdateXmlService service = new UpdateXmlService();
+			String path = ProjectUtils.getProjectURL() + "/version.xml";
+			URL url = new URL(path);
+			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+			conn.setReadTimeout(5 * 1000);
+			conn.setConnectTimeout(3000);
+			conn.setRequestMethod("GET");
+			StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
+					.permitAll().build();
+			StrictMode.setThreadPolicy(policy);
+			InputStream inStream = conn.getInputStream();
+			mHashMap = service.parseXml(inStream);
+			if (null != mHashMap) {
+				int serviceCode = Integer.valueOf(mHashMap.get("version"));
+				// 版本判断
+				if (serviceCode > versionCode) {
+					next_version = mHashMap.get("version_name");
+					return true;
+				}
+			}
+			return false;
+		} catch (SocketTimeoutException ex){
+			ToastUtils.showToast(mContext, "连接超过");
+		} catch (Exception e) {
+			Log.e(TAG, "meth:isUpdate");
+			throw e;
+		}
+		return false;
+	}
+
+
+	/**
+	 * 显示软件下载对话框
+	 */
+	public void showDownloadDialog() {
+		// 构造软件下载对话框
+		Builder builder = new Builder(mContext);
+		builder.setTitle(R.string.soft_updating);
+		// 给下载对话框增加进度条
+		final LayoutInflater inflater = LayoutInflater.from(mContext);
+		View v = inflater.inflate(R.layout.softupdate_progress, null);
+		mProgress = (ProgressBar) v.findViewById(R.id.update_progress);
+		mProgressText = (TextView) v.findViewById(R.id.update_progress_text);
+		builder.setView(v);
+		// 取消更新
+//		builder.setNegativeButton(R.string.soft_update_close,(dialog,which)-> dialog.dismiss());
+		mDownloadDialog = builder.create();
+		mDownloadDialog.setCancelable(false);
+		mDownloadDialog.setCanceledOnTouchOutside(false);
+		mDownloadDialog.show();
+		downloadApk();
+	}
+
+	/**
+	 * 下载apk文件
+	 */
+	private void downloadApk() {
+		// 启动新线程下载软件
+		new downloadApkThread().start();
+	}
+
+	/**
+	 * 下载文件线程
+	 */
+	private class downloadApkThread extends Thread {
+		@Override
+		public void run() {
+			try {
+				// 判断SD卡是否存在,并且是否具有读写权限
+				if (Environment.getExternalStorageState().equals(
+						Environment.MEDIA_MOUNTED)) {
+					// 获得存储卡的路径
+//					File path = Environment.getExternalStorageDirectory();
+				//	mSavePath = mContext.getExternalCacheDir().getAbsolutePath();
+
+					URL url = new URL(ProjectUtils.getProjectURL()
+							+ mHashMap.get("url") + "/" + mHashMap.get("name"));
+					FILE_NAME = mHashMap.get("name");
+					mSavePath= ProjectUtils.APK;
+//					URL url = new URL(ip + "/shares/android/"
+//							+ mHashMap.get("url")+"/"+mHashMap.get("name"));
+					// 创建连接
+					HttpURLConnection conn = (HttpURLConnection) url
+							.openConnection();
+					conn.setRequestProperty("Accept-Encoding", "identity");
+					conn.connect();
+					// 获取文件大小
+					int length = conn.getContentLength();
+					// 显示文件大小格式:2个小数点显示
+					DecimalFormat df = new DecimalFormat("0.00");
+					fileSize = df.format((float) length / 1024 / 1024)
+							+ "MB";
+					// 创建输入流
+					InputStream is = conn.getInputStream();
+
+					File file = new File(mSavePath);
+					// 判断文件目录是否存在
+					if (!file.exists()) {
+						file.mkdir();
+					}else {
+						try {
+							for (File f : file.listFiles()) {
+								f.delete();
+							}
+						}catch (Exception e){
+							e.printStackTrace();
+						}
+					}
+					File apkFile = new File(mSavePath, FILE_NAME);
+					FileOutputStream fos = new FileOutputStream(apkFile);
+					int count = 0;
+					// 缓存
+					byte buf[] = new byte[1024];
+					// 写入到文件中
+					do {
+						int numread = is.read(buf);
+						count += numread;
+						// 计算进度条位置
+						tmpFileSize = df.format((float) count / 1024 / 1024)
+								+ "MB";
+						progress = (int) (((float) count / length) * 100);
+						// 更新进度
+						mHandler.sendEmptyMessage(DOWNLOAD);
+						if (numread <= 0) {
+							// 下载完成
+							mHandler.sendEmptyMessage(DOWNLOAD_FINISH);
+							break;
+						}
+						// 写入文件
+						fos.write(buf, 0, numread);
+					} while (!cancelUpdate);// 点击取消就停止下载.
+					fos.close();
+					is.close();
+				}
+
+			} catch (Exception e) {
+				e.printStackTrace();
+				mylog.error("文件下载失败:", e);
+				Message msg = new Message();
+				msg.what = ERROR;
+				msg.obj = e.getMessage();
+				mHandler.sendMessage(msg);
+			}
+			// 取消下载对话框显示
+//			mDownloadDialog.dismiss();
+		}
+	};
+
+	/**
+	 * 安装APK文件
+	 */
+	private void installApk() {
+		File apkfile = null;
+		for (int i = 0;i<5;i++) {
+			apkfile = new File(mSavePath, FILE_NAME);
+			if (!apkfile.exists()) {
+				try {
+					Thread.sleep(1000);
+				}catch (Exception e){
+					e.printStackTrace();
+				}
+			}else{
+				break;
+			}
+		}
+		if (!apkfile.exists()) {
+			ToastUtils.showToast(mContext,"文件不存在");
+			return;
+		}
+//		openAssignFolder(mSavePath);
+		// 通过Intent安装APK文件
+		Intent install = new Intent(Intent.ACTION_VIEW);
+		install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+			install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+			Uri apkUri = FileProvider.getUriForFile(mContext, "com.byjr.app.fileprovider", apkfile);//在AndroidManifest中的android:authorities值
+			install.setDataAndType(apkUri, "application/vnd.android.package-archive");
+			// 查询所有符合 intent 跳转目标应用类型的应用,注意此方法必须放置在 setDataAndType 方法之后
+			List<ResolveInfo> resolveLists = mContext.getPackageManager().queryIntentActivities(install, PackageManager.MATCH_DEFAULT_ONLY);
+			// 然后全部授权
+			for (ResolveInfo resolveInfo : resolveLists){
+				String packageName = resolveInfo.activityInfo.packageName;
+				mContext.grantUriPermission(packageName, apkUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+			}
+		} else {
+			install.setDataAndType(Uri.fromFile(apkfile), "application/vnd.android.package-archive");
+		}
+		mContext.startActivity(install);
+	}
+
+	/* 卸载apk */
+	public static void uninstallApk(Context context, String packageName) {
+		Uri uri = Uri.parse("package:" + packageName);
+		Intent intent = new Intent(Intent.ACTION_DELETE, uri);
+		context.startActivity(intent);
+	}
+
+	public void install(){
+		File apkfile = null;
+		try {
+			for (int i = 0; i < 5; i++) {
+				apkfile = new File(mSavePath, FILE_NAME);
+				if (!apkfile.exists()) {
+					try {
+						Thread.sleep(1000);
+					} catch (Exception e) {
+						e.printStackTrace();
+					}
+				} else {
+					break;
+				}
+			}
+			if (!apkfile.exists()) {
+				ToastUtils.showToast(mContext, "文件不存在");
+				return;
+			}
+			Intent install = new Intent(Intent.ACTION_VIEW);
+			install.setDataAndType(Uri.parse(apkfile.getAbsolutePath()), "application/vnd.android.package-archive");
+			install.putExtra("IMPLUS_INSTALL", "SILENT_INSTALL");
+			mContext.startActivity(install);
+		}catch (Exception ex){
+			ex.printStackTrace();
+			ToastUtils.showToast(mContext, "更新失败");
+		}
+	}
+}