之前笔者项目有个强更的需求,后来发现渠道sdk都有这个功能,就废弃掉了,但好歹自己查了好多资料调试了些时间才出的劳动成功,直接扔了不管有些可惜,所以放上来,有需要的同学可以拿来直接使用。
当打开app时用http和服务器进行一次通信,比较客户端和服务器端的版本号,如果不需要更新则开始游戏(笔者的项目是一个Unity3d的游戏项目),否则服务器返回新apk的下载地址,调用更新逻辑,即调用下面的UpdateNewVersion的downNewApk方法开始下载。
package com.kugou.wushen;
import android.app.DownloadManager;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
public class UpdateNewVersion {
private Handler handler;
private Context context;
private ProgressDialog mProgress;
private long refernece;
public static final Uri CONTENT_URI = Uri.parse("content://downloads/my_downloads");
public UpdateNewVersion(Context _context,Handler _handler){
this.context = _context;
this.handler = _handler;
}
public void downNewApk(String url){
DownloadManager dManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
Uri uri = Uri.parse(url);
DownloadManager.Request request = new DownloadManager.Request(uri);
// 设置下载路径和文件名
int idx = url.lastIndexOf("/");
String apkName = url.substring(idx+1);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, apkName);
request.setDescription("舞神新版本下载");
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setMimeType("application/vnd.android.package-archive");
// 设置为可被媒体扫描器找到
request.allowScanningByMediaScanner();
// 设置为可见和可管理
request.setVisibleInDownloadsUi(true);
refernece = dManager.enqueue(request);
// 把当前下载的ID保存起来
SharedPreferences sPreferences = context.getSharedPreferences("downloadcomplete", 0);
sPreferences.edit().putLong("refernece", refernece).commit();
DownloadChangeObserver observer = new DownloadChangeObserver(handler);
context.getContentResolver().registerContentObserver(CONTENT_URI, true, observer);
}
//用于显示下载进度
class DownloadChangeObserver extends ContentObserver{
public DownloadChangeObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange){
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(refernece);
DownloadManager dManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
final Cursor cursor = dManager.query(query);
if(cursor != null && cursor.moveToFirst()){
final int fileSizeIdx = cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
final int bytesDLIdx = cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
handler.post(new Runnable() {
public void run() {
Log.i("text", ""+cursor.getInt(bytesDLIdx)+"/"+cursor.getInt(fileSizeIdx));
UpdateDownloadProgress(cursor.getInt(bytesDLIdx),cursor.getInt(fileSizeIdx));
}
});
}
}
}
private void UpdateDownloadProgress(int cur, int total){
if(mProgress == null){
mProgress = new ProgressDialog(context);
mProgress.setIcon(R.drawable.app_icon);
mProgress.setTitle("舞神更新。。。");
mProgress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgress.setCancelable(false);
mProgress.setCanceledOnTouchOutside(false);
mProgress.setProgressNumberFormat("%dM/%dM");
mProgress.show();
}
mProgress.setMax(total/1024/1024);
mProgress.setProgress(cur/1024/1024);
}
}
当下载完成时需要打开安装界面,需要一个BroadcastReceiver侦听下载完成事件
package com.kugou.wushen;
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
public class UpdataBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
long myDwonloadID = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
SharedPreferences sPreferences = context.getSharedPreferences("downloadcomplete", 0);
long refernece = sPreferences.getLong("refernece", 0);
if (refernece == myDwonloadID) {
String serviceString = Context.DOWNLOAD_SERVICE;
DownloadManager dManager = (DownloadManager) context.getSystemService(serviceString);
Intent install = new Intent(Intent.ACTION_VIEW);
Uri downloadFileUri = dManager.getUriForDownloadedFile(myDwonloadID);
install.setDataAndType(downloadFileUri, "application/vnd.android.package-archive");
install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(install);
}
}
}
将UpdataBroadcastReceiver注册到AndroidManifest.xml中,如下:
<receiver
android:name="com.DWhale.god.UpdataBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
</intent-filter>
</receiver>
并在AndroidManifest.xml中添加响应的权限
< uses-permission android:name = "android.permission.RECEIVE_SMS" />
< uses-permission android:name = "android.permission.SEND_SMS" />
这样即使关闭了app,也能收到下载完成的广播,打开安装界面。
注:本文代码主要参考了 使用Android系统提供的DownloadManager来下载文件 ,对原作者表示感谢!

本文介绍了如何在Android应用中实现强制更新功能。当启动应用时,通过http请求对比客户端和服务器的版本号,若需更新,则调用DownloadManager下载新APK。下载完成后,通过BroadcastReceiver监听并启动安装界面。文中提供了相关代码示例,并提到了参考来源。

4311

被折叠的 条评论
为什么被折叠?



