您的位置:首页 > 移动开发 > Android开发

直接拿来用的版本更新(Android 兼容7.0)

2017-06-01 16:10 337 查看

1、需求:

版本更新,一个经常用到的功能。写一个工具类,拿去直接用。

2、实现思路:

1、请求数据 拿到后台的apk的版本号、版本名、更新内容、下载地址(可能还会包括是否强制更新的标志位)。这里有一点需要注意,如果有强制更新的概念,这时候请求数据的时候要给服务器你当前的版本号。如果你现在的版本号是1 ,用户很久没有操作,期间版本更新了2(强制更新)、3(不强制更新)。这时候用户打开版本号为1的版本,应该是要强制更新的。

2、和本地的apk版本号对比时候需要更新

3、这里用户可能会忽略此版本,这时候我要存储一个版本号,用户忽略的版本号

4、在步骤2以后 如果需要更新,先判断步骤3里边存储的版本号,比较大小, 如果用户忽略更新这个版本,那就不更新了;如果用户没有忽略过此版本,继续往下

5、这时候给用户一个提示,展示内容是有新版本是否更新,更新内容

5.1 这里可能涉及到一个强制更新,如果是强制更新的,那就要求,用户没有更新,就退出程序;不是强制更新的,可以忽略此版本

6、启动下载服务

7、下载完成之后的自动安装

3、代码实现

这里使用DownLoadManager来做下载,在UpdateAppService类中。

在UpdateAppUtils检测是否要下载

UpdateAppUtils.java

package com.example.lql.updateappdemo;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Message;

import com.example.lql.updateappdemo.message.ExitappMessage;
import com.example.lql.updateappdemo.service.UpdateAppService;
import com.example.lql.updateappdemo.utils.FinalData;
import com.example.lql.updateappdemo.utils.PreferenceUtils;
import com.example.lql.updateappdemo.utils.PublicStaticData;
import com.example.lql.updateappdemo.utils.T;

import org.greenrobot.eventbus.EventBus;

import java.lang.ref.WeakReference;

/**
* 类描述:版本更新工具类
* 这里使用DownLoadManager来做下载,在UpdateAppService类中
* 在UpdateAppUtils检测是否要下载
* 逻辑关系说明:
* 1、请求数据  拿到后台的apk的版本号、版本名、更新内容、下载地址(可能还会包括是否强制更新的标志位)
* 2、和本地的apk版本号对比时候需要更新
* 3、这里用户可能会忽略此版本,这时候我要存储一个版本号,用户忽略的版本号,如果用户的是主动更新的,都要提示。如果不是主动更新的判断一下,判断一下。
* 4、在步骤2以后   如果需要更新,先判断步骤3里边存储的版本号,比较大小,
* 如果用户忽略更新这个版本,那就不更新了;如果用户没有忽略过此版本,继续往下
* 5、这时候给用户一个提示,展示内容是有新版本是否更新,更新内容
* 5.1  这里可能涉及到一个强制更新,如果是强制更新的,那就要求,用户没有更新,就退出程序,不是强制更新的,可以忽略此版本
* 6、启动下载服务
* 7、下载完成之后的自动安装
* 使用说明:
* 在外部直接调用UpdateApp()方法
* 作  者:李清林
* 时  间:2017.5.12
* 修改备注:
*/
public class UpdateAppUtils {

public static int versionCode = 0;//当前版本号
public static String versionName = "";//当前版本名称
private static Context mContext;

public UpdateAppUtils() {
}

/**
* @param mContext       上下文
* @param newVersionCode 服务器的版本号
* @param newVersionName 服务器的版本名称
* @param content        更新了的内容
* @param downUrl        下载地址
* @param IsUpdate       是否强制更新
* @param IsToast        是否提示用户当前已经是最新版本
*/
public static void UpdateApp(Context mContext, int newVersionCode, String newVersionName,
String content, String downUrl, boolean IsUpdate, boolean IsToast) {
UpdateAppUtils.mContext = mContext;

//首先拿到当前的版本号和版本名
try {
UpdateAppUtils.mContext = mContext;
PackageManager pm = mContext.getPackageManager();
PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), 0);
versionName = pi.versionName;
versionCode = pi.versionCode;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}

if (versionCode < newVersionCode) {//第2步骤
if (PreferenceUtils.getInt(FinalData.VERSIONCODE, 0) < newVersionCode || IsToast) {//第3步骤
//这时候要去更新,展示下载的对话框
showDownLoadDialog(newVersionName, newVersionCode, content, downUrl, IsUpdate);
}
} else {
if (IsToast) {
T.shortToast(mContext, "当前已是最新版本");
}
}
}

/**
* 下载对话框
*
* @param versionname 要下载的版本名
* @param versionCode 要下载的版本号
* @param desc        更新说明
* @param downloadurl 下载地址
* @param isUpdate    是否强制更新
*/
private static void showDownLoadDialog(String versionname, final int versionCode, String desc,
final String downloadurl, final boolean isUpdate) {
AlertDialog dialog = new AlertDialog.Builder(mContext).setCancelable(false)
.setTitle("更新到 " + versionname).setMessage(desc)
.setPositiveButton("下载", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {//第6步骤,下载
T.shortToast(mContext, "正在下载...");
new Thread(new Runnable() {
@Override
public void run() {
PublicStaticData.downLoadUrl = downloadurl;
//启动服务
Intent service = new Intent(mContext, UpdateAppService.class);
mContext.startService(service);
}
}).start();
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//这里涉及到下载的强制更新,是不是强制更新   强制更新,点取消按钮,退出程序
if (isUpdate) {
T.shortToast(mContext, "此版本需要更新,程序即将退出");
MyHandler myHandler = new MyHandler(new UpdateAppUtils());
myHandler.sendEmptyMessageDelayed(0, 1000 * 3);
} else {
PreferenceUtils.setInt(FinalData.VERSIONCODE, versionCode);
dialog.dismiss();
}
}
})
.create();
dialog.show();
}

static class MyHandler extends Handler {
WeakReference<UpdateAppUtils> mWeakReference;

public MyHandler(UpdateAppUtils mUpdateAppUtils) {
mWeakReference = new WeakReference<UpdateAppUtils>(mUpdateAppUtils);
}

@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mWeakReference.get().exitApp();
}
}

/**
* 这里使用EventBus像Activity发送消息,当然你也可以使用广播
*/
private void exitApp() {
EventBus.getDefault().post(new ExitappMessage(""));
}
}


UpdateAppService.java

package com.example.lql.updateappdemo.service;

import android.app.DownloadManager;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.IBinder;
import android.support.v4.content.FileProvider;
import android.text.TextUtils;

import com.example.lql.updateappdemo.utils.LogUtils;
import com.example.lql.updateappdemo.utils.PublicStaticData;
import com.example.lql.updateappdemo.utils.T;

import java.io.File;

/**
* 类描述:下载服务
* 作  者:李清林
* 时  间:
* 修改备注:兼容7.0
*/
public class UpdateAppService extends Service {

public UpdateAppService() {

}

/** 安卓系统下载类 **/
DownloadManager manager;

/** 接收下载完的广播 **/
DownloadCompleteReceiver receiver;

/** 初始化下载器 **/
private void initDownManager() {
manager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
receiver = new DownloadCompleteReceiver();

if(TextUtils.isEmpty(PublicStaticData.downLoadUrl)){
T.shortToast(UpdateAppService.this,"下载地址为空");
return;
}

//设置下载地址
String urlPath = PublicStaticData.downLoadUrl;
Uri parse = Uri.parse(urlPath);
DownloadManager.Request down = new DownloadManager.Request(parse);
// 设置允许使用的网络类型,这里是移动网络和wifi都可以
down.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);
// 下载时,通知栏显示途中
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
down.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
}
// 显示下载界面
down.setVisibleInDownloadsUi(true);
// 设置下载后文件存放的位置
String apkName = parse.getLastPathSegment();
down.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS, apkName);
// 将下载请求放入队列
manager.enqueue(down);
//注册下载广播
registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 调用下载
initDownManager();
return super.onStartCommand(intent, flags, startId);
}

@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public void onDestroy() {
// 注销下载广播
if (receiver != null)
unregisterReceiver(receiver);
super.onDestroy();
}

// 接受下载完成后的intent
class DownloadCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(intent.getAction())) {
DownloadManager.Query query = new DownloadManager.Query();
// 在广播中取出下载任务的id
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
query.setFilterById(id);
Cursor c = manager.query(query);
if (c.moveToFirst()) {
int fileUriIdx = c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI);
String fileUri = c.getString(fileUriIdx);
String fileName = null;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
if (fileUri != null) {
fileName = Uri.parse(fileUri).getPath();
}
} else {
//Android 7.0以上的方式:请求获取写入权限,这一步报错
int fileNameIdx = c.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME);
fileName = c.getString(fileNameIdx);
}
if (null!=fileName&&!TextUtils.isEmpty(fileName)) {
install1(context, fileName);
}
//停止服务并关闭广播
UpdateAppService.this.stopSelf();
}
}
}

private  boolean install1(Context context, String filePath) {
Intent i = new Intent(Intent.ACTION_VIEW);
File file = new File(filePath);
if (file != null && file.length() > 0 && file.exists() && file.isFile()) {
//判断是否是AndroidN以及更高的版本
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
LogUtils.Loge("context.getPackageName():" + context.getPackageName() + ".provider");
Uri contentUri = FileProvider.getUriForFile(context, context.getPackageName() + ".provider", file);
i.setDataAndType(contentUri, "application/vnd.android.package-archive");
} else {
i.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
context.startActivity(i);
return true;
}
return false;
}
}
}


“`

最后别忘了在清单文件中注册服务。

4、就这样结束啦。附上源码下载地址(demo已更新):

https://github.com/LiQinglin007/UpdateAppDemo
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android