flutter开发实战-应用更新apk下载、安装apk、启动应用实现
flutter开发实战-应用更新apk下载、安装apk、启动应用实现
在开发过程中,经常遇到需要更新下载新版本的apk文件,之后进行应用更新apk下载、安装apk、启动应用。我们在flutter工程中实现下载apk,判断当前版本与需要更新安装的版本进行比对判断,通过判断VersionCode来确定下载新版版APK
一、应用更新apk下载
当应用需要更新的时候,我们需要判断版本号,在flutter工程中versionCode是工程中的pubspec.yaml中的version确定的。
如version: 1.0.0+1
version为1.0.0,versionCode为1
需要我们获取接口,需要判断的就是versionCode确定是否需要下载apk。
1.1、获取新版本地址接口
获取新版本的接口使用的是Dio库。dio 是一个强大的 Dart HTTP 请求库,支持全局配置、Restful API、FormData、拦截器、 请求取消、Cookie 管理、文件上传/下载、超时以及自定义适配器等。
这里的请求为GET请求,
Response? response = await dio.get(requestUrl,queryParameters: params,options: Options(contentType: Headers.jsonContentType));
我这里就不写请求的逻辑了。
根据请求,获取到了
// 获取检查版本
Future<void> checkVersion() async {var params = {};ApiRepository.checkVersion(params: params,success: (response) {// {"version":"2","url":"http://wwww.laileshuo.com/download/myapp_v1.0.0_release.apk"}var object = response.object;if (object != null && (object is Map) && object.isNotEmpty) {String? versionCode = object['versionCode'];String? url = object['url'];// 判断是否需要下载更新String versionCodeStr = "";if (version != null) {versionCodeStr = "${versionCode}";}checkAppVersionUpdate(versionCodeStr: versionCodeStr, apkUrl: url);}print("checkVersion params:${params}, object:${object.toString()}");},failure: (error) {print("checkVersion params:${params}, error:${error.toString()}");});}
通过检查新版本接口获取到了url及versionCode,这里的versionCode和pubspec.yaml的进行比较看是否需要下载apk。
判断下载apk
Future<void> checkAppVersionUpdate({String? versionCodeStr, String? apkUrl}) async {try {if (versionCodeStr != null &&apkUrl != null &&versionCodeStr.isNotEmpty &&apkUrl.isNotEmpty) {String curVersionCodeStr = await PlatformUtils.getBuildNum();int versionCode = int.parse(versionCodeStr);int curVersionCode = int.parse(curVersionCodeStr);if (versionCode > curVersionCode) {// 需要更新的版本code,大于当前的版本才更新}}} catch (e) {print("appVersionUpdate apkUrl:${apkUrl}, version:${version}, exception:${e.toString()}");}}
1.2、下载Apk
在判断需要更新的时候,我们需要下载新版本的apk。下载的库我们使用的也是Dio。
下载的代码可参考https://blog.csdn.net/gloryFlow/article/details/131658621
当获取到新版的下载地址url时候,需要下载apk
void downApk(String url, String saveDestPath) {HttpApi().doDownload(url, saveDestPath, cancelToken: CancelToken(),progress: (int received, int total) {// 下载进度setState(() {_downloadRatio = (received / total);if (_downloadRatio == 1) {_downloading = false;}_downloadIndicator = (_downloadRatio * 100).toStringAsFixed(2) + '%';});}, completion: () {// 下载成功FlutterLoadingHud.showToast(message: "\"下载完成\"");}, failure: (error) {// 下载出错FlutterLoadingHud.showToast(message: error.message);});
}
下载完成后可以执行安装并且启动操作了。
二、APK安装及启动
APK安装及启动需要原生插件来实现。
2.1、创建原生插件flutter_package_manager
创建flutter plugin,我使用的工具是Android studio。
配置如下内容:
- Project name
- Project location
- Description
- Project type: Plugin
- Android language
- iOS language
- Platforms
如图所示
我们需要实现installThenStart
/// An implementation of [FlutterPackageManagerPlatform] that uses method channels.
class MethodChannelFlutterPackageManager extends FlutterPackageManagerPlatform {/// The method channel used to interact with the native platform.final methodChannel = const MethodChannel('flutter_package_manager');Future<String?> getPlatformVersion() async {final version = await methodChannel.invokeMethod<String>('getPlatformVersion');return version;}Future<void> installThenStart(String apkFilePath, String activity) async {final result = await methodChannel.invokeMethod<void>('installThenStart');return result;}
}
可以看到定义了installThenStart,需要apkFilePath与activity作为参数。
在Android端实现,由于我这边需要静默安装(apk在后台安装,不出现安装界面的提示)
public class FlutterPackageManager implements MethodCallHandler {private static final String TAG = "FlutterPackageManager";private final Registrar registrar;/*** Plugin registration.*/public static void registerWith(Registrar registrar) {final MethodChannel channel = new MethodChannel(registrar.messenger(), "flutter_package_manager");channel.setMethodCallHandler(new FlutterPackageManager(registrar));}private FlutterPackageManager(Registrar registrar) {this.registrar = registrar;} public void onMethodCall(MethodCall call, Result result) {if (call.method.equals("getPlatformVersion")) {result.success(android.os.Build.VERSION.RELEASE);} else if (call.method.equals("installThenStart")) {String path = call.arguments['filePath'];String activity = call.arguments['activity'];installApk(path, activity);} else {result.notImplemented();}}void installApk(String path, String activity) {// root权限静默安装实现 实现实际使用的是su pm install -r filePath命令。Process process = null; OutputStream out = null; InputStream in = null; try { // 请求root process = Runtime.getRuntime().exec("su"); out = process.getOutputStream(); // 调用安装 out.write(("pm install -r " + path + "\n").getBytes()); in = process.getInputStream(); int len = 0; byte[] bs = new byte[256]; while (-1 != (len = in.read(bs))) { String state = new String(bs, 0, len); if (state.equals("Success\n")) { //安装成功后的操作 startActivity(activity);} } } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (out != null) { out.flush(); out.close(); } if (in != null) { in.close(); } } catch (IOException e) { e.printStackTrace(); } } }void startActivity(String activity) {// activity格式为'com.laileshuo.app/com.laileshuo.app.MainActivity'Intent mIntent = new Intent(); val componentName = ComponentName(this, activity)val intent = Intent().setComponent(componentName)startActivity(intent)}
}
当然,工程中的AndroidManifest.xml也需要做相应的调整,如下
<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"package="com.laileshuo.app"><applicationtools:replace="android:label"android:label="我的应用"android:name="${applicationName}"android:icon="@mipmap/ic_launcher"><activityandroid:name="com.laileshuo.app.MainActivity"android:exported="true"android:launchMode="singleTop"android:theme="@style/LaunchTheme"android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"android:hardwareAccelerated="true"android:windowSoftInputMode="adjustResize"><!-- Specifies an Android theme to apply to this Activity as soon asthe Android process has started. This theme is visible to the userwhile the Flutter UI initializes. After that, this theme continuesto determine the Window background behind the Flutter UI. --><meta-dataandroid:name="io.flutter.embedding.android.NormalTheme"android:resource="@style/NormalTheme"/><intent-filter><action android:name="android.intent.action.MAIN"/><category android:name="android.intent.category.LAUNCHER"/></intent-filter></activity><!-- Don't delete the meta-data below.This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --><meta-dataandroid:name="flutterEmbedding"android:value="2" /></application>
</manifest>
2.2、如果非root环境安装,可以使用open_file插件
需要在pubspec.yaml引入插件
dependencies:open_file: ^3.3.2
在可以直接使用代码安装apk
import 'package:open_file/open_file.dart';OpenFile.open(apkFilePath);
当与关于FileProvider的其他插件发生冲突时,需要配置AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"package="xxx.xxx.xxxxx"><application>...<providerandroid:name="androidx.core.content.FileProvider"android:authorities="${applicationId}.fileProvider"android:exported="false"android:grantUriPermissions="true"tools:replace="android:authorities"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/filepaths"tools:replace="android:resource" /></provider></application>
</manifest>
三、小结
flutter开发实战-应用更新apk下载、安装apk、启动应用实现。在开发过程中,经常遇到需要更新下载新版本的apk文件,之后进行应用更新apk下载、安装apk、启动应用。我们在flutter工程中实现下载apk,判断当前版本与需要更新安装的版本进行比对判断,通过判断VersionCode来确定下载新版版APK。内容较多,描述可能不准确,请见谅。
https://blog.csdn.net/gloryFlow/article/details/133440529
学习记录,每天不停进步。
相关文章:

flutter开发实战-应用更新apk下载、安装apk、启动应用实现
flutter开发实战-应用更新apk下载、安装apk、启动应用实现 在开发过程中,经常遇到需要更新下载新版本的apk文件,之后进行应用更新apk下载、安装apk、启动应用。我们在flutter工程中实现下载apk,判断当前版本与需要更新安装的版本进行比对判断…...
DispatcherServlet初始化之Spring容器创建1.0
一、前言 在SpringMVC框架中,DispatcherServlet扮演着非常重要的角色,它负责接收所有的HTTP请求并将其分发给相应的处理器。在DispatcherServlet的初始化过程中,会创建一个Spring容器来管理应用程序中的Bean。 二、步骤 1、加载配置文件&a…...
CSS的基础
CSS美化HTML,布局网页 CSS最大的价值:由HTML专注去做结构呈现,样式给CSS,结构(HTML)与样式(CSS)相分离 CSS主要由选择器以及一条或多条声明 在<head></head>中实现CSS在<body…...

mathtype如何嵌入到word中?详细mathtype安装步骤教程
mathtype是一款功能特别强大的数学方式编辑软件,为用户提供各种强大的数学公式符号帮助用户进行计算,并且速度很快。有小伙伴知道mathtype如何嵌入到word中吗,这里小编就给大家详细介绍一下mathtype嵌入到word中的方法,有需要的小…...

云安全之访问控制的常见攻击及防御
访问控制攻击概述 访问控制漏洞即应用程序允许攻击者执行或者访问某种攻击者不具备相应权限的功能或资源。 常见的访问控制可以分为垂直访问控制、水平访问控制及多阶段访问控制 (上下文相关访问控制),与其相应的访问控制漏洞为也垂直越权漏洞(普通用户可以访问或…...

Java编程技巧:跨域
目录 1、跨域概念2、后端CORS(跨域资源共享)配置原理3、既然请求跨域了,那么请求到底发出去没有?4、通过后端CORS(跨域资源共享)配置解决跨域问题代码4.1、SpringBoot(FilterRegistrationBean&a…...

react create-react-app 配置less
环境信息: create-react-app:v5 react:18.2.0 node:18.16.0 如果你不必须使用 less 建议直接使用scss。 因为less配置会遇到很多问题。 配置less过程: 如果你只需要 sass的话,就可以直接使用sass。因为默认配置了scss。 npm、yarn、cnpm、…...

树的表示——孩子兄弟表示法
从图中可以看出,树的每个结点,都有不确定的指向他们的孩子的节点,如果我们定义这样一个结构体来便是数的结构的话: struct TreeNode { int val; struct TreeNodep1; struct TreeNodep1; … }; 是不能够表示一棵树的,因…...

Windows11安装MySQL8.1
安装过程中遇到任何问题均可以参考(这个博客只是单纯升级个版本和简化流程) Windows安装MySQL8教程-CSDN博客 到官网下载mysql8数据库软件 MySQL :: Download MySQL Community Server 下载完后,解压到你需要安装的文件夹 其中的配置文件内容了如下 [mysqld]# 设置3306端口po…...
Linux编程——经典链表list_head
1. 关于list_head struct list_head是Linux内核定义的双向链表,包含一个指向前驱节点和后继节点的指针的结构体。其定义如下: struct list_head {struct list_head *next, *prev; //双向链表,指向节点的指针 };1.1 链表的定义和初始化 有两…...

基于51单片机NEC协议红外遥控发送接收仿真设计( proteus仿真+程序+原理图+报告+讲解视频)
基于51单片机NEC协议红外遥控发送接收仿真设计 讲解视频1.主要功能:2.仿真3. 程序代码4. 原理图5. 设计报告6. 设计资料内容清单&&下载链接 基于51单片机NEC协议红外遥控发送接收仿真设计 51单片机红外发送接收仿真设计( proteus仿真程序原理图报告讲解视频…...

Jmeter分布式压力测试
目录 1、场景 2、原理 3、注意事项 4、slave配置 5、master配置 6、脚本执行 1、场景 在做性能测试时,单台机器进行压测可能达不到预期结果。主要原因是单台机器压到一定程度会出现瓶颈。也有可能单机网卡跟不上造成结果偏差较大。 例如4C8G的window server机…...
Rust :mod.rs和lib.rs中use的作用
一、mod.rs和lib.rs mod.rs往往是把同一目录下的n个rs文件综合在一起的有效方式; lib.rs是一个库或子库层次综合在一起的有效方式; 下面举个实例来说明。生成一个rusttoc本地库(由cargo new rusttoc --lib所生成),目录…...

ISP图像信号处理——平场校正介绍以及C++实现
参考文章1:http://t.csdn.cn/h8TBy 参考文章2:http://t.csdn.cn/6nmsT 参考网址3:opencv平场定标 - CSDN文库 平场校正一般先用FPN(Fixed Pattern Noise)固定图像噪声校正,即暗场校正;再用PRNU(Photo Response Non Uniformity)…...

【深入了解Java String类】
目录 String类 常用方法 字符串的不可变性 String的内存分析 StringBuilder类 解释可变和不可变字符串 常用方法 面试题:String,StringBuilder,StringBuffer之间的区别和联系 String类的OJ练习 String类 【1】直接使用,…...

基于SpringBoot的知识管理系统
目录 前言 一、技术栈 二、系统功能介绍 用户管理 文章分类 资料分类 文章信息 论坛交流 资料下载 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息互联网信息的飞速发展,无纸化作业变成了一种趋势,针对这个问题开发一个…...
Pytorch基础:Tensor的reshape方法
在Pytorch中,reshape是Tensor的一个重要方法,它与Numpy中的reshape类似,用于返回一个改变了形状但数据和数据顺序和原来一致的新Tensor对象。注意:此时返回的数据对象并不一定是新的,这取决于应用此方法的Tensor是否是…...

【数据库——MySQL】(13)过程式对象程序设计——存储函数、错误处理以及事务管理
目录 1. 存储函数2. 存储函数的应用3. 错误处理4. 抛出异常5. 事务处理6. 事务隔离级7. 应用实例参考书籍 1. 存储函数 要 创建 存储函数,需要用到 CREATE 语句: CREATE FUNCTION 存储函数名([参数名 类型, ...])RETURNS 类型[存储函数体]注意࿱…...

Spring Boot的魔法:构建高性能Java应用
文章目录 Spring Boot:简化Java开发Spring Boot的性能优势1. 内嵌服务器2. 自动配置3. 起步依赖4. 缓存和优化5. 异步处理 实际示例:构建高性能的RESTful API总结 🎉欢迎来到架构设计专栏~Spring Boot的魔法:构建高性能Java应用 ☆…...
如何做好测试?(七)兼容性测试 (Compatibility Testing, CT)
1. 兼容性测试介绍 兼容性测试 (Compatibility Testing, CT)是一种软件测试方法,旨在验证应用程序在不同操作系统、浏览器、设备和网络环境下的正确运行和一致性。对于网上购物系统来说,兼容性测试非常重要,因为用户可能使用各种不同的设备和…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...

ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...