Android app强更解决方案。

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

之前笔者项目有个强更的需求,后来发现渠道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来下载文件 ,对原作者表示感谢!



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值