版本更新涉及到几个问题,文件下载,下载进度,更新逻辑的控制(强制更新,正常更新以及无更新)等。
- 文件下载,利用DownloadManager,关键代码:
/**
* 下载最新APK
*/
private void downloadApk(String url) {
downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
downloadObserver = new DownloadChangeObserver();
registerContentObserver();
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setDescription("有料天气新版本下载");
request.setMimeType("application/vnd.android.package-archive");
/**设置用于下载时的网络状态*/
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
/**设置通知栏是否可见*/
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
/**设置漫游状态下是否可以下载*/
request.setAllowedOverRoaming(false);
/**如果我们希望下载的文件可以被系统的Downloads应用扫描到并管理,
我们需要调用Request对象的setVisibleInDownloadsUi方法,传递参数true.*/
request.setVisibleInDownloadsUi(true);
/**设置文件保存路径*/
// request.setDestinationInExternalFilesDir(getApplicationContext(), "muguo", "muguo.apk");
request.setDestinationInExternalPublicDir(getSDPath(), "youliao.apk");
/**将下载请求放入队列, return下载任务的ID*/
downloadId = downloadManager.enqueue(request);
registerBroadcast();
}
2.下载进度,利用ContentObserver,通過查询文件总大小和已下载的大小实现下载进度的监听。
/**
* 通过query已下载数据大小,总大小,下载状态
*
* @param downloadId
* @return
*/
private int[] getBytesAndStatus(long downloadId) {
int[] bs = new int[]{-1, -1, 0};
DownloadManager.Query query = new DownloadManager.Query().setFilterById(downloadId);
Cursor cursor = null;
try {
cursor = downloadManager.query(query);
if (cursor != null && cursor.moveToFirst()) {
//已下载文件大小
bs[0] = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
//文件的总大小
bs[1] = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
//下载状态
bs[2] = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
}
} finally {
if (cursor != null) {
cursor.close();
}
}
return bs;
}
3.更新逻辑的控制,一般包括无需更新、需要更新、强制更新三种装态。
fun setPWDataView(context: Activity, appVersionModel: AppVersionModel) {
mContext = context
val rl_root_view = conentView.findViewById<RelativeLayout>(R.id.rl_root_view)
val view_line = conentView.findViewById<View>(R.id.view_line)
val tv_tip_ok = conentView.findViewById<TextView>(R.id.tv_tip_ok)
val tv_tip_content = conentView.findViewById<TextView>(R.id.tv_tip_content)
val tv_tip_cancel = conentView.findViewById<TextView>(R.id.tv_tip_cancel)
rl_update_progress = conentView.findViewById(R.id.rl_update_progress)
rl_update_content = conentView.findViewById(R.id.rl_update_content)
my_progress = conentView.findViewById(R.id.my_progress)
tv_progress = conentView.findViewById(R.id.tv_progress)
if (appVersionModel.verForce == 1) {
tv_tip_content.text = "对不起,老版本已经不提供支持,请点击马上更新。"
view_line.visibility = View.GONE
tv_tip_cancel.visibility = View.GONE
} else {
tv_tip_content.text = appVersionModel.updateInfo
}
conentView.setOnTouchListener { v, event ->
//强制更新点击外面无反应
appVersionModel.verForce == 1
}
tv_tip_ok.setOnClickListener { it ->
RxPermissions(context as FragmentActivity)
.requestEach(Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
.subscribe { // will emit 2 Permission objects
permission ->
if (permission.granted) {
val path = SharedPreferencesUtils.get(context, Constant.SP_DOWNLOAD_PATH, "")
val fileName = File(path)
if (fileName != null && fileName.exists() && fileName.isFile) {
AppUpdateUtil.installApk(context, Uri.parse("file://" + fileName.toString()))
if (appVersionModel.verForce == 1) {
dismissPopupWindow()
}
} else {
isBindService = AppUpdateUtil.bindsService(context, appVersionModel.resUrl, conn)
ToastUtils.s(context, "新版本正在下载")
rl_update_progress!!.visibility = View.VISIBLE
rl_update_content!!.visibility = View.GONE
}
} else if (permission.shouldShowRequestPermissionRationale) {
// Denied permission without ask never again
} else {
// Denied permission with ask never again
// Need to go to the settings
}
}
// RxPermissions(conte
tv_tip_cancel.setOnClickListener { dismissPopupWindow() }
rl_root_view.setOnClickListener { dismissPopupWindow() }
}
}
注意:
1.适配Android N以上版本的要添加
<!-- 7.0文件访问-->
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="appupdate.zhouh.com.appdownload.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
2.权限,6.0以上动态申请权限是肯定要的了。
版本更新需要的权限包括:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
3.项目中的UI及逻辑可以自己改。
主要类是AppUpdatePopupWindow(弹出框的样式)和UpdateController(控制网络请求)以及DownloadService(下载的主要逻辑)
网友评论