Android 实现一个检查版本更新功能(适配到8.0+)
作为一个app,如果要长期使用,我们是要对它的版本进行更新迭代的,记录一下,网上参考一个一下别人的检查更新的做法,然后自己修改成自己需要的。
我们可以看一些效果图:
以上是效果图
我们还是看回自己的代码,布局那些就不放上来了,自己可以随便撸一个自己喜欢的样式出来。
这个是我的检查更新按钮:
case R.id.ll_auto_update:
//更新方法
auto_update();
break;
1.auto_update()这个方法里,我去调用服务器上有apk 的接口,请求获得返回 版本号信息,apk下载链接,版本内容介绍。(代码不可以复制使用,可以参考),重要的是拿到接口返回来的apk下载链接。
//更新版本信息
private void auto_update() {
String url = "XXXXXXXXXXXXXX";
//获取本地内部版本好
final int vcode = PackageUtils.getVersionCode(getContext());
Map<String, String> map = new HashMap<>();
map.put("XXXXX", "XXXXX");
//调用封装好的网络请求,返回json格式
OkHttpRequest.getInstance().getRequest(url, map, getContext(), new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
try {
ResponseModer responseModer = (ResponseModer) msg.obj;
JSONObject jsonObject = responseModer.getJsonResultData();
System.out.println("asdad" + jsonObject);
String version = jsonObject.getString("version");
//重要的是拿到下载apk链接
String update_url = jsonObject.getString("update_url");
int verion_int = jsonObject.getInt("verion_int");
String ver_introduction = jsonObject.getString("ver_introduction");
System.out.println("外部版本号==" + version);
System.out.println("下载链接==" + update_url);
System.out.println("内部版本号==" + verion_int);
System.out.println("版本介绍==" + ver_introduction);
if (verion_int <= vcode) {
Util.showToast(getContext(), "现在是最新的版本");
} else {
// Util.showToast(getContext(), "检查到有新版本信息更新");
showUpdateDialog();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
这里面去获取当前apk的信息,拿到当前的版本信息,我是通过一个(PackageUtils)类去获取的。
public class PackageUtils {
/**
* 获取版本名称
*
* @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;
}
/**
* 获取App的名称
*
* @param context 上下文
*
* @return 名称
*/
public static String getAppName(Context context) {
PackageManager pm = context.getPackageManager();
//获取包信息
try {
PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(), 0);
//获取应用 信息
ApplicationInfo applicationInfo = packageInfo.applicationInfo;
//获取albelRes
int labelRes = applicationInfo.labelRes;
//返回App的名称
return context.getResources().getString(labelRes);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
//获取本地内部版本号
final int vcode = PackageUtils.getVersionCode(getContext());
跟服务器返回接口的内部版本号(verion_int ) 进行比较;
服务器上的内部版本号大于本地的时候,我们在去拿到apk下载链接 去执行下一步的操作。
2.showUpdateDialog();这个方法,来处理;
/**
* 点击下载弹框
*/
private void showUpdateDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("检测到新版本");
builder.setMessage("版本介绍:\n" + ver_introduction);
builder.setPositiveButton("以后再说", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
}).setNegativeButton("立即更新", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
showDownloadDialog();
}
});
builder.show();
}
弹出窗提示,版本介绍内容,当点击立即更新时,我们再进去下一步的下载操作。
3.showDownloadDialog(); 下载进度;
/*
* 显示正在下载对话框
*/
protected void showDownloadDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("下载中");
View view = LayoutInflater.from(getContext()).inflate(R.layout.dialog_progress, null);
mProgressBar = view.findViewById(R.id.id_progress);
builder.setView(view);
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 隐藏当前对话框
dialog.dismiss();
// 设置下载状态为取消
mIsCancel = true;
}
});
mDownloadDialog = builder.create();
mDownloadDialog.show();
// 下载文件
downloadAPK();
}
/* 开启新线程下载apk文件
*/
private void downloadAPK() {
new Thread(new Runnable() {
@Override
public void run() {
try {
mIsCancel = false;
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
String sdPath = Environment.getExternalStorageDirectory() + "/";
// 文件保存路径
mSavePath = sdPath + "lianzhandownload";
File dir = new File(mSavePath);
if (!dir.exists()) {
dir.mkdir();
}
// 下载文件
HttpURLConnection conn = (HttpURLConnection) new URL(update_url).openConnection();
conn.connect();
InputStream is = conn.getInputStream();
int length = conn.getContentLength();
File apkFile = new File(mSavePath, version);
FileOutputStream fos = new FileOutputStream(apkFile);
int count = 0;
byte[] buffer = new byte[1024];
while (!mIsCancel) {
int numread = is.read(buffer);
count += numread;
// 计算进度条的当前位置
mProgress = (int) (((float) count / length) * 100);
// 更新进度条
mUpdateProgressHandler.sendEmptyMessage(1);
// 下载完成
if (numread < 0) {
mUpdateProgressHandler.sendEmptyMessage(2);
break;
}
fos.write(buffer, 0, numread);
}
fos.close();
is.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
开启线程介绍;下载进度更新ui显示:
/**
* 接收消息
*/
private Handler mUpdateProgressHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
// 设置进度条
mProgressBar.setProgress(mProgress);
break;
case 2:
// 隐藏当前下载对话框
mDownloadDialog.dismiss();
// 安装 APK 文件
installAPK();
}
}
};
当下载完成之后,我们再去安装新版的apk:
我们要注意文件清单添加相应的权限:
<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" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
如果没有添加到最后一条的权限,8.0下载完不会跳转获取apk安装。安装之前还要做一下的处理https://blog.****.net/zhaihaohao1/article/details/81809110参考别人的方法。
4。 installAPK()方法;
/*
* 下载到本地后执行安装
*/
protected void installAPK() {
File apkFile = new File(mSavePath, version);
if (!apkFile.exists()) {
return;
}
Intent intent = new Intent(Intent.ACTION_VIEW);
//判断是否是AndroidN以及更高的版本
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri contentUri = FileProvider.getUriForFile(getContext(), BuildConfig.APPLICATION_ID + ".fileProvider", apkFile);
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
} else {
intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
getActivity().startActivity(intent);
}
文件清单多加
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="包名.fileProvider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
3、打开file_paths.xml文件添加如下内容
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path="包名/" name="fileProvider" />
<external-path path="." name="apk下载文件夹名" />
</paths>
path:需要临时授权访问的路径(.代表所有路径)
name:就是你给这个访问路径起个名字
然后再去调用installAPK()。到这里就基本上就可以了。这是我修改了部分代码。如果你还是看不懂,你可以参考下别人的
https://blog.****.net/zhaihaohao1/article/details/81808902
每个人的需求不一定相同,但大致的方向还是一样的,我们可以参考别的踩过的坑,避免再去踩,当然目前这样的方式还是多少会存在不足,但我们可以实现之前,有了大致的思路,我们再去深入学习探讨,这样的学习方式也是不错的,由于本人知识有限,上面的东西没过多的详细说明,只是简单的说明。如有什么问题,可在评论区留意,我们一起探讨学习,谢谢。