一个项目的基础功能几乎都要配备这个需求,版本更新,我们根据判断当前的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()
这个是我之前封装的简单粗暴的版本更新,有需要完善的地方 还需要小伙伴多多指点,有不明白的地方可以留言,谢谢