这里直接上代码
在你需要下载的地方调用
VersionUtil.getInstance().downLoadAPK(updateBeen.getUpdatedUrl(),context);
相关是相关类的代码
VersionUtil
package com.zte.general_project.ui.utils;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.Toast;
import com.zte.general_project.R;
import java.io.File;
import java.io.IOException;
/**
* Created by lovelin on 2017/8/10.
*/
public class VersionUtil {
private static VersionUtil instance = null;
private Context mContext;
private String localUrl;
private MyHandler mHandler;
public static String TAG = VersionUtil.class.getSimpleName();
public static VersionUtil getInstance() {
if (instance == null) {
instance = new VersionUtil();
}
return instance;
}
public VersionUtil setContext(Context context) {
this.mContext = context;
return instance;
}
public void downLoadAPK(String apkUrl, Context context) {
this.mContext = context;
String[] strs = apkUrl.split("/");
String fileName = strs[strs.length - 1];
File cacheDir = FileUtil.creatFileDirectory("apk");
localUrl = cacheDir.getAbsolutePath() + File.separator + fileName;
mHandler = new MyHandler();
new DownLoadAPKUtil(mHandler, apkUrl, cacheDir.getAbsolutePath(),
fileName).start();
}
private class MyHandler extends Handler {
private final NotificationCompat.Builder mBuilder;
private final NotificationManager mNotifyManager;
public MyHandler() {
Log.e("tga", "mNotifyManager。。。。。。。");
mBuilder = new NotificationCompat.Builder(mContext);
mBuilder.setContentTitle("软件升级").setSmallIcon(
R.drawable.icon_lib_cancel);
mNotifyManager = (NotificationManager) mContext
.getSystemService(Context.NOTIFICATION_SERVICE);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (DownLoadAPKUtil.MSG_NET_RES_OK == msg.what) {
// installVersion(localUrl);
if (checkFileMD5()) {
installVersion(localUrl);
} else {
Toast.makeText(mContext,
"下载失败",
Toast.LENGTH_SHORT).show();
mBuilder.setProgress(0, 0, false);
mBuilder.setContentText("升级失败");
mNotifyManager.notify(NOTIFICATION_ID, mBuilder.build());
}
} else if (DownLoadAPKUtil.MSG_NET_RES_GET == msg.what) {
mBuilder.setProgress(100, (Integer) msg.obj, false);
mBuilder.setContentText("正在下载,请稍后...");
mNotifyManager.notify(NOTIFICATION_ID, mBuilder.build());
} else if (DownLoadAPKUtil.MSG_DOWNLOAD_OK == msg.what) {
in(mBuilder);
mBuilder.setProgress(100, (Integer) msg.obj, false);
mBuilder.setContentText("下载成功,点击安装");
mNotifyManager.notify(NOTIFICATION_ID, mBuilder.build());
// installVersion(localUrl);
}
}
}
private int NOTIFICATION_ID = 10000;
private void installVersion(String filename) {
try {
File file = new File(filename);
if (file.isFile()) {
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(Intent.ACTION_VIEW); // 浏览网页的Action(动作)
String type = "application/vnd.android.package-archive";
intent.setDataAndType(Uri.fromFile(file), type); // 设置数据类型
mContext.startActivity(intent);
// ((Activity) mActivity).finish();
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
private void in(NotificationCompat.Builder mBuilder){
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(Intent.ACTION_VIEW); // 浏览网页的Action(动作)
String type = "application/vnd.android.package-archive";
intent.setDataAndType(Uri.fromFile(new File(localUrl)), type); // 设置数据类型
mBuilder.setAutoCancel(true);
Log.e("tga", "mNotifyManager。。。。。。。" + localUrl);
mBuilder.setContentIntent(PendingIntent.getActivity(mContext, 100,
intent, PendingIntent.FLAG_UPDATE_CURRENT));
}
private boolean checkFileMD5() {
boolean bSuccess = false;
String checkString;
try {
checkString = MD5ChangeUtile.getFileMD5String(new File(localUrl))
.toUpperCase();
if (checkString != null) {
bSuccess = true;
}
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
return bSuccess;
}
}
DownLoadAPKUtil
package com.zte.general_project.ui.utils;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class DownLoadAPKUtil extends Thread{
private static final String TAG = DownLoadAPKUtil.class.getSimpleName();
public static final int BUF_LEN = 1024;
public static final int MSG_NET_RES_OK = 1000;
public static final int MSG_NET_RES_ERR = 1001;
public static final int MSG_NET_RES_GET = 1002;
public static final int MSG_DOWNLOAD_OK = 1005;
private Handler mHandler = null;
private String mUrl = null;
private String mFileName = "";
private String mPath;
public DownLoadAPKUtil(){
}
public DownLoadAPKUtil(Handler handler, String url, String localPath, String fileName) {
this.mHandler=handler;
this.mUrl=url;
this.mFileName=fileName;
this.mPath=localPath;
}
@Override
public void run() {
InputStream inputStream;
try {
URL url = new URL(mUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(5000);
connection.setRequestMethod("GET");
if(connection.getResponseCode()==200){
int fileSize = connection.getContentLength() / 1024;
Message msg;
inputStream = connection.getInputStream();
if (inputStream == null) {
throw new RuntimeException("stream is null");
}
mkDirs(mPath);
Log.e("tga","爱情。。down。。。mPath。。"+mPath);
File dFile = new File(mPath, mFileName);
// dFile.setExecutable(true);
FileOutputStream fos = new FileOutputStream(dFile);
byte buf[] = new byte[BUF_LEN];
int total = 0;
inputStream = connection.getInputStream();
int len = 0;
while ((len = inputStream.read(buf)) != -1) {
fos.write(buf, 0, len);
total += (len / 1024);
Log.e("tga","路过。。。。。。。"+total * 100+"#正在下载#"+fileSize+"###进度"+total * 100 / fileSize);
// Log.e(total * 100+"#正在下载#"+fileSize+"###进度"+total * 100 / fileSize);
msg = mHandler.obtainMessage(MSG_NET_RES_GET, total * 100 / fileSize);
mHandler.sendMessage(msg);
}
fos.flush();
fos.close();
inputStream.close();
msg = mHandler.obtainMessage(MSG_DOWNLOAD_OK, 100);
mHandler.sendMessage(msg);
msg = mHandler.obtainMessage(MSG_NET_RES_OK, "complete");
mHandler.sendMessage(msg);
}
} catch (Exception e) {
Message msg = mHandler.obtainMessage(MSG_NET_RES_ERR,
e.toString());
mHandler.sendMessage(msg);
}
}
public static void mkDirs(String path) throws IOException {
File file = new File(path);
if (!file.exists()) {
try {
file.mkdirs();
} catch (Exception e) {
// LogUtil.e(TAG, e.getMessage());
}
}
}
}
FileUtil
package com.zte.general_project.ui.utils;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Environment;
import android.os.StatFs;
import android.text.TextUtils;
import android.util.Log;
import com.zte.general_project.APPAplication;
import com.zte.general_project.ui.exception.ServiceRulesException;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.text.DecimalFormat;
/*
* Author: Lucifer
*
* Created Date:2015-4-7
* Copyright @ 2015 BU
* Description: 文件工具类
*
* History:
*/
public class FileUtil {
public static String appFile = "app";// 默认app文件目录
public static final String baseFile = Environment
.getExternalStorageDirectory() + File.separator;
public static final String appBaseFile = baseFile + appFile
+ File.separator;
boolean sdCardExist = Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED);// 是否有存储设备
public FileUtil() throws ServiceRulesException {
if (!sdCardExist)
throw new ServiceRulesException("请插入外部SD存储卡");
File fileBase = new File(appBaseFile);
if (!fileBase.exists())
fileBase.mkdir();
}
/**
* 创建一个文件目录
*
* @return void
* @author Lucifer 2015-4-8 下午8:02:31
*/
public static File creatFileDirectory(String path) {
File file = new File(appBaseFile + File.separator + path);
if (!file.exists()) {
file.mkdirs();
}
return file;
}
/**
* 创建一个文件
*
* @param path
* @param fileName
* @return File
* @author Lucifer 2015-4-8 下午8:28:54
*/
public static File creatNewFile(String path, String fileName) {
File file = null;
creatFileDirectory(path);
file = new File(appBaseFile + File.separator + path + File.separator
+ fileName);
return file;
}
/**
* 将图片写入当前文件中
*
* @param photo
* @param path
* @param fileName
* @return File
* @author Lucifer 2015-4-8 下午8:38:17
*/
public static File saveBitmapToFile(Bitmap photo, String path, String fileName) {
File file = null;
file = creatNewFile(path, fileName);
FileOutputStream fOut = null;
try {
fOut = new FileOutputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
photo.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
try {
fOut.flush();
} catch (IOException e) {
e.printStackTrace();
}
try {
fOut.close();
} catch (IOException e) {
e.printStackTrace();
}
return file;
}
/**
* 写到sd卡
* @param path
* @param fileName
* @param inputStream
* @return File
* @author luxf 2015-5-26 下午2:37:43
*/
public static File write2SDFormInput(String path, String fileName,
InputStream inputStream) {
// 创建文件
File file = creatNewFile(path, fileName);
OutputStream outputStream = null;
try {
// 创建输出流
outputStream = new FileOutputStream(file);
// 创建缓冲区
byte buffer[] = new byte[4 * 1024];
// 写入数据
while ((inputStream.read(buffer)) != -1) {
outputStream.write(buffer);
}
// 清空缓存
outputStream.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return file;
}
/**
* 获取文件大小
*
* @param file
* @return long
* @throws Exception
* @author Administrator 2015-6-14 下午8:22:02
*/
public static long getFileSize(File file) throws Exception {
long size = 0;
File flist[] = file.listFiles();
for (int i = 0; i < flist.length; i++) {
if (flist[i].isDirectory()) {
size = size + getFileSize(flist[i]);
} else {
size = size + flist[i].length();
}
}
return size;
}
/**
* 转换文件 大小
*
* @param fileS
* @return String
* @author Administrator 2015-6-14 下午8:22:14
*/
public static String FormetFileSize(long fileS) {// 转换文件大小
DecimalFormat df = new DecimalFormat("#.00");
String fileSizeString = "";
if (fileS == 0) {
fileSizeString = "0.0B";
} else if (fileS < 1024) {
fileSizeString = df.format((double) fileS) + "B";
} else if (fileS < 1048576) {
fileSizeString = df.format((double) fileS / 1024) + "K";
} else if (fileS < 1073741824) {
fileSizeString = df.format((double) fileS / 1048576) + "M";
} else {
fileSizeString = df.format((double) fileS / 1073741824) + "G";
}
return fileSizeString;
}
/**
* 递归删除文件和文件夹
*
* @param file 要删除的根目录
*/
public static void RecursionDeleteFile(File file) {
if (file.isFile()) {
file.delete();
return;
}
if (file.isDirectory()) {
File[] childFile = file.listFiles();
if (childFile == null || childFile.length == 0) {
file.delete();
return;
}
for (File f : childFile) {
RecursionDeleteFile(f);
}
file.delete();
}
}
/**
* 判断文件是否存在
*
* @param path
* @param fileName
* @return boolean
* @author Administrator 2015-6-16 下午10:32:40
*/
public static boolean isFileExistes(String path, String fileName) {
try {
File f = new File(path + fileName);
if (!f.exists()) {
return false;
}
} catch (Exception e) {
return false;
}
return true;
}
/**
* 判断SDCard是否可用
*
* @return
*/
public static boolean isSDCardEnable() {
return Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED);
}
/**
* 获取SD卡路径
*
* @return
*/
public static String getSDCardPath() {
return Environment.getExternalStorageDirectory().getAbsolutePath()
+ File.separator;
}
/**
* 获取SD卡的剩余容量 单位byte
*
* @return
*/
public static long getSDCardAllSize() {
if (isSDCardEnable()) {
StatFs stat = new StatFs(getSDCardPath());
// 获取空闲的数据块的数量
long availableBlocks = (long) stat.getAvailableBlocks() - 4;
// 获取单个数据块的大小(byte)
long freeBlocks = stat.getAvailableBlocks();
return freeBlocks * availableBlocks;
}
return 0;
}
/**
* 获取指定路径所在空间的剩余可用容量字节数,单位byte
*
* @param filePath
* @return 容量字节 SDCard可用空间,内部存储可用空间
*/
public static long getFreeBytes(String filePath) {
// 如果是sd卡的下的路径,则获取sd卡可用容量
if (filePath.startsWith(getSDCardPath())) {
filePath = getSDCardPath();
} else {// 如果是内部存储的路径,则获取内存存储的可用容量
filePath = Environment.getDataDirectory().getAbsolutePath();
}
StatFs stat = new StatFs(filePath);
long availableBlocks = (long) stat.getAvailableBlocks() - 4;
return stat.getBlockSize() * availableBlocks;
}
/**
* 读取Assets目录下的citylist.json文件
* @param context
* @return
*/
public static String readCityListJson(Context context) {
String json="";
try {
json=readAssetsFile(context,"");
} catch (IOException e) {
Log.e("FileUtil","error:读取文件出错"+e.getMessage());
e.printStackTrace();
}
return json;
}
/**
* 读取Assets目录下的文件
* @param context
* @param fileName
* @return
* @throws IOException
*/
public static String readAssetsFile(Context context,String fileName) throws IOException {
String fileContent = "";
if(TextUtils.isEmpty(fileName)){
fileName = "citylist.json";
}
InputStream inputStream = context.getAssets().open(fileName);
InputStreamReader inputReader = new InputStreamReader(inputStream);
BufferedReader bufReader = new BufferedReader(inputReader);
String line;
while ((line = bufReader.readLine()) != null) {
fileContent += line;
}
inputStream.close();
return fileContent;
}
}
MD5ChangeUtile
package com.zte.general_project.ui.utils;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* md5 工具类
*
* @author luxf
*/
public class MD5ChangeUtile {
/**
* md5 16位 加密
*
* @param plainText
* @return
*/
public static String Md5_16(String plainText) {
StringBuffer buf = new StringBuffer("");
int i;
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(plainText.getBytes());
byte b[] = md.digest();
for (int offset = 0; offset < b.length; offset++) {
i = b[offset];
if (i < 0)
i += 256;
if (i < 16)
buf.append("0");
buf.append(Integer.toHexString(i));
}
System.out.println("result: " + buf.toString());// 32位的加密
System.out.println("result: " + buf.toString().substring(8, 24));// 16位的加密
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return buf.toString().substring(8, 24);
}
/**
* md5 32位 加密
*
* @param plainText
*/
public static String Md5_32(String plainText) {
StringBuffer buf = new StringBuffer("");
int i;
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(plainText.getBytes());
byte b[] = md.digest();
for (int offset = 0; offset < b.length; offset++) {
i = b[offset];
if (i < 0)
i += 256;
if (i < 16)
buf.append("0");
buf.append(Integer.toHexString(i));
}
System.out.println("result: " + buf.toString());// 32位的加密
System.out.println("result: " + buf.toString().substring(8, 24));// 16位的加密
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return buf.toString();
}
public static enum EncryptLength {
EL_16, EL_32
}
public static String calcMD5(String plainText, EncryptLength encryptLength) {
// 返回字符串
String md5Str = null;
try {
// 操作字符串
StringBuilder buf = new StringBuilder();
/**
* MessageDigest 类为应用程序提供信息摘要算法的功能,如 MD5 或 SHA 算法。
* 信息摘要是安全的单向哈希函数,它接收任意大小的数据,并输出固定长度的哈希值。
*
* MessageDigest 对象开始被初始化。 该对象通过使用 update()方法处理数据。 任何时候都可以调用
* reset()方法重置摘要。 一旦所有需要更新的数据都已经被更新了,应该调用digest()方法之一完成哈希计算。
*
* 对于给定数量的更新数据,digest 方法只能被调用一次。 在调用 digest 之后,MessageDigest
* 对象被重新设置成其初始状态。
*/
MessageDigest md = MessageDigest.getInstance("MD5");
// 添加要进行计算摘要的信息,使用 plainText 的 byte 数组更新摘要。
md.update(plainText.getBytes());
// 计算出摘要,完成哈希计算。
byte b[] = md.digest();
int i;
for (int offset = 0; offset < b.length; offset++) {
i = b[offset];
if (i < 0) {
i += 256;
}
if (i < 16) {
buf.append("0");
}
// 将整型 十进制 i 转换为16位,用十六进制参数表示的无符号整数值的字符串表示形式。
buf.append(Integer.toHexString(i));
}
switch (encryptLength) {
case EL_32:
md5Str = buf.toString();
break;
case EL_16:
md5Str = buf.toString().substring(8, 24);
break;
default:
md5Str = buf.toString().substring(8, 24);
break;
}
} catch (Exception e) {
Log.e(MD5ChangeUtile.class.getSimpleName(),e.getMessage());
}
return md5Str;
}
/**
* 默认的密码字符串组合,用来将字节转换成 16 进制表示的字符,apache校验下载的文件的正确性用的就是默认的这个组合
*/
protected static char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6',
'7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
protected static MessageDigest messagedigest = null;
static {
try {
messagedigest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException nsaex) {
nsaex.printStackTrace();
}
}
/**
* 生成字符串的md5校验值
*
* @param s
* @return
*/
public static String getMD5String(String s) {
return getMD5String(s.getBytes());
}
/**
* 判断字符串的md5校验码是否与一个已知的md5码相匹配
*
* @param password
* 要校验的字符串
* @param md5PwdStr
* 已知的md5校验码
* @return
*/
public static boolean checkPassword(String password, String md5PwdStr) {
String s = getMD5String(password);
return s.equals(md5PwdStr);
}
/**
* 生成文件的md5校验值
*
* @param file
* @return
* @throws IOException
*/
public static String getFileMD5String(File file) throws IOException {
InputStream fis;
fis = new FileInputStream(file);
byte[] buffer = new byte[1024];
int numRead = 0;
while ((numRead = fis.read(buffer)) > 0) {
messagedigest.update(buffer, 0, numRead);
}
fis.close();
return bufferToHex(messagedigest.digest());
}
public static String getMD5String(byte[] bytes) {
messagedigest.update(bytes);
return bufferToHex(messagedigest.digest());
}
private static String bufferToHex(byte bytes[]) {
return bufferToHex(bytes, 0, bytes.length);
}
private static String bufferToHex(byte bytes[], int m, int n) {
StringBuffer stringbuffer = new StringBuffer(2 * n);
int k = m + n;
for (int l = m; l < k; l++) {
appendHexPair(bytes[l], stringbuffer);
}
return stringbuffer.toString();
}
private static void appendHexPair(byte bt, StringBuffer stringbuffer) {
char c0 = hexDigits[(bt & 0xf0) >> 4];// 取字节中高 4 位的数字转换, >>>
// 为逻辑右移,将符号位一起右移,此处未发现两种符号有何不同
char c1 = hexDigits[bt & 0xf];// 取字节中低 4 位的数字转换
stringbuffer.append(c0);
stringbuffer.append(c1);
}
}
ServiceRulesException
package com.zte.general_project.ui.exception;
/**
* Author: Lucifer
*
* Created Date:2015-3-7
* Copyright @ 2015 BU
* Description:自定义Exception
*
* History:
*/
public class ServiceRulesException extends Exception {
private static final long serialVersionUID = 7674369722371197535L;
public ServiceRulesException(String msg) {
super(msg);
}
}
到此结束 需要注意的是(注意在清单文件中添加读写权限哦) 6。0以上需要动态获取权限哦