自从离开校园,在工资低下的日子里面,依然决然的选择了Android开发的队伍,那个时候Android 开发是最流行也是最香的时候,所以去一个公司工作,相对简单一些,至此,坚持Android开发6个年头,从几个人开发一个App,到最后一个人开发一个App的过程,至此自己解决问题,版本更新再到bug修复,再到上线都是一个漫长的过程。
那个时候上架还是相对简单的,但是市场多啊,各个市场都要上传一遍,也要耽误半天的时间,修改bug ,在发布版本,确实是一个过程,尤其遇到紧急的bug,修复更难了。
当时还有bugly,还能用,我还可以进行版本更新提示,虽然但是热更新还不是很熟悉,但是一直想做个热修复功能,但是有些项目是外包,有些是用户量不大的App,再就是频繁的跳槽,当刚会一些热更新和版本更新的接口的时候,就跳到其他公司里面了,导致这个版本更新就更难了。自己所做的就是从零开始,并且有时候因为业务放弃一些东西。
这次不放弃了,念念不忘的功能要实现自己去开发一个版本更新系统。
Android 端
Android 端先调用更新接口在启动ui,在进行是全量更新还是热更新,进行不同的操作,这里我先写的是全量更新。这样好理解。在进行下载,在启动安装功能。
后台,进行apk 上传,如果包名没有存在数据库中,我们就认为是一个新的App,从而进行创建一个应用,并上传包,设为最新的版本了,如果存在了,就只直接上传apk,在根据包里面的版本信息,保存起来,并设为最新版本。相同版本的,安装最后一次上传的版本为主;等细节处理。
至此业务逻辑就结束了。
主要用到什么技术呢?
- Android kotlin
- MVC
- Spring Boot
- MybitisPlus
- Vue3 + TS + Element Plus + Vite
Android 基础的UI 界面
Android 源码部分在Ruoyi-Android-App这里面。根据第三方框架改造的https://gitee.com/xuexiangjys/XUpdat
接口性和扩展性都不错的。
测试版本更新
json 数据
{
"Code": 0,
"Msg": "",
"UpdateStatus": 2,
"VersionCode": 2,
"VersionName": "1.0.0",
"UploadTime": "2023-07-10 17:28:41",
"ModifyContent": "\r\n1、优化api接口。\r\n2、优化更新提示界面。",
"DownloadUrl": "https://gitee.com/OptimisticDevelopers/Ruoyi-Android-App/raw/master/api/app-release.apk",
"ApkSize": 8086648,
"ApkMd5": "28845340c7c5fcc0259a5920c90800eb"
}
这样基本上最简单的版本更新;通过updateStatus 来判断是否为强制更新还是普通更新,同VersionCode 和本地版本比对,是否要进行版本更新,来更新下载,然后在提示自动下载来安装。
但这个符合最初的版本更新,我想要的是,从后台上传,然后再设置是版本更新,还是热更新,所以自己独立学习Spring Boot Vue3 等为App接口开发做准备。
后台管理
先进行数据库设计
表结构
DROP TABLE IF EXISTS `app_version`;
CREATE TABLE `app_version` (
`app_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'AppID',
`app_key` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'App API Key',
`app_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '应用名字',
`app_introduce` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'App介绍',
`sort` smallint(6) NULL DEFAULT NULL COMMENT '排序',
`platform` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '1 android 2 ios 3 phone_web 4 小程序 5 pc',
`statue` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '状态:0已上架 1已下架 ',
`del_flag` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '删除标记 0 正常 1 删除',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建者',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新者',
`remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`app_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'App 的版本' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of app_version
-- ----------------------------
INSERT INTO `app_version` VALUES (12,'1234567776666555', 'QQQ', NULL, NULL, '1', '0', '0', NULL, NULL, NULL, NULL, NULL);
-- ----------------------------
-- Table structure for app_version_edition
-- ----------------------------
DROP TABLE IF EXISTS `app_version_edition`;
CREATE TABLE `app_version_edition` (
`edition_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键版本ID',
`app_id` bigint(20) NULL DEFAULT NULL COMMENT 'AppID',
`app_name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'App名字',
`app_package` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'App包名',
`app_version_code` bigint(20) NULL DEFAULT 0 COMMENT 'App版本号',
`app_version_name` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'App显示版本名',
`app_min_version` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '支持的最低版本',
`icon_file_id` bigint(20) NULL DEFAULT NULL COMMENT '文件id',
`app_icon` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'App桌面ICON url地址',
`app_version_introduce` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '版本更新介绍',
`app_random_short` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '详情地址',
`app_file_id` bigint(20) NULL DEFAULT NULL COMMENT '文件id',
`app_donwload_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '下载地址url地址',
`app_donwload_number` bigint(20) NULL DEFAULT 0 COMMENT '下载次数',
`state` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '0预上传1正常',
`upload_status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '0' COMMENT '0普通更新 1强制更新',
`del_flag` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '删除标记 0 正常 1 删除',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建者',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新者',
`remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '说明',
PRIMARY KEY (`edition_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'App版本记录' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of app_version_edition
-- ----------------------------
INSERT INTO `app_version_edition` VALUES (8, 12, 'QQ', 'com.zzz', 0, '2.4.0', '21', 42, 'http://localhost:8089/profile/upload/2023/07/11\\202307111535471212.png', NULL, NULL, 43, 'http://localhost:8089/profile/upload/2023/07/11/QQ_v2.4.0_2023_05_29_221_20230711153553A009.apk', 1, '0', '0', '0', '2023-07-11 15:35:54', 'admin', NULL, NULL, NULL);
后台配置和上传app
实现了界面如下:
这个换号需要手动输入换行标签。衰了
整体流程如下,先创建一个应用签名,在上传一个应用,获取AppKey,在走更新接口。
管理员只需要一个apk,通过后台上传到服务器上,服务器上进行apk解析,对apk 里面数据 保存起来,保存数据有,app名字,版本号,权限信息、图标,在上传到oss里面给出下载地址。然后生成一个app_key 值,给app端。app端,通过这个key值,获取最新版本,然后再显示版本升级,是下载还是略过等操作。
后台有个逻辑是,同版本的按照最新版本为主。
app 获取最新版本,是最大版本的,最新App的版本为最新版本处理。
推广页面一个静态html 展示
目前就想到这么多。
ios 其实也使用,目前没有ios 版本更新UI.功能
热更新部分在 ,想加入热更新部分,用tinker来处理,发现成功率不是很高。
我考虑用增量更新来做。