Android 最简单直白的版本更新下载APP自动安装(带进度条)

一个项目的基础功能几乎都要配备这个需求,版本更新,我们根据判断当前的APK版本信息和服务器校验,是否下载,今天我们只聊一下下载自动更新的功能实现

第一步.下载工具类(包含进度框+自动安装)

//负责软件更新模块
public class UpdateUnit {

    private Context context;
    private String url;

    // 更新提示语
   // private String upDateMSG = "有更新,是否现在更新?";

    // 获取SD卡根目录
    private static final String ROOT = Environment.getExternalStorageDirectory().getPath();

    // 文件保存路径
    private static final String savePath = ROOT + "/MyAPP/";

    // 文件路径+文件名
    private static final String saveFilePath = savePath + "MyAPP.apk";

    // 进度条
    private ProgressBar progressBar;
    private TextView tv_bfb;
    private int progress;
private Button bt_down;
    // 下载标识
    private static final int DOWN_UPDATE = 0;

    // 结束下载标识
    private static final int DOWN_OVER = 1;

    // 下载错误标识
    private static final int DOWN_FAIL = 2;

    // 取消下载按钮标识
    private boolean interceptFlag = false;

    // 子线程
    private Thread downloadThread;

    public UpdateUnit(Context context, String url) {
        this.context = context;
        this.url = url;
    }

    // 外部接口 让Activity调用
    public void updateInfo() {
        showdownDialog();
    }

    // 显示提示对话框
    //private void shownoticeDialog() {

		/*AlertDialog.Builder SNDialog = new AlertDialog.Builder(context);
		SNDialog.setTitle("软件版本更新");
		SNDialog.setMessage(upDateMSG);
		// 确定更新按钮
		SNDialog.setPositiveButton("立即更新", new OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				dialog.dismiss();
				// 调用下载对话框
				showdownloadDialog();
			}
		});
		// 以后再说按钮
		SNDialog.setNeutralButton("以后再说", new OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				dialog.dismiss();
			}
		});
		// 设置对话框失去焦点的时候仍然不消失
		SNDialog.setCancelable(false);
		SNDialog.create();
		SNDialog.show();*/
    //}

    // 显示下载对话框
    private void showdownDialog() {
        Builder SDDialog = new Builder(context);

        // 显示进度条
        LayoutInflater inflater = LayoutInflater.from(context);
        View view = inflater.inflate(R.layout.dialog_pgsbar, null);
        progressBar =  view.findViewById(R.id.progressBar);
        tv_bfb=view.findViewById(R.id.tv_bfb);
        bt_down=view.findViewById(R.id.bt_down);
      //  Button bt_pgsbar=view.findViewById(R.id.bt_pgsbar);
        SDDialog.setView(view);
        bt_down.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });
        /*bt_pgsbar.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismiss();
                interceptFlag = true;
            }
        });*/
        // 取消按钮
        SDDialog.setNeutralButton("Cancel", (dialog, which) -> {
            dialog.dismiss();
            interceptFlag = true;
        });
        // 设置对话框失去焦点的时候仍然不消失
        SDDialog.setCancelable(false);
        SDDialog.create();
        SDDialog.show();
        downloadAPK();
    }

    // 下载APK
    private void downloadAPK() {
        downloadThread = new Thread(downAPKRunnable);
        downloadThread.start();
    }

    // 子线程中执行下载
    private Runnable downAPKRunnable = new Runnable() {

        @Override
        public void run() {
            try {
                URL uri = new URL(Api.HOST + url);
       
                HttpURLConnection urlConnection = (HttpURLConnection) uri
                        .openConnection();
                urlConnection.connect();
                // 获取下载文件长度
                int apkLength = urlConnection.getContentLength();
                InputStream inputStream = urlConnection.getInputStream();
                // 创建文件保存路径
                File file = new File(savePath);
                if (!file.exists()) {
                    file.mkdir();
                }
                File APKFile = new File(saveFilePath);
                FileOutputStream fileOutputStream = new FileOutputStream(
                        APKFile);
                // 已经下载的长度
                int count = 0;
                byte[] bs = new byte[1024];
                do {
                    int num = inputStream.read(bs);
                    count += num;
                    progress = (int) (((float) count / apkLength) * 100);
                    handler.sendEmptyMessage(DOWN_UPDATE);
                    if (num <= 0) {
                        handler.sendEmptyMessage(DOWN_OVER);
                        break;
                    }
                    fileOutputStream.write(bs, 0, num);
                }
                // 点击取消停止下载
                while (!interceptFlag);
                fileOutputStream.close();
                inputStream.close();
            } catch (Exception e) {
                handler.sendEmptyMessage(DOWN_FAIL);
                e.printStackTrace();
            }
        }
    };

    // 使用Handler更新进度
     private Handler handler = new Handler() {
        @SuppressLint("HandlerLeak")
        public void handleMessage(@NotNull Message msg) {
            switch (msg.what) {
                // 正在下载,更新进度
                case DOWN_UPDATE:
                    tv_bfb.setText(progress+"%");
                    progressBar.setProgress(progress);
                    break;
                // 下载结束
                case DOWN_OVER:
                    installAPK();
                    break;
                case DOWN_FAIL:
                    Toast.makeText(context, "文件下载失败!", Toast.LENGTH_LONG).show();
                    break;
            }
        }

    };

    // 安装APK
    private void installAPK() {
        File apkFile = new File(saveFilePath);
        if (!apkFile.exists()) {
            return;
        }
        Intent i = new Intent(Intent.ACTION_VIEW);
        i.setDataAndType(Uri.parse("file://" + apkFile.toString()),
                "application/vnd.android.package-archive");
      
        context.startActivity(i);
    }

}

第二步.进度条xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:orientation="vertical"
        >

    <TextView android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:text="@string/downloading"
            android:textColor="@color/blue"
            android:textSize="16sp"
            android:textStyle="bold"
            android:layout_marginTop="10dp"/>

    <ProgressBar
            android:id="@+id/progressBar"
            android:layout_marginTop="20dp"
            android:layout_centerHorizontal="true"
            android:layout_width="match_parent"
            android:layout_marginRight="20dp"
            android:layout_marginLeft="20dp"
            android:layout_gravity="center"
            android:layout_height="10dp"
            android:max="100"
            android:progress="0"
            android:progressDrawable="@drawable/progress_white"
            style="@android:style/Widget.ProgressBar.Horizontal" />
    <TextView
            android:id="@+id/tv_bfb"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:textColor="@color/white"
            android:textSize="12sp"
            android:layout_marginTop="10dp"/>
    <Button
        android:id="@+id/bt_down"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:textColor="@color/white"
        android:background="@drawable/shape_bt_regist"
        android:textSize="12sp"
        android:text="@string/cancel"
        android:visibility="gone"
        android:layout_marginTop="10dp"/>
</LinearLayout>

第三步 直接调用即可

   UpdateUnit(this, "下载路径").updateInfo()

这个是我之前封装的简单粗暴的版本更新,有需要完善的地方 还需要小伙伴多多指点,有不明白的地方可以留言,谢谢

猜你喜欢

转载自blog.csdn.net/qq_28643195/article/details/107787947