在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();
}
}
}