一般的安卓app都有自动更新功能,实现app的更新,以让用户体验新版本的功能,这里也是项目中用到的,今天就来总结一下。做和记录。
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.gwkj.qixiubaodian.Manifest;
import com.gwkj.qixiubaodian.R;
import com.gwkj.qixiubaodian.qxbd.SdCardUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* 版本更新
*/
public class UpdateManager extends SdCardUtils {
private Context mContext;
private String updateMsg = "发现新版本,请及时更新";// 提示语
private String apkurl = "";// 返回的安装包url//
private AlertDialogEx downloadDialog;// 下载提示
@SuppressLint("SdCardPath")
private static final String savePath1 = "/sdcard/App";// 保存路径
@SuppressLint("SdCardPath")
private static final String savePath = "/sdcard/App/updatedemo/";// 保存路径
private static final String saveFileName = "App.apk";
private ProgressBar mProgress;// 进度条
private static final int DOWN_UPDATE = 1;
private static final int DOWN_OVER = 2;
private int progress;
private Thread downLoadThread;
private boolean interceptFlag = false;
// 外部接口调用
public void checkUpdateInfo(String apkurl, String apkInfo) {
this.apkurl = apkurl;
this.updateMsg = apkInfo;
showNoticeDialog();
}
// 当有新版本提示示更新
public void showNoticeDialog() {
final AlertDialogEx alert = new AlertDialogEx(mContext);
alert.setTitle("软件版本更新");
alert.setMessage(updateMsg);
alert.setConfirmButton("立即更新", new AlertDialogEx.OnClickListener() {
@Override
public void onClick(AlertDialogEx dialog, int button) {
showDownloadDialog();
}
});
// alert.setCancelButton("暂不更新", null);
alert.show();
}
// 下载apk
public void showDownloadDialog() {
downloadDialog = new AlertDialogEx(mContext);
final LayoutInflater inflater = LayoutInflater.from(mContext);
View v = inflater.inflate(R.layout.pross, null);
mProgress = (ProgressBar) v.findViewById(R.id.progress);
downloadDialog.setTitle("软件更新");
downloadDialog.setCancelButton("取消更新", new AlertDialogEx.OnClickListener() {
@Override
public void onClick(AlertDialogEx dialog, int button) {
downloadDialog.dismiss();
interceptFlag = true;
}
});
downloadDialog.show();
downloadDialog.setContentView(v);
downloadApk();
}
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case DOWN_UPDATE:
mProgress.setProgress(progress);
break;
case DOWN_OVER:
downloadDialog.dismiss();
installApk();
break;
}
}
};
public UpdateManager(Context context) {
this.mContext = context;
}
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
"android.permission.READ_EXTERNAL_STORAGE",
"android.permission.WRITE_EXTERNAL_STORAGE"};
// 申请所需的权限
public static void verifyStoragePermissions(Context context) {
try {
//检测是否有写的权限
int permission = ActivityCompat.checkSelfPermission(context,
"android.permission.WRITE_EXTERNAL_STORAGE");
if (permission != PackageManager.PERMISSION_GRANTED) {
// 没有写的权限,去申请写的权限,会弹出对话框
ActivityCompat.requestPermissions((Activity) context, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 申请所需的权限
private Runnable mdownApkRunnable = new Runnable() {
@Override
public void run() {
try {
URL url = new URL(apkurl);
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
conn.connect();
int length = conn.getContentLength();
InputStream is = conn.getInputStream();
// 假如大于6.0申请所需的权限
if (Build.VERSION.SDK_INT >= 23) { //假如大于23则申请权限
verifyStoragePermissions(mContext);
if (SdCardUtils.checkSdCard() == true) {
SdCardUtils.createFileDir(SdCardUtils.FILEDIR);
SdCardUtils.createFileDir(SdCardUtils.FILEDIR + "/" + SdCardUtils.FILEPHOTO);
} else {
Toast.makeText(mContext, "创建文件夹失败SD卡不可用", Toast.LENGTH_LONG).show();
}
} else { //否则则直接创建文件夹
SdCardUtils.createFileDir(SdCardUtils.FILEDIR);
SdCardUtils.createFileDir(SdCardUtils.FILEDIR + "/" + SdCardUtils.FILEPHOTO);
}
File file1 = new File(savePath1);
if (!file1.exists()) {
file1.mkdir();
}
File file = new File(SdCardUtils.getSdApkPath());
if (!file.exists()) {
file.mkdir();
}
String apkFile = SdCardUtils.getSdApkPath() + "/" + saveFileName;
File ApkFile = new File(apkFile);
if (ApkFile.isFile() && ApkFile.exists()) {
ApkFile.delete();
}
ApkFile.createNewFile();
FileOutputStream fos = new FileOutputStream(apkFile);
int count = 0;
byte buf[] = new byte[1024];
do {
int numread = is.read(buf);
count += numread;
progress = (int) (((float) count / length) * 100);
// 更新进度
mHandler.sendEmptyMessage(DOWN_UPDATE);
if (numread <= 0) {
// 下载完成通知安装
mHandler.sendEmptyMessage(DOWN_OVER);
break;
}
fos.write(buf, 0, numread);
fos.flush();
} while (!interceptFlag);// 点击取消就停止下载.
fos.close();
is.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
};
// 下载apk
private void downloadApk() {
downLoadThread = new Thread(mdownApkRunnable);
downLoadThread.start();
}
// 安装apk
private void installApk() {
File apkFile = new File(SdCardUtils.getSdApkPath() + "/" + saveFileName);
if (!apkFile.exists()) {
return;
}
Intent i = new Intent(Intent.ACTION_VIEW);
// 新加的打开询问
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setDataAndType(Uri.parse("file://" + apkFile.toString()),
"application/vnd.android.package-archive");
mContext.startActivity(i);
}
}
Sd卡创建文件工具类;
import android.os.Environment;
import android.util.Log;
import java.io.File;
/**
* 创建文件工具类
* Created by admin on 2018/6/14.
*/
public class SdCardUtils {
private String[] permissions = new String[]{android.Manifest.permission.CAMERA,
android.Manifest.permission.READ_EXTERNAL_STORAGE,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE};
private static final int REQUEST_1 = 1;
// 项目文件根目录
public static final String FILEDIR = "QiXiuBaoDian";
// 项目APK目录
public static final String FILEPHOTO = "updatedemo";
// 应用程序图片存放
public static final String FILEIMAGE = "/images";
// 应用程序缓存
public static final String FILECACHE = "/cache";
// 用户信息目录
public static final String FILEUSER = "user";
private static String path;
/*
* 检查sd卡是否可用
* getExternalStorageState 获取状态
* Environment.MEDIA_MOUNTED 直译 环境媒体登上 表示,当前sd可用
*/
public static boolean checkSdCard() {
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED))
//sd卡可用
return true;
else
//当前sd卡不可用
return false;
}
/*
* 获取sd卡的文件路径
* getExternalStorageDirectory 获取路径
*/
public static String getSdPath() {
return Environment.getExternalStorageDirectory() + "/";
}
/*
* 创建一个文件夹
*/
public static void createFileDir(String fileDir) {
path = getSdPath() + fileDir;
File path1 = new File(path);
if (!path1.exists()) {
path1.mkdirs();
Log.i("yang", "我被创建了");
Log.e("path", path);
}
}
public static String getSdApkPath() {
return path;
}
}
应用:
/**
* 版本更新
*/
@SuppressLint("StaticFieldLeak")
class UpgradeTask extends AsyncTask {
@Override
protected UpgradeResponse doInBackground(Void... params) {
return DataInterface.upgradeResponse();
}
@Override
protected void onPostExecute(UpgradeResponse upgradeResponse) {
String packageName = getPackageName();
int versionCode = 0;
try {
versionCode = getPackageManager().getPackageInfo(packageName, 0).versionCode;
} catch (PackageManager.NameNotFoundException e) {
return;
}
if (upgradeResponse != null) {
int newver = upgradeResponse.getApp_ver();//新版本号
String sesc = upgradeResponse.getDesc();//更新内容
String apk = upgradeResponse.getUrl();//更新地址
if (versionCode < newver) {
UpdateManager updateManager = new UpdateManager(MainActivity.this);
updateManager.checkUpdateInfo(apk, sesc);
}
} else {
Toast.makeText(MainActivity.this, "服务器开小差啦,请稍后再试", Toast.LENGTH_SHORT).show();
}
}
}