在Flutter中使用Install_Plugin安装APK

目录

      • 前言
      • 添加依赖
      • 添加权限
      • 下载APK
      • 安装APK

前言

在开发Flutter应用时,有时候我们需要实现在应用内部安装APK的功能。众所周知,Android 7.0以后由于改变了文件URI的访问方式,我们需要使用FileProvider来创建一个content://URI来授予临时访问权限。

Flutter不同与原生,在Flutter中要么自己手写插件调用原生代码进行安装APK,要么找个第三方库来实现该功能,本人能力有限就简单介绍并使用本文的主角install_plugin来实现该功能吧。

添加依赖

首先,你需要在你的pubspec.yaml文件中添加install_plugin的依赖:

dependencies:install_plugin: ^2.1.0

然后执行flutter pub get获取依赖。

去官网查看最新版本 >>> https://pub.dev/packages/install_plugin

添加权限

<!-- read permissions for external storage --><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- installation package permissions -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<!-- write permissions for external storage -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

在Android 7.0(API级别24)以后,由于改变了文件URI的访问方式,为了应用间共享文件,如安装APK,需要使用FileProvider来创建一个content://URI来授予临时访问权限。

在项目中的android/app/src/main/AndroidManifest.xml文件中的标签内添加配置,如下:

<application ...>...<providerandroid:name="androidx.core.content.FileProvider"android:authorities="${applicationId}.fileprovider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_paths" /></provider><!-- ${applicationId}会被替换为你的应用ID --><!-- android:resource="@xml/file_paths"指定了存放共享文件路径的资源文件。 -->
</application>

接下来,在android/app/src/main/res/目录下创建xml文件夹(有则不用创建),然后在xml文件夹下创建file_paths.xml文件,指定共享文件的路径:

<?xml version="1.0" encoding="utf-8"?>
<resources><paths><root-path name="root" path="" /><files-path name="files" path="" /><cache-path name="cache" path="" /><external-path name="external" path="" /><external-files-path name="external_files" path="" /><external-cache-path name="external_cache" path="" /></paths>
</resources>

下载APK

  Future<void> _download() async {try {setInitDir(initStorageDir: true);await DirectoryUtil.getInstance();DirectoryUtil.createStorageDirSync(category: 'Download');final String path = DirectoryUtil.getStoragePath(fileName: 'my', category: 'Download', format: 'apk') ?? '';Log('_download path -> $path ');//path  -> storage/emulated/0/Android/data/com.xxx.xxx/files/Download/my.apkfinal File file = File(path);/// 链接可能会失效await Dio().download('http://imtt.dd.qq.com/16891/apk/FF9625F40FD26F015F4CDED37B6B66AE.apk',file.path,cancelToken: _cancelToken,onReceiveProgress: (int count, int total) {if (total != -1) {//更新界面进度_value = count / total;setState(() {});if (count == total) {_installApk(path);}}},);} catch (e) {XToast.show('下载失败!');debugPrint(e.toString());setState(() {_isDownload = false;});}}

此处初始化存储文件路径使用的工具类库是:https://github.com/Sky24n/flustars

安装APK

  • ANDROID
  _installApk(String path) {//换成你的apk包名InstallPlugin.installApk(path, appId: 'com.xxx.xxx.fileprovider').then((result) {print('install apk $path success: $result');}).catchError((error) {print('install apk $path fail: $error');});}

注意: 以上流程仅在Android中有效,iOS不支持此操作。另外,如果你的应用是从Google Play商店下载的,Google可能会阻止用户从应用内部安装APK,所以可能需要考虑使用应用市场的安装方式。

  • IOS
  final String _defaultUrl = 'https://itunes.apple.com/cn/app/%E5%86%8D%E6%83%A0%E5%90%88%E4%BC%99%E4%BA%BA/id1375433239?l=zh&ls=1&mt=8';///跳转苹果应用商店_gotoAppStore(String url) async {url = url.isEmpty ? _defaultUrl : url;final res = await InstallPlugin.install(url);Log("go to appstroe ${res['isSuccess'] == true ? 'success' : 'fail:${res['errorMessage'] ?? ''}'}");}

打完收工!


这就是关于如何在Flutter中使用install_plugin插件进行APK安装的简单介绍。希望对你有所帮助。如果你有任何问题或者想要了解更多关于Flutter的内容,欢迎在评论区留言。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/634146.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

应该怎样保存用户密码

应该怎样保存用户密码&#xff1f; 首先&#xff0c;MD5 其实不是真正的加密算法。所谓加密算法&#xff0c;是可以使用密钥把明文加密为密文&#xff0c;随后还可以使用密钥解密出明文&#xff0c;是双向的。 使用 MD5 运算后得到的都是固定长度的摘要信息或指纹信息&#x…

C#:接口中如何将某个值类型的字段传null?

在实际对接第三方接口时&#xff0c;偶尔会有一些字段在某些情况下是不需要传值的。那如何处理呢&#xff1f; 有两种方法&#xff1a; 1、将值类型改为可空类型&#xff1b; 2、定义基类&#xff0c;基类包含所有必须要传的字段&#xff0c;子类则加入偶尔需要传的字段。 下…

java注释

注释 1、单行注释 2、多行注释 3、文档注释&#xff08;重点&#xff09; /*** author cx* version 1.0*/ public class Comment{//编写一个main方法public static void main(String[] args){System.out.println("hello,world~");} } 1. 在D盘找到javacode文件&a…

电梯节能落座-智慧停车场️,电梯不仅可载人也可以载汽车!

电梯不仅可载人也可以载汽车哦&#xff01; 在北京市丰台区&#xff0c;有这么一个智慧停车场&#x1f17f;️ &#xff0c;共298个停车位&#xff0c;全部智能一体化&#xff0c;简直是“豪华” “智能” 的象征。 523能源&#xff1a;小伍&#xff0c;你跑题了... 小伍&am…

【unity学习笔记】语音驱动blendershape

1.导入插件 https://assetstore.unity.com/packages/tools/animation/salsa-lipsync-suite-148442 1.选择小人&#xff0c;点击添加组件 分别加入组件&#xff1a; SALSA EmoteR Eyes Queue Processor&#xff08;必须加此脚本&#xff09;&#xff1a;控制前三个组件的脚本。…

QTAV踩过的坑和MDK-SDK的一些小东西

最近需要在qt界面内放一个widget用以播放视频&#xff0c;被推荐了qtav&#xff0c;踩了很多坑 qtav 首先说明&#xff0c;我是需要内网编译&#xff0c;内网开发&#xff0c;然后打包程序&#xff0c;所以直接注入到qt根目录的方式我是不考虑的&#xff0c;以下问题大多建立…

Python GUI 新手入门教程:轻松构建图形用户界面

Python 凭借其简单性和多功能性&#xff0c;已经成为最流行的编程语言之一。被广泛应用于从 web 开发到数据科学的各个领域。 在本教程中&#xff0c;我们将探索用于创建图形用户界面&#xff08;GUIs&#xff09;的 Python 内置库&#xff1a; Tkinter&#xff1a;无论你是初…

golang 中使用 statik 将静态资源编译进二进制文件中

现在的很多程序都会提供一个 Dashboard 类似的页面用于查看程序状态并进行一些管理的功能&#xff0c;通常都不会很复杂&#xff0c;但是其中用到的图片和网页的一些静态资源&#xff0c;如果需要用户额外存放在一个目录&#xff0c;也不是很方便&#xff0c;如果能打包进程序发…

Byrdhouse AI实时语音翻译工具,可以在视频通话中翻译100多种语言

你是否曾经在跨国会议或与外国友人聊天时&#xff0c;因为语言不通而感到尴尬或困扰&#xff1f;是不是还在找可以实时翻译的软件或者APP&#xff1f;现在&#xff0c;有了这款语音翻译神器&#xff0c;一切都将变得简单&#xff01; 免费使用链接&#xff1a;https://byrdhous…

常用的JavaScript数组内置方法

目录 1、修改数组 push()&#xff1a;添加 pop()&#xff1a;删除 unshift()&#xff1a;添加 shift()&#xff1a;删除 splice()&#xff1a;修改&#xff0c;删除&#xff0c;添加 2、访问数组 concat()&#xff1a;连接数组 join()&#xff1a;连接 slice()&#xff1a…

【工作记录】基于springboot3+springsecurity实现多种方式登录及鉴权(二)

前言 上篇文章介绍了基于springboot3+springsecurity实现的基于模拟数据的用户多种方式登录及鉴权的流程和代码实现,本文我们继续完善。 主要完善的点 主要通过如下几个点来完成优化和完善: 用户信息获取通过查询mysql数据库实现token生成方式使用jwt用户信息存储及读取使用…

Text:焦点切换文字颜色随之改变

按Tab键切换2段文字的焦点&#xff0c;哪段文字的焦点为true&#xff0c;则字体颜色变为红色。 import QtQuickWindow {width: 640height: 480visible: truetitle: qsTr("2.2 属性")Rectangle {Text {id: thislabeltext: qsTr("hello world")font.pixelSiz…

JAVA ORM Bee的设计模式分析

创建型 工厂模式&#xff08;Factory Pattern&#xff09; 日志工厂 LoggerFactory 静态工厂模式 *&#xff08;Static Factory&#xff09; BeeFactoryHelper 单例模式&#xff08;Singleton Pattern&#xff09; 使用单例模式管理系统的配置信息 HoneyConfig 建…

龙芯3A5000上使用腾讯会议

原文链接&#xff1a;龙芯3A5000上使用腾讯会议 hello&#xff0c;大家好啊&#xff01;今天我要给大家介绍的是在龙芯3A5000处理器上安装使用腾讯会议的经验分享。随着远程工作和在线会议的普及&#xff0c;腾讯会议成为了许多人日常工作不可或缺的工具。而对于使用龙芯3A5000…

极客时间-《罗剑锋的 C++ 实战笔记》文章笔记 + 个人思考

极客时间-《罗剑锋的 C 实战笔记》文章笔记 个人思考 语言特性06 | auto/decltype&#xff1a;为什么要有自动类型推导&#xff1f; 语言特性 06 | auto/decltype&#xff1a;为什么要有自动类型推导&#xff1f; auto 在C 11 引入。 为什么说C是静态强类型语言&#xff1f…

Open3D 点云转深度图像

目录 一、算法原理1、算法过程2、主要函数二、代码实现三、结果展示1、点云2、深度图像四、测试数据Open3D 点云转深度图像由CSDN点云侠原创。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。<

【JavaScript】 失去了eval时怎么办(表达式解析与求值深入解析)

JavaScript 表达式解析与求值深入解析 有的时候我们不得不面临不可使用eval函数或者new function&#xff0c;但是又需要将一个字符串作为代码运行的尴尬场景&#xff0c;比如小程序考虑到其安全性问题&#xff0c;就禁止使用&#xff1b;这种情况下我们就需要一个表达式解析器…

全网最详细!!Python 爬虫快速入门

1. 背景 最近在工作中有需要使用到爬虫的地方&#xff0c;需要根据 Gitlab Python 实现一套定时爬取数据的工具&#xff0c;所以借此机会&#xff0c;针对 Python 爬虫方面的知识进行了学习&#xff0c;也算 Python 爬虫入门了。 需要了解的知识点&#xff1a; Python 基础语…

Spring Cloud核心组件介绍

三大门派 有Spring Cloud的地方就有江湖&#xff0c;我们就来看一看在这个江湖中都有哪些独霸一方的门派! Netflix 是先有SpringCloud还是先有Netflix?这是一个好问题。Netflix是一家大名鼎鼎的互联网传媒公司&#xff0c;但为什么它在开源软件领域有这么大的名声呢?这就…

标题:智能对话新纪元:ChatGPT与文心一言的全面比较

标题&#xff1a;智能对话新纪元&#xff1a;ChatGPT与文心一言的全面比较 引言&#xff1a; 在这个由数据驱动的时代&#xff0c;人工智能语言模型已成为技术创新的前沿。特别是OpenAI的ChatGPT和百度的文心一言&#xff08;ERNIE Bot&#xff09;&#xff0c;它们不仅代表了…