compose调用系统分享功能分享图片文件

compose调用系统分享功能图片文件

  • 简介
    • UI界面
    • 提供给外部程序的文件访问权限
      • 创建FileProvider
      • 设置共享文件夹
  • 通用分享工具
  • 虚拟机验证结果
  • 参考

本系列用于新人安卓基础入门学习笔记,有任何不同的见解欢迎留言

运行环境 jdk17 andriod 34 compose material3

简介

本案例采用 provider来分享当前应用下的文件,其他系统文件直接通过context地址直接获取
本案例是直接 【MediaProvider】content://media/external/images/media,来让其他app直接访问,如果是系统文件请直接忽略provider相关设置

在这里插入图片描述

UI界面

在这里插入图片描述

package com.example.myapplication.uiimport android.app.Activity
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Share
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavHostController
import com.example.myapplication.R
import com.example.myapplication.common.ShareUtil
import com.example.myapplication.common.Utils
import com.example.myapplication.common.ui.FullScreenImage
import com.example.myapplication.entity.ImageEntity
import java.io.Filevar snackbarHostState = SnackbarHostState()@Composable
fun ImageDetail(imageEntity: ImageEntity, mainController: NavHostController) {Scaffold(snackbarHost = {SnackbarHost(hostState = snackbarHostState, modifier = Modifier.padding(0.dp))},topBar = {ImageTopBar(imageEntity.name, mainController)},bottomBar = {GetBottomBar(imageEntity.file)}) { innerPadding ->FullScreenImage(imageEntity = imageEntity, modifier = Modifier.padding(innerPadding))}
}@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun GetBottomBar(file: File) {val scope = rememberCoroutineScope()val activity = LocalContext.current as ActivityBottomAppBar(containerColor = MaterialTheme.colorScheme.primaryContainer,contentColor = MaterialTheme.colorScheme.primary,) {Row(Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.SpaceEvenly,verticalAlignment = Alignment.CenterVertically) {val buttonModifier = Modifier.size(70.dp)val IconModifier = Modifier.size(30.dp)val message = stringResource(id = R.string.empty_ui)IconButton(onClick = { Utils.message(scope, message, snackbarHostState) },modifier = buttonModifier) {Column(horizontalAlignment = Alignment.CenterHorizontally) {Icon(modifier = IconModifier,imageVector = Icons.Filled.Edit,contentDescription = "Localized description")Text(text = "编辑",fontSize = 12.sp,)}}IconButton(onClick = {// 打开系统分享ShareUtil.shareImage(activity,"com.example.myapplication.fileprovider",file.name,file.path)},modifier = buttonModifier) {Column(horizontalAlignment = Alignment.CenterHorizontally) {Icon(modifier = IconModifier,imageVector = Icons.Filled.Share,contentDescription = "Localized description")Text(text = "分享", fontSize = 12.sp)}}IconButton(onClick = { Utils.message(scope, message, snackbarHostState) },modifier = buttonModifier) {Column(horizontalAlignment = Alignment.CenterHorizontally) {Icon(modifier = IconModifier,imageVector = Icons.Filled.Delete,contentDescription = "Localized description")Text(text = "删除", fontSize = 12.sp)}}IconButton(onClick = { Utils.message(scope, message, snackbarHostState) },modifier = buttonModifier) {Column(horizontalAlignment = Alignment.CenterHorizontally) {Icon(modifier = IconModifier,imageVector = Icons.Filled.MoreVert,contentDescription = "Localized description")Text(text = "更多", fontSize = 12.sp)}}}}}
}

提供给外部程序的文件访问权限

  • 这里只适用于外部访问当前app下的数据,本案例是直接 content://media/external/images/media,来让其他app直接访问,如果是系统文件请直接忽略这一段
  • Android 7.0之前,文件的Uri以file:///形式提供给其他app访问。
  • Android 7.0之后,分享文件的Uri发生了变化。为了安全起见,file:///形式的Uri不能正常访问。官方提供了FileProvider,FileProvider生成的Uri会以content://的形式分享给其他app使用。
    content形式的Uri可以让其他app临时获得读取(Read)和写入(Write)权限,只要我们在创建Intent时,使用Intent.setFlags()添加权限。只要接收Uri的app在接收的Activity任务栈中处于活动状态,添加的权限就会一直有效,直到app被任务栈移除

创建FileProvider

<application>
....<providerandroid:name="androidx.core.content.FileProvider"android:authorities="com.example.myapplication.fileprovider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/filepath" /> </provider>
</application>
  • android:authorities 指定可以查找此内容提供程序的权限。可以使用分号分隔多个授权机构。授权机构名称应该使用java风格的命名约定(如com.google.provider.MyProvider),以避免冲突。通常,此名称与描述提供程序数据结构的类实现相同。
  • android:resource 文件的权限清单
  • android:exported 设置为false,FileProvider不需要公开。
  • android:grantUriPermissions 设置为true,这样就能授权接收端的app临时访问权限了。

设置共享文件夹

这里的绝对路径是 /data/data/{package}
例如我的是 /data/data/com.example.myapplication

在res/xml中创建一个资源文件filepath.xml

<?xml version="1.0" encoding="utf-8"?>
<paths><files-path name="Pictures" path="/pictures/"/>
</paths>

/data/data/com.example.myapplication/files/pictures/

通用分享工具

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;import androidx.core.content.FileProvider;import java.io.File;public class ShareUtil {// 原生通用分享文本public static void shareText(Activity activity, String title, String text) {Intent sendIntent = new Intent();sendIntent.setAction(Intent.ACTION_SEND);sendIntent.putExtra(Intent.EXTRA_TEXT, text);sendIntent.setType("text/plain");activity.startActivityForResult(Intent.createChooser(sendIntent, title), 80001);}// 原生通用分享图片public static void shareImage(Activity activity, String authority, String title, File file){shareImage(activity, authority, title, file, false);}public static void shareImage(Activity activity, String authority, String title, File file,  boolean isApp) {Intent sendIntent = new Intent();sendIntent.setAction(Intent.ACTION_SEND);Uri uri = getFileUri(activity, authority, file, isApp);sendIntent.putExtra(Intent.EXTRA_STREAM, uri);sendIntent.setType("image/png");activity.startActivityForResult(Intent.createChooser(sendIntent, title), 80002);}// 通用文件public static void shareFile(Activity activity, String authority, String type, File file,  boolean isApp) {Intent sendIntent = new Intent();sendIntent.setAction(Intent.ACTION_SEND);Uri uri = FileProvider.getUriForFile(activity, authority , file);sendIntent.putExtra(Intent.EXTRA_STREAM, uri);sendIntent.setType(type);activity.startActivityForResult(Intent.createChooser(sendIntent, file.getName()), 80002);}public static Uri getFileUri(Context context, String authority, File file, boolean isApp) {Uri uri;// 低版本直接用 Uri.fromFileif (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {uri = Uri.fromFile(file);} else {if(isApp){// 分享当前应用下的共享路径中的uri = FileProvider.getUriForFile(context, authority , file);}else {// 分享外部的文件uri = getImageContentUri(context, file);}}return uri;}public static Uri getImageContentUri(Context context, File imageFile) {String filePath = imageFile.getAbsolutePath();Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,new String[]{MediaStore.Images.Media._ID}, MediaStore.Images.Media.DATA + "=? ",new String[]{filePath}, null);if (cursor != null && cursor.moveToFirst()) {@SuppressLint("Range") int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));Uri baseUri = Uri.parse("content://media/external/images/media");return Uri.withAppendedPath(baseUri, "" + id);} else {if (imageFile.exists()) {ContentValues values = new ContentValues();values.put(MediaStore.Images.Media.DATA, filePath);return context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);} else {return null;}}}
}

虚拟机验证结果

在这里插入图片描述
在这里插入图片描述

参考

Android之FileProvider详解 - 掘金 (juejin.cn)
Android原生分享与指定app分享_android 原生分享链接-CSDN博客

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

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

相关文章

JavaEE_操作系统之进程(计算机体系,,指令,进程的概念、组成、特性、PCB)

一、冯诺依曼体系&#xff08;Von Neumann Architecture&#xff09; 现代的计算机, 大多遵守冯诺依曼体系结构 CPU 中央处理器: 进行算术运算和逻辑判断.存储器: 分为外存和内存, 用于存储数据(使用二进制方式存储)输入设备: 用户给计算机发号施令的设备.输出设备: 计算机个…

基于php+mysql+html超市商品管理系统(含论文)

博主介绍&#xff1a; 大家好&#xff0c;本人精通Java、Python、Php、C#、C、C编程语言&#xff0c;同时也熟练掌握微信小程序、Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我有丰富的成品Java、Python、C#毕设项目经验&#xff0c;能够为学生提供各类…

【数据结构-之八大排序(下),冒泡排序,快速排序,挖坑法,归并排序】

&#x1f308;个人主页&#xff1a;努力学编程’ ⛅个人推荐&#xff1a;基于java提供的ArrayList实现的扑克牌游戏 |C贪吃蛇详解 ⚡学好数据结构&#xff0c;刷题刻不容缓&#xff1a;点击一起刷题 &#x1f319;心灵鸡汤&#xff1a;总有人要赢&#xff0c;为什么不能是我呢 …

eve 导入linux

mkdir /opt/unetlab/addons/qemu/linux-centos7 cd /opt/unetlab/addons/qemu/linux-centos7 上传hda.qcow2 /opt/unetlab/wrappers/unl_wrapper -a fixpermissions Linux images - (eve-ng.net) Due to very high demand of this section and problems with how to crea…

【车载开发系列】MCAL基本概念

【车载开发系列】MCAL基本概念 【车载开发系列】MCAL基本概念 【车载开发系列】MCAL基本概念一. BSW与MCAL1&#xff09;BSW-服务层2&#xff09;BSW-ECU抽象层3&#xff09;MCAL驱动层 二. MCAL基本概念三. MCAL组成1&#xff09;PORT2&#xff09;DIO3&#xff09;ADC4&#…

阿里云开源大模型开发环境搭建

ModelScope是阿里云通义千问开源的大模型开发者社区&#xff0c;本文主要描述AI大模型开发环境的搭建。 如上所示&#xff0c;安装ModelScope大模型基础库开发框架的命令行参数&#xff0c;使用清华大学提供的镜像地址 如上所示&#xff0c;在JetBrains PyCharm的项目工程终端控…

机器人正反向运动学(FK和IK)

绕第一个顶点可以沿Z轴转动&#xff0c;角度用alpha表示 绕第二个点沿X轴转动&#xff0c;角度为Beta 第三个点沿X轴转动&#xff0c;记作gama 这三个点构成姿态&#xff08;pose&#xff09; 我们记第一个点为P0&#xff0c;画出它的本地坐标系&#xff0c;和世界坐标系一样红…

SpringCloud知识点梳理

1. Spring Cloud 综述 1.1 Spring Cloud 是什么 [百度百科]Spring Cloud是⼀系列框架的有序集合。它利⽤Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中⼼、消息总线、负载均衡、断路器、数据监控等,都可以⽤ Spring Boot的开发⻛格…

(C语言)文件操作与函数,超详解

目录 1. 文件 1.1 为什么使用文件&#xff1f; 1.2 什么是文件&#xff1f; 1.2.1 程序文件 1.2.2 数据文件 1.3 文件名 1.4 二进制文件和文本文件 2. 文件的打开和关闭 2.1 流和标准流 2.1.1 流 2.1.2 标准流 2.2 文件指针 2.3 文件的打开和关闭 3. 文件的顺序…

Go Web 开发【Gin 框架快速开发】

1、Gin Web 快速开发 1.1、环境准备 1.1.1、导入 gin 依赖 这里就叫 gin 依赖了&#xff0c;在 Goland 命令行中输入下面的命令&#xff1a; go get -u github.com/gin-gonic/gin 1.1.2、设置代理 如果下载失败&#xff0c;最好设置一下代理&#xff0c;在 cmd 命令行中输…

深度学习论文:Local Feature Matching Using Deep Learning: A Survey

深度学习论文: Local Feature Matching Using Deep Learning: A Survey Local Feature Matching Using Deep Learning: A Survey PDF: https://arxiv.org/pdf/2401.17592 1 概述 近年来&#xff0c;深度学习模型的引入引发了对局部特征匹配技术的广泛探索。本文旨在全面概述局…

爬虫学习:基本网络请求库的使用

目录 一、urllib网络库 1.urlopen()方法 2.request方法 二、requests网络请求库 1.主要方法 2.requests.get()和requests.post() 一、urllib网络库 1.urlopen()方法 语法格式&#xff1a; urlopen(url,data,timeout,cafile,capath,context) # url:地址 # data:要提交的数据…

POWERBI==官网教程

地址 COVID-19 tracking sample for US state and local governments - Power BI | Microsoft Learn 已经非常全面了

JSON教程(非常详细)

参考文章来源&#xff1a;JSON教程&#xff08;非常详细&#xff09; 目录 JSON JSON 发展史 为什么要使用 JSON&#xff1f; JSON 的不足 存储格式 使用场景 1) 定义接口 2) 序列化 3) 生成 Token 4) 配置文件 JSON语法规则 JSON 与 JavaScript 对象的区别 JSON数…

解决Pycharm全局搜索与输入法简繁切换快捷键冲突问题

Pycharm中全局搜索快捷键Ctrl Shift F 如图所示&#xff1a; 微软输入法简繁切换快捷键设置&#xff1a; 解决办法&#xff1a; 关掉输入法的切换功能即可&#xff0c;或者更改简繁切换快捷键&#xff0c;毕竟简繁切换使用频率极低。

骑缝电子章怎么盖?

盖骑缝电子章通常涉及几个基本步骤&#xff0c;这里提供一个通用的流程&#xff0c;适用于大多数电子文档处理软件&#xff0c;尤其是那些支持电子签名和印章功能的软件&#xff0c;比如Adobe Acrobat Pro DC、e-章宝(易友EU3000智能盖章软件)等。请注意&#xff0c;具体操作可…

2024年五一数学建模C题完整解题思路代码

2024年第二十一届五一数学建模竞赛题目 C题 煤矿深部开采冲击地压危险预测 煤炭是中国的主要能源和重要的工业原料。然而&#xff0c;随着开采深度的增加&#xff0c;地应力增大&#xff0c;井下煤岩动力灾害风险越来越大&#xff0c;严重影响着煤矿的安全高效开采。在各类深…

路由器的构成

一、路由器简介 路由器是互联网中的关键设备&#xff1a; 连接不同的网络路由器是多个输入端口和多个输出端口的专用计算机&#xff0c;其任务是转发分组&#xff08;转发给下一跳路由器&#xff09;下一跳路由器也按照这种方法处理分组&#xff0c;直到该分组到达终点为止 …

Pandas入门篇(二)-------Dataframe篇4(进阶)(Dataframe的进阶用法)(机器学习前置技术栈)

目录 概述一、复合索引&#xff08;一&#xff09;创建具有复合索引的 DataFrame1. 使用 set_index 方法&#xff1a;2.在创建 DataFrame 时直接指定索引&#xff1a; &#xff08;二&#xff09;使用复合索引进行数据选择和切片&#xff08;三&#xff09;重置索引&#xff08…

使用 Langchain、Langfuse、Nemo-gaurdrails、RAGAs构建 RAG 管道并进行监控和评估

原文地址:build-end-to-end-rag-pipeline-with-monitoring-and-evaluation-using-langchain-azure-ai-search 2024 年 4 月 21 日 介绍 使用现代的LLM框架,如Langchain或llamaindex,可以迅速搭建一个用于 RAG 的管道,通常只需编写大约5-6行代码。然而,若要构建一个适用于生…