获取文件的md5值
/**
* 获取文件的md5值
* @param file
* @return
*/
public static String getMd5ByFile(File file) {
String value = "";
FileInputStream in=null;
try {
in= new FileInputStream(file);
MappedByteBuffer byteBuffer = in.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length());
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(byteBuffer);
BigInteger bi = new BigInteger(1, md5.digest());
value = bi.toString(16);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != in) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return value;
}
获取字符串的md5值
/**
*获取字符串的md5值
*/
public static String getMd5ByString(String string) {
{
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(string.getBytes("UTF-8"));
byte[] encryption = md5.digest();
StringBuffer strBuf = new StringBuffer();
int encryptionLength=encryption.length;
for (int i = 0; i < encryptionLength; i++) {
if (Integer.toHexString(0xff & encryption[i]).length() == 1) {
strBuf.append("0").append(Integer.toHexString(0xff & encryption[i]));
} else {
strBuf.append(Integer.toHexString(0xff & encryption[i]));
}
}
return VnTool.replaceBlank(strBuf.toString());
} catch (NoSuchAlgorithmException e) {
return "";
} catch (UnsupportedEncodingException e) {
return "";
}
}
}
版本更新
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
- jar包:okhttp3; okio; okhttputils-2_6_2; gson
- 代码
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.support.v4.content.FileProvider;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import com.google.gson.Gson;
import com.zhy.http.okhttp.OkHttpUtils;
import com.zhy.http.okhttp.callback.FileCallBack;
import com.zhy.http.okhttp.callback.StringCallback;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import okhttp3.Call;
import static android.content.Context.MODE_PRIVATE;
/**
* 版本更新器
* Created by zxjz on 17-6-15.
*/
public class Updater {
private boolean needResponse=false;
private Context context;
private VersionBean versionBean;
private static final String preferencesName ="VersionUpdatePreference";
private static final String key_latestVersionCode ="versionCode";
private static final String key_forcedUpdate="forcedUpdate";
private static final String key_localPath ="localPath";
private static final String key_md5="md5";
private static final String static_checkUpdateUrl="http://116.62.12.119/version/latest/apk/";
private String checkUpdateUrl="";
private boolean printLog=true;
private InstallDialogAble dialogAble=null;
private String localCachePath;
/**
* 检查升级的接口
* @param context
* @param checkUpdateUrl
*/
public Updater(Context context, String checkUpdateUrl) {
if (TextUtils.isEmpty(checkUpdateUrl)){
this.checkUpdateUrl=static_checkUpdateUrl+context.getPackageName();
}else {
this.checkUpdateUrl=checkUpdateUrl+context.getPackageName();
}
this.context = context;
localCachePath=new File( "/sdcard/VersionUpdater/updater/").getPath()+"/";
File file=new File(localCachePath);
if (!file.exists()){
file.mkdirs();
}
}
/**
* 检查版本更新
* @param shouldDialog 是否显示升级提示对话框
* @param dialogAble 具备弹框能力的对话框接口,参考 defaultdialogAble,可以为空,当为空时,会使用默认的弹框 defaultdialogAble
*/
public void checkForUpdate(boolean shouldDialog,InstallDialogAble dialogAble){
if (shouldDialog){
this.dialogAble=dialogAble!=null?dialogAble:defaultdialogAble;
}
log("开始联网检查版本更新:url="+checkUpdateUrl);
OkHttpUtils.get().url(checkUpdateUrl).build().execute(new StringCallback() {
@Override
public void onError(Call call, Exception e, int i) {
e.printStackTrace();
String msg="获取云端版本信息失败."+e.getMessage();
reply(msg);
log(msg);
log("检查缓存更新...");
checkUpdateInCache();
}
@Override
public void onResponse(String result, int i) {
boolean noResult=true;
if (result != null) {
log("result:" + result);
VersionBean remoteVersion=null;
try{
remoteVersion= new Gson().fromJson(result, VersionBean.class);
}catch (IllegalStateException e){
e.getMessage();
}
if (remoteVersion != null&& !TextUtils.isEmpty(remoteVersion.downloadLink)) {
noResult=false;
log("remoteVersion:"+remoteVersion.toString());
int selfVersionCOde=getVersionCode(context);
if (remoteVersion.versionCode>selfVersionCOde){
VersionBean cache = getCache();
boolean ableInstallCache=false;
if (cache!=null){
if (cache.versionCode==remoteVersion.versionCode){
log("检查缓存");
ableInstallCache= checkUpdateInCache();
}
}
if (!ableInstallCache){
downloadNewVersion(remoteVersion);
}
}else {
reply("已是最新版本.");
}
}
}
if (noResult){
reply("获取版本信息失败.");
}
}
});
}
/**
* 检查缓存中是否有可以更新的版本,如果有就更新
* @return 返回是否可以通过缓存更新
*/
private boolean checkUpdateInCache() {
VersionBean cacheVersion = getCache();
if (cacheVersion==null){
log("缓存中无可以更新.");
return false;
}
File upapk=new File(cacheVersion.localPath);
if (upapk!=null){
log("缓存文件存在"+cacheVersion.localPath);
String fmd5=getMd5ByFile(upapk);
log("缓存md5记录:"+cacheVersion.md5+",缓存apk文件MD5:"+fmd5);
}else {
log("缓存文件不存在"+cacheVersion.localPath);
}
boolean b = upapk!=null&&getMd5ByFile(upapk).equalsIgnoreCase(cacheVersion.md5);
if (b){
attemptInstallNewVersion(cacheVersion);
}
return b;
}
private void log(String s) {
if (printLog){
Log.d("versionUpdater",""+s);
}
}
/**
* 获取已经缓存的版本信息
* @return
*/
private VersionBean getCache(){
SharedPreferences preferences=context.getApplicationContext().getSharedPreferences(preferencesName,MODE_PRIVATE);
versionBean =new VersionBean();
versionBean.localPath =preferences.getString(key_localPath,"");
versionBean.versionCode =preferences.getInt(key_latestVersionCode,-1);
versionBean.forcedUpdate =preferences.getBoolean(key_forcedUpdate,true);
versionBean.md5=preferences.getString(key_md5,"");
if (versionBean.versionCode<=getVersionCode(context)){
return null;
}
return versionBean;
}
/**
* 保存最新版本到缓存
* @param versionBean
*/
private void saveCache(VersionBean versionBean) {
log("cache():"+ versionBean.toString());
SharedPreferences preferences=context.getApplicationContext().getSharedPreferences(preferencesName,MODE_PRIVATE);
SharedPreferences.Editor editer = preferences.edit();
editer.putBoolean(key_forcedUpdate, versionBean.forcedUpdate);
editer.putInt(key_latestVersionCode, versionBean.versionCode);
editer.putString(key_localPath, versionBean.localPath);
editer.putString(key_md5,versionBean.md5);
editer.commit();
}
private void downloadNewVersion(final VersionBean remoteVersion) {
log("下载更新...");
String url=remoteVersion.downloadLink;
final String newApkName=context.getString(R.string.app_name)+"_v"+remoteVersion.versionCode+".apk";
OkHttpUtils.get().url(url).build().execute(new FileCallBack(localCachePath,newApkName) {
@Override
public void onError(Call call, Exception e, int i) {
log("下载更新文件失败");
e.printStackTrace();
}
@Override
public void onResponse(File file, int i) {
if (file!=null) {
String fileMd5=getMd5ByFile(file)+"";
if(fileMd5.equalsIgnoreCase(remoteVersion.getMd5())) {
log("downloadNewVersion():" + file.getAbsolutePath() + ", path:" + file.getPath());
VersionBean versionBean = remoteVersion;
versionBean.localPath = localCachePath + newApkName;
log("缓存到本地的路径:"+versionBean.localPath);
saveCache(versionBean);
attemptInstallNewVersion(versionBean);
}else{
log("downloadNewVersion():下载的更新文件md5:"+fileMd5+",与服务器的md5:"+remoteVersion.getMd5()+"不匹配");
}
}else {
log("downloadNewVersion():下载的更新文件file==null");
}
}
});
}
public interface InstallDialogAble{
void onCanbeUpdate(boolean forcedUpdate, Exector erector);
}
public class Exector {
private Updater updater;
private VersionBean willInstallVersion;
public Exector(Updater updater, VersionBean versionBean) {
this.updater = updater;
this.willInstallVersion=versionBean;
}
public void install(){
updater.install(willInstallVersion);
}
}
private InstallDialogAble defaultdialogAble=new Updater.InstallDialogAble(){
@Override
public void onCanbeUpdate(final boolean ForcedUpdate, final Updater.Exector exector) {
String msg=ForcedUpdate?"程序有重大更新,请您更新到最新版本使用.":"程序有可用的新版本,是否现在更新?";
String negativeStr=ForcedUpdate?"退出":"取消";
android.support.v7.app.AlertDialog alertDialog=
new android.support.v7.app.AlertDialog.Builder
(context)
.setTitle("版本更新")
.setMessage(msg)
.setPositiveButton("更新", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
exector.install();
}
})
.setNegativeButton(negativeStr, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (ForcedUpdate){
String msg=context.getString(R.string.app_name)+"需要更新,请您更新后使用.";
Toast.makeText(context,msg,Toast.LENGTH_SHORT).show();
System.exit(0);
}
}
})
.setCancelable(false)
.show();
}
};
public InstallDialogAble getDefaultdialogAble() {
return defaultdialogAble;
}
public void setDialogAble(InstallDialogAble dialogAble) {
this.dialogAble = dialogAble;
}
private void attemptInstallNewVersion(VersionBean versionBean) {
log("attemptInstallNewVersion()");
if (dialogAble!=null) {
Exector exector=new Exector(this,versionBean);
dialogAble.onCanbeUpdate(versionBean.forcedUpdate,exector);
}else {
install( versionBean);
}
}
public void install(VersionBean versionBean){
log("开始安装");
File newApkFile=new File(versionBean.localPath);
if (newApkFile==null){
log("安装文件是空");
return;
}
log("启动系统安装界面");
String packageName=context.getPackageName();
installApp(context,newApkFile,packageName);
}
private void reply(String string){
if (needResponse) {
}
}
private class VersionBean {
/**
* clientType : android
* versionCode : 2
* md5 : AEA3BD557B00C62D232B85DA81DD28ED
* forcedUpdate : false
* downloadLink : 182.92.160.8:8889/app-version/apk/com.smart.chat/2/app-release.apk
*/
private String clientType;
private int versionCode;
private String md5;
private boolean forcedUpdate;
private String downloadLink;
public String localPath;
@Override
public String toString() {
return "VersionBean{" +
"clientType='" + clientType + '\'' +
", versionCode=" + versionCode +
", md5='" + md5 + '\'' +
", forcedUpdate=" + forcedUpdate +
", downloadLink='" + downloadLink + '\'' +
", localPath='" + localPath + '\'' +
'}';
}
public String getClientType() {
return clientType;
}
public void setClientType(String clientType) {
this.clientType = clientType;
}
public int getVersionCode() {
return versionCode;
}
public void setVersionCode(int versionCode) {
this.versionCode = versionCode;
}
public String getMd5() {
return md5;
}
public void setMd5(String md5) {
this.md5 = md5;
}
public boolean isForcedUpdate() {
return forcedUpdate;
}
public void setForcedUpdate(boolean forcedUpdate) {
this.forcedUpdate = forcedUpdate;
}
public String getDownloadLink() {
return downloadLink;
}
public void setDownloadLink(String downloadLink) {
this.downloadLink = downloadLink;
}
}
/**
* 获取版本名称
* @param context 上下文
* @return 版本名称
*/
public static String getVersionName(Context context){
PackageManager pm = context.getPackageManager();
try {
PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(),0);
return packageInfo.versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return null;
} /**
* 获取版本号
* @param context 上下文
* @return 版本号
*/
public static int getVersionCode(Context context){
PackageManager pm = context.getPackageManager();
try {
PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(),0);
return packageInfo.versionCode;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return 0;
}
/**
* 获取文件的md5值
* @param file
* @return
*/
public static String getMd5ByFile(File file) {
String value = "";
FileInputStream in=null;
if (file==null){
return value;
}
try {
in= new FileInputStream(file);
MappedByteBuffer byteBuffer = in.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length());
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(byteBuffer);
BigInteger bi = new BigInteger(1, md5.digest());
value = bi.toString(16);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != in) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return value;
}
/**
* 安装apk
* @param context
* @param apkFile apk文件
* @param pakgname 包名
*/
public static void installApp(Context context, File apkFile, String pakgname) {
if(apkFile == null||context==null) {
return ;
} else {
Log.d("installApp","执行安装,文件名;"+apkFile.getName()+",包名:"+pakgname+"content="+context);
Intent intent = new Intent("android.intent.action.VIEW");
String var4 = "application/vnd.android.package-archive";
Uri var3;
if(Build.VERSION.SDK_INT < 24) {
var3 = Uri.fromFile(apkFile);
} else {
try {
intent.setFlags(1);
var3 = FileProvider.getUriForFile(context.getApplicationContext(), pakgname, apkFile);
}catch (Exception e){
var3 = Uri.fromFile(apkFile);
}
}
intent.setDataAndType(var3, var4);
context.startActivity(intent);
}
}
}