安卓实现APP自动检测软件版本并提示更新
前言
当我们在做安卓项目的时候,客户的需求往往难免会发生变动。但是我们的产品已经上线了,却又需要修改的话我们该怎么办呢?也许很多应用商店已经集成了这个功能,只需要开发者上传新的APK文件即可,应用商店会自动进行提醒用户进行应用更新。可是对于那些因可能不想写申请著作权相关的文件又或着产品急于上线而无法上线到应用商店的APP又该怎么办呢?(这里提一句:绝大多数应用商店在开发者发布应用的时候需要提供软件的著作权,而申请软著则需要写一些相关的文件,然后提交上去之后还需要等待审核人员对材料进行审核,审核通过了才会给你发软件的著作权,但是这个审核期通常要大约一个月)没办法,就只能靠我们自己实现。其实自己实现也不是特别难。接下来我们来看如何对其进行实现吧。
效果图
Tips:这里只改了服务器中的版本号而已,并没有放新的APK上去,所以图中显示的是 版本 1.0.1 → 1.0.1
实现思路
其实实现的思路很简单,就是在打开APP的时候首先从服务器中去获取保存的版本号,然后再获取软件本身的版本号并与服务器版本号进行比较,若相同,则不做任何事,若不相同,则弹出版本更新的提示框去提示用户进行更新。用户如果点击更新则软件就去放在服务器中的APK资源,下载完毕后进行安装,这样我们就完成了软件的自动检测版本更新功能。
准备事项
① 服务器数据库中保存服务器中的软件版本号。
② 返回服务器数据库中版本号的后台接口。
③ 服务器中tomcat中放入软件的APK文件。
④ APP获取软件本身版本号以及弹出版本更新弹窗并下载服务器中APK文件功能。
接下来我们来一一实现
① 数据库保存版本号
相信这个对于绝大多数人来说并不难,直接在数据库中创建一个表和一个字段即可。这里放下我自己创建的数据库表供大家参考。
② 返回服务器数据库中版本号的后台接口
这个对于Java程序员来说简直是易容反掌。就是返回服务器版本号Json数据的Servlet而已。相信对于大多数人来说也不难。这里也就不再详细说明了。
③ 服务器中tomcat中放入软件的APK文件
这里的意思就是大家要把更新时所需的APK资源给用户准备好,以便用户在进行更新的时候能够访问并下载到最新版本的APK文件供用户安装。这里只需要大家把最新版本的APK文件放在服务器的tomcat的如下路径(Tomacat/webapps/ROOT)下即可。访问地址为:服务器地址 + / + apk文件名,如图中的地址为:http://183.66.246.214:9420/BluetoothSPP.apk
Tips:当用户访问该网址,即可进行下载该APK文件。
④ APP获取软件本身版本号以及弹出版本更新弹窗并下载服务器中APK文件功能。
【1】APP获取软件本身版本号
不知道大家在写安卓软件的时候有没有注意到在项目的build.gradle文件中就包含着该项目的版本号以及版本名的内容。如下图所示:
既然软件自身的版本号以及版本名都已经知道在哪里了,那么接下来的任务就是获取到它就行了。
//获取软件版本号
public String getVersionCode(Context context)
{
try {
String pkName = context.getPackageName();
String versionName = context.getPackageManager().getPackageInfo(
pkName, 0).versionName;
int versionCode = context.getPackageManager().getPackageInfo(
pkName, 0).versionCode;
return "V" + versionCode + "_" + versionName;
}
catch (Exception e)
{
Log.d(TAG, "getVersionCode: " + e.getMessage());
e.printStackTrace();
}
return null;
}
【2】弹出版本更新弹窗并下载服务器中APK文件
这个功能相比上一个获取版本号的功能来说相对复杂一点,但实现的不是太难。首先弹出提示窗,这个重写一下AlertDialog就能实现。并且能够制定自己想要的弹出界面。接着就是下载服务器中的APK文件,这个也不是很难,直接用一个服务(Server)进行下载即可。其实呢,这两个功能是有一些大佬早已集成在了一起,界面和功能呢也做的很成熟稳定了。所以这里我们不妨直接使用这些大佬已经弄好的接口来进行实现,这样既稳定又便捷。 在这里要感谢提供这一接口的大佬,大佬的gitHub项目地址 → 传送门
注意:大家需要详细阅读项目下的README.md文件内容来进行使用,这样才不会出错。
我是用的java版本的,下面给出我这部分的核心代码。
//获取服务器保存的版本号
public void GetServerVersionInfo()
{
new Thread(new Runnable() {
@Override
public void run() {
//通过访问后台接口来获取保存在数据库中的版本号内容
//将返回的json数据解析出来并进行判断处理
try {
OkHttpClient client = new OkHttpClient();
RequestBody requestBody = new FormBody.Builder()
.build();
Request request = new Request.Builder()
.url("http://183.66.246.214:9420/cloundctrl/user/getSoftware2")
.post(requestBody)
.build();
Response response = client.newCall(request).execute();
String responseData = response.body().string();
JSONObject jsonObject = new JSONObject(responseData);
//获取到返回的状态值 json数据的code项
String code = jsonObject.getString("code");
Log.d(TAG, "run: code的值为: " + code);
if(code.equals("200"))
{
String data = jsonObject.getString("data");
JSONObject dataJsonObject = new JSONObject(data);
Log.d(TAG, "run: data为 " + data);
String id = dataJsonObject.getString("id");
Log.d(TAG, "run: id为 " + id);
String versionCode = dataJsonObject.getString("versionCode");
Log.d(TAG, "run: versionCode为" + versionCode);
String versionName = dataJsonObject.getString("versionName");
Log.d(TAG, "run: versionName为 " + versionName);
//获取到本身的apkVersionCode和apkVersionName
String versionInfo = getVersionCode(MainActivity.this);
String serverVersionInfo = "V" + versionCode + "_" + versionName;
//如果俩不相等则进行提示升级
if(!versionInfo.equals(serverVersionInfo))
{
VarsOfUpdate.setUpdateTitle("发现新版本V" + versionName);
VarsOfUpdate.setVersionName("V" +versionName);
//进行升级
UpdateConfig updateConfig1 = new UpdateConfig();
updateConfig1.setCheckWifi(true);
updateConfig1.setNotifyImgRes(R.drawable.ic_update_logo);
//是否强制更新(取出取消更新按钮)
//updateConfig.setForce(true);
updateConfig1.setAlwaysShowDownLoadDialog(true);
UiConfig uiConfig1 = new UiConfig();
uiConfig1.setUiType(UiType.CUSTOM);
uiConfig1.setCustomLayoutId(R.layout.view_update_dialog_custom);
Log.d(TAG, "onClick: 运行到了这里!");
UpdateAppUtils
.getInstance()
.apkUrl(VarsOfUpdate.getApkUrl())
.updateConfig(updateConfig1)
.uiConfig(uiConfig1)
.setOnInitUiListener(new OnInitUiListener() {
@Override
public void onInitUpdateUi(View view, UpdateConfig updateConfig, final UiConfig uiConfig) {
TextView tv_updateTitle;
TextView tv_versionName;
TextView tv_updateContent;
TextView btn_updateSure;
ImageView imageView_updateCancel;
tv_updateTitle = (TextView)view.findViewById(R.id.tv_update_title);
tv_versionName = (TextView)view.findViewById(R.id.tv_version_name);
tv_updateContent = (TextView)view.findViewById(R.id.tv_update_content);
// public static String apkUrl = "http://183.66.246.214:9420/BluetoothSPP.apk";
//
// public static String updateTitle = "发现新版本V1.0.0";
// //更新内容
// public static String updateContent = "1、控制更加智能\n2、参数一目了然\n3、在线升级不是问题\n4、更多功能等你探索";
// //更新版本名称
// public static String versionName = "1.0.0";
tv_updateTitle.setText(VarsOfUpdate.getUpdateTitle());
tv_versionName.setText(VarsOfUpdate.getVersionName());
tv_updateContent.setText(VarsOfUpdate.getUpdateContent());
}
})
.update();
}
}
}catch (Exception e)
{
e.printStackTrace();
Log.d(TAG, "run: 错误信息为 :" + e.getMessage());
//Toast.makeText(MainActivity.this,"网络异常,检查软件更新失败!", Toast.LENGTH_SHORT).show();
}
}
}).start();
}
最后
提醒大家一定要在项目的AndroidManifest.xml文件下加入如下用户权限
<uses-permission android:name="android.permission.INTERNET" />
以下是相关类库
//更新APP库
implementation 'com.teprinciple:updateapputils:2.3.0'
//AndroidX
//implementation 'com.teprinciple:updateapputilsx:2.3.0'
//访问互联网需要的库
implementation 'com.squareup.okhttp3:okhttp:4.5.0'