AutoUpdater.java 12.4 KB
package etelligens.com.foodsafety.utils;


import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import androidx.core.content.FileProvider;
import etelligens.com.foodsafety.R;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
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.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.SecureRandom;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static me.pushy.sdk.config.PushyLogging.TAG;

/**
 * @author wj
 * @Description: 自动更新apk
 * @create 2023/10/24  14:02
 **/
public class AutoUpdater {

    // 下载安装包的网络路径
    private String apkUrl = "http://52.74.130.36/upload/app/";
    protected String checkUrl = apkUrl + "output-metadata.json";

    // 保存APK的文件名
    private static final String saveFileName = "release.apk";
    private static File apkFile;

    // 下载线程
    private Thread downLoadThread;
    private int progress;// 当前进度
    // 应用程序Context
    private Context mContext;
    // 是否是最新的应用,默认为false
    private boolean isNew = false;
    private boolean intercept = false;
    // 进度条与通知UI刷新的handler和msg常量
    private ProgressBar mProgress;
    private TextView txtStatus;

    private static final int DOWN_UPDATE = 1;
    private static final int DOWN_OVER = 2;
    private static final int SHOWDOWN = 3;

    public AutoUpdater(Context context) {
        mContext = context;
        String root = Environment.getExternalStorageDirectory().getPath();
        String parentPath = "";
        try {
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
                parentPath = mContext.getExternalFilesDir(null).getPath();
            } else {
                parentPath = mContext.getFilesDir().getPath();
            }
        } catch (Exception e) {
            Log.d(TAG, "doDownload e:" + e.getMessage());
        }

        Log.d(TAG, "doDownload parentPath:" + parentPath);
        //Toast.makeText(mContext,"跟路径"+root,Toast.LENGTH_SHORT).show();
        //Toast.makeText(mContext, "Android版本"+Build.VERSION.SDK_INT, Toast.LENGTH_SHORT).show();
        apkFile = new File(parentPath, saveFileName);
        //如果已有文件,删除
        if (apkFile.exists()) {
            Log.d(TAG, "doDownload delete APK");
            apkFile.delete();
        }
        //Log.e("路径",mContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString());
        //apkFile = new File(root, saveFileName);
        //apkFile = new File(mContext.getFilesDir(), saveFileName);
    }

    public void ShowUpdateDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
        builder.setCancelable(false);
        builder.setTitle("SOFTWARE UPDATE");
        builder.setMessage("Please download and install the latest version !");
        builder.setPositiveButton("Now", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                ShowDownloadDialog();
            }
        });
        builder.setNegativeButton("Later", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });

        builder.create().show();
    }

    private void ShowDownloadDialog() {
        AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
        dialog.setCancelable(false);
        dialog.setTitle("Updating...");
        LayoutInflater inflater = LayoutInflater.from(mContext);
        View v = inflater.inflate(R.layout.progress, null);
        mProgress = (ProgressBar) v.findViewById(R.id.progress);
        txtStatus = v.findViewById(R.id.txtStatus);
        dialog.setView(v);
        dialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                intercept = true;
            }
        });
        dialog.show();
        DownloadApk();
    }

    /**
     * 检查是否更新的内容
     */
    public void CheckUpdate() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                String localVersion = "1";
                try {
                    localVersion = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionName;
                 //localVersion="20231024083955";
                } catch (PackageManager.NameNotFoundException e) {
                    e.printStackTrace();
               }
                String versionName = "1";
                String outputFile = "";
                String config = doGet(checkUrl);
                if (config != null && config.length() > 0) {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                        Matcher matcher = Pattern.compile("\"outputFile\":\\s*\"([^\"]*?)\"").matcher(config);
                        if (matcher.find()) {
                            outputFile = matcher.group(1);
                        }
                        matcher = Pattern.compile("\"versionName\":\\s*\"([^\"]*?)\"").matcher(config);

                        if (matcher.find()) {
                            String v = matcher.group(1);
                            versionName = v.replace("v1.0.", "");
                        }
                    }
                }
                if (Long.parseLong(localVersion) < Long.parseLong(versionName)) {
                    apkUrl = apkUrl + outputFile;
                    mHandler.sendEmptyMessage(SHOWDOWN);
                    Log.e("部署版",versionName);
                    Log.e("本班",localVersion);
                } else {
                    return;
                }
            }
        }).start();
    }

    /**
     * 从服务器下载APK安装包
     */
    public void DownloadApk() {
        downLoadThread = new Thread(DownApkWork);
        downLoadThread.start();
    }

    private Runnable DownApkWork = new Runnable() {
        @Override
        public void run() {
            URL url;
            try {
                //如果下载地址是HTTPS,则把这段加上,http则不需要
                SSLContext sslContext = SSLContext.getInstance("SSL");//第一个参数为 返回实现指定安全套接字协议的SSLContext对象。第二个为提供者
                TrustManager[] tm = {new MyX509TrustManager()};
                sslContext.init(null, tm, new SecureRandom());
                SSLSocketFactory ssf = sslContext.getSocketFactory();
                url = new URL(apkUrl);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.connect();
                int length = conn.getContentLength();
                InputStream ins = conn.getInputStream();
                FileOutputStream fos = new FileOutputStream(apkFile);
                int count = 0;
                byte[] buf = new byte[1024];
                while (!intercept) {
                    int numread = ins.read(buf);
                    count += numread;
                    progress = (int) (((float) count / length) * 100);
                    // 下载进度
                    mHandler.sendEmptyMessage(DOWN_UPDATE);
                    if (numread <= 0) {
                        // 下载完成通知安装
                        mHandler.sendEmptyMessage(DOWN_OVER);
                        break;
                    }
                    fos.write(buf, 0, numread);
                }
                fos.close();
                ins.close();

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };

    //卸载
    public  void uninstallAPP() {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_DELETE);
        intent.setData(Uri.parse("package:" + mContext.getApplicationContext().getPackageName()));
        mContext.startActivity(intent);
        installAPK();
    }
    /**
     * 安装APK内容
     */
    public void installAPK() {
        try {
            if (!apkFile.exists()) {
                return;
            }
            Toast.makeText(mContext, "install", Toast.LENGTH_SHORT).show();
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//安装完成后打开新版本
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // 给目标应用一个临时授权
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//判断版本大于等于7.0
                //如果SDK版本>=24,即:Build.VERSION.SDK_INT >= 24,使用FileProvider兼容安装apk
                String packageName = mContext.getApplicationContext().getPackageName();
                String authority = new StringBuilder(packageName).append(".provider").toString();
                Uri apkUri = FileProvider.getUriForFile(mContext, authority, apkFile);
                Log.e("packageName",packageName);
                Log.e("authority",authority);
                Log.e("apkFile", String.valueOf(apkFile));
                intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
            } else {
                intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
            }
            mContext.startActivity(intent);
            android.os.Process.killProcess(android.os.Process.myPid());//安装完之后会提示”完成” “打开”。
        } catch (Exception e) {
        }
    }

    private Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
                case SHOWDOWN:
                    ShowUpdateDialog();
                    break;
                case DOWN_UPDATE:
                    txtStatus.setText(progress + "%");
                    mProgress.setProgress(progress);
                    break;
                case DOWN_OVER:
                    Toast.makeText(mContext, "Download complete", Toast.LENGTH_SHORT).show();
                    uninstallAPP();
                    break;
                default:
                    break;
            }
        }
    };

    public static String doGet(String httpurl) {
        HttpURLConnection connection = null;
        InputStream is = null;
        BufferedReader br = null;
        String result = null;
        try {
            URL url = new URL(httpurl);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(15000);
            connection.setReadTimeout(60000);
            connection.connect();
            if (connection.getResponseCode() == 200) {
                is = connection.getInputStream();
                br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                StringBuffer sbf = new StringBuffer();
                String temp = null;
                while ((temp = br.readLine()) != null) {
                    sbf.append(temp);
                    sbf.append("\r\n");
                }
                result = sbf.toString();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            connection.disconnect();
        }
        return result;
    }

}