在layout创建一个XML文件

<?xml version="1.0" encoding="utf-8"?>
<!--整体对话框-->
<RelativeLayout
    android:background="@drawable/dialogradius"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="1280px"
    android:layout_height="670px"
    app:layout_constraintCircleRadius="20dp">
    <!--内部对话框-->
    <LinearLayout
        android:layout_width="1280px"
        android:layout_height="670px"
        android:layout_marginStart="10px"
        android:layout_marginLeft="10px"
        android:layout_marginTop="10px"
        android:layout_marginEnd="10px"
        android:layout_marginRight="10px"
        android:orientation="vertical"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintCircleRadius="20dp">

        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="标题"
            android:textSize="50px"
            android:layout_marginTop="30px"
            android:layout_marginLeft="100px"
            android:textColor="#333333"/>

        <TextView
            android:id="@+id/message"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="信息"
            android:textSize="40px"
            android:textColor="#666666"
            android:layout_marginLeft="100px"
            android:layout_marginTop="50px"/>
<!--进度条-->
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/linearLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="30px"
            android:layout_marginLeft="50px"
            android:layout_marginEnd="30px"
            android:layout_marginRight="100px"
            android:layout_marginTop="100px"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="1.0"
            app:layout_constraintStart_toStartOf="parent"
            tools:layout_editor_absoluteY="127px">

            <ProgressBar
                android:id="@+id/progress01"
                style="?android:attr/progressBarStyleHorizontal"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginLeft="100px"
                android:layout_marginRight="100px"
                android:progressDrawable="@drawable/myprogressbar" />


        </LinearLayout>
        <!--进度信息-->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/linearLayout"
            android:layout_marginLeft="160px"
            android:layout_marginRight="160px"
            >
  <!--更新了多少文件或者多少Mb创建后用来导入数据-->
            <TextView
                android:id="@+id/filename"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="TextView"
                android:textSize="42px"
                android:textColor="#f5578d"/>

            <TextView
                android:id="@+id/midText"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="进度信息"
                android:textSize="40px"
                android:textColor="#666666"/>
            <TextView
                android:id="@+id/num"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:textSize="42px"
                android:textColor="#f5578d"
                />
        </LinearLayout>
<!--按键-->
        <LinearLayout
            android:id="@+id/actionArea"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal"
            android:gravity="right"
            android:layout_marginTop="50dp"
            >

            <TextView
                android:id="@+id/Cancel"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="40dp"
                android:layout_marginBottom="50px"
                android:text="取消"
                android:onClick="Cancel"
                android:textColor="#00bfff"
                android:textSize="42px"
                app:layout_constraintEnd_toEndOf="parent"
                tools:layout_editor_absoluteY="146dp" />
        </LinearLayout>
    </LinearLayout>




</RelativeLayout>

创建一个JAVA类继承Dialog

package com.example.updataprocess;

import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;

public class SelectDialog  extends Dialog {
    private Context mContext;
    private View view;

    public SelectDialog(Context context, int theme) {
        super(context, theme);
        mContext = context;
    }

    public SelectDialog(Context context) {
        super(context);
        mContext = context;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.progress);
        //与刚才创建的Xml文件结合
        view = LayoutInflater.from(mContext).inflate(R.layout.progress,null,false);
        setContentView(view);
    }

    public View aVoid(){
        return view;
    }


}

创建一个drawable文件设置弹框的样式,背景色,填充色,边框线,圆角等

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <!-- rectangle表示为矩形 -->

    <!-- 填充的颜色 -->
    <solid android:color="#fff" />

    <!-- 边框的颜色和粗细 -->
    <stroke
        android:width="1dp"
        android:color="#fff"
        />

    <!-- android:radius 圆角的半径 -->
    <corners
        android:radius="20dp"
            android:topLeftRadius="20dp"
            android:topRightRadius="20dp"
            android:bottomRightRadius="20dp"
            android:bottomLeftRadius="20dp"
            />

</shape>

实际应用

private void showDownloadDialog(){
        //调用继承Dialog的SelectDialog
        final SelectDialog selectDialog = new SelectDialog(mContext,R.style.my_dialog);
        selectDialog.show();
//因为需要在其他方法中关闭弹框,将selectDialog赋值给全局变量downloadDialog
        downloadDialog=selectDialog;

//调用圆角布局,没有这句,圆角外会遗留三角形白色区域
selectDialog.getWindow().setBackgroundDrawableResource(R.drawable.dialogradius);
//配置对话框
        View v = selectDialog.aVoid();
        mProgress = v.findViewById(R.id.progress01);//进度条
        mProgress.setIndeterminate(false);
        mTitle=v.findViewById(R.id.title);//Title
        mMessage=v.findViewById(R.id.message);//message
        mUpdataName=v.findViewById(R.id.filename);//进度信息,这里是文件名
        mNum=v.findViewById(R.id.num);//进度,这里是几分之几
        mCancel=v.findViewById(R.id.Cancel);//取消按钮
        mMidText=v.findViewById(R.id.midText);//文件名和几分之几中间的文字,理论上不会变化,为了设置字体,调用一下
        
  //设置点击事件
        mCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                    selectDialog.dismiss();//关闭窗口
                    interceptFlag = true;//停止下载用
            }
        });
//设置外部字体
        mTitle.setTypeface(tf);
        mUpdataName.setTypeface(tf);
        mCancel.setTypeface(tf);
        mNum.setTypeface(tf);
        mMessage.setTypeface(tf);
        mMidText.setTypeface(tf);
    }

为了设置外部字体需要先创建assets文件夹,再创建fonts文件夹,将外部字体复制进去,然后输入代码

public UpdateManager(Context context) {
        this.mContext = context;

        mgr=mContext.getAssets();
        tf = Typeface.createFromAsset(mgr,"fonts/fzktjt.ttf");
    }

创建handle接受信息更新

private Handler mHandler = new Handler(){
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:
                    mProgress.setProgress(progress);//更新进度条
                    break;
                case 2:
//                    showDownloadOverDialog();
                    System.out.println("下载完成");
                    break;
                case 3:
                    mUpdataName.setText(updataFileName);//更新文件名
                    mNum.setText(updataNum);//更新几分之几
                    break;
                case 4:
                    showDownloadfileDialog();//下载失败弹框
                default:
                    break;
            }
        }
    };

下载方法,我这里是接受后台传来的JSON数组,每个JSON字符串中包含版本包名,版本信息,下载路径等信息

//下载文件并解压
        public boolean downloadApk(JSONArray urllist) {
        final JSONArray data=urllist;
        final FileOperation fileOperation=new FileOperation();
        final JSONArray versionList=new JSONArray();
        //比对包名和版本信息,包名为Key,版本号为value
            final HashMap<String,Integer> versionInfoMap = new  HashMap<String,Integer>();
        
            //设置进度条最大值
            mProgress.setMax(100);
            //创建下载线程,我发现不用线程进度条貌似无法更新
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //循环
            for (int i=0;i<data.length();i++) {
                JSONObject pg =new JSONObject();
                try {
                    String title=data.getJSONObject(i).getString("resPackageNm");
                    Integer version=data.getJSONObject(i).getInt("publishVer");
                    pg.put("resPackageNm",title);
                    pg.put("publishVer",version);
                    //设置下载文件的包名为key
                     if (versionInfoMap.containsKey(title)) {
                         Integer versionInt = versionInfoMap.get(title);
                        //判断版本号是否最大
                         if (versionInt < version) {
                             versionInfoMap.put(title, version);
                         }
                     }else {
                         versionInfoMap.put(title,version);
                     }

                    URL url = new URL(data.getJSONObject(i).getString("path"));
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.connect();
                    
                    InputStream is = conn.getInputStream();
                    File file = new File(savePath);
                    if (!file.exists()) {
                        file.mkdirs();
                    }
                    String apkFile = saveFileName;

                    File ApkFile = new File(apkFile);
                    FileOutputStream fos = new FileOutputStream(ApkFile);
                    //文件数量进度,这里有4个文件
                    int length=data.length();
                    //计算文件大小,这里弃用
//                    int length = conn.getContentLength()-1;
                    int count = i+1;//正在更新第几个文件
                    progress =(int)(((float)count / length) * 100);//计算出进度,这里会以25%进度更新
                    //进度条显示包名
                    updataFileName=title;
                    //进度条显示
                    updataNum=i+1+"/"+data.length();
                    //这是在干嘛,我也不知道,抄的
                    byte buf[] = new byte[1024];
                    
                    do {
                        int numread = is.read(buf);
                        Message nmsg=new Message();
                        nmsg.what=3;
                        mHandler.sendMessage(nmsg);
//                        count += numread;
                        //好像是文件剩余是否为0的判断
                        if (numread <= 0) {
                            //下载完成后进行解压
                            //解压哪个文件
                            String zipOutName=savePath+data.getJSONObject(i).getString("unzipPath");
                            //调用解压方法
                            installApk(saveFileName,zipOutName);
                            //发送handle信息
                            Message msg=new Message();
                            msg.what=1;
                            //更新进度条
                            mHandler.sendMessage(msg);
                            break;
                        }
                        fos.write(buf, 0, numread);
                    } while (!interceptFlag);//点击取消就停止下载.


                    fos.close();
                    is.close();

                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();

                } catch (JSONException e) {
                    e.printStackTrace();
                }
                //用包名和版本号生成一个版本信息的text文档,每次打开app时读取这个文档判断是否需要更新
                for (Map.Entry<String, Integer> entry : versionInfoMap.entrySet()) {
                    JSONObject jsonObject=new JSONObject();
                    try {
                        jsonObject.put("resPackageNm",entry.getKey());
                        jsonObject.put("publishVer",entry.getValue());
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                    versionList.put(jsonObject);
                }

                String a=versionList.toString();
                fileOperation.writeTxtFile(a,saveFileName);
            }
//更新完成后,线程睡个0.7秒后关闭进度弹框
                    try {
                        Thread.sleep(700);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
             downloadDialog.dismiss();
      
//4个文件全部下载解压完成后,提示显示完成,interceptFlag下载时点击取消会被赋值为true.
                    //此时会关闭下载弹框,打开下载失败弹框
                    //正常下载完成打开,下载完成提示框
                    if (interceptFlag) {
                        Message msg = new Message();
                        msg.what = 4;
                        mHandler.sendMessage(msg);
                    }else{
                        Message msg = new Message();
                        msg.what = 2;
                        mHandler.sendMessage(msg);
                    }
                }

            }).start();

                return true;
            }

    /**
     *解压ZIP
     * @paramurl
     */
    //解压(文件名,文件路径)
    private void installApk(String gwt,String path) {
        ZipUtils mZipUtils=new ZipUtils();
        FileOperation fileOperation=new FileOperation();
        try {
            mZipUtils.UnZipFolder(gwt, path);

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