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

4 篇文章 0 订阅
4 篇文章 0 订阅

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

运行环境 jdk17 andriod 34 compose material3

简介

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

在这里插入图片描述

UI界面

在这里插入图片描述

package com.example.myapplication.ui

import 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.File


var 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 Activity
    BottomAppBar(
        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>
....
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="com.example.myapplication.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android: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.fromFile
        if (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博客

  • 11
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
蛋白质是生物体中普遍存在的一类重要生物大分子,由天然氨基酸通过肽键连接而成。它具有复杂的分子结构和特定的生物功能,是表达生物遗传性状的一类主要物质。 蛋白质的结构可分为四级:一级结构是组成蛋白质多肽链的线性氨基酸序列;二级结构是依靠不同氨基酸之间的C=O和N-H基团间的氢键形成的稳定结构,主要为α螺旋和β折叠;三级结构是通过多个二级结构元素在三维空间的排列所形成的一个蛋白质分子的三维结构;四级结构用于描述由不同多肽链(亚基)间相互作用形成具有功能的蛋白质复合物分子。 蛋白质在生物体内具有多种功能,包括提供能量、维持电解质平衡、信息交流、构成人的身体以及免疫等。例如,蛋白质分解可以为人体提供能量,每克蛋白质能产生4千卡的热能;血液里的蛋白质能帮助维持体内的酸碱平衡和血液的渗透压;蛋白质是组成人体器官组织的重要物质,可以修复受损的器官功能,以及维持细胞的生长和更新;蛋白质也是构成多种生理活性的物质,如免疫球蛋白,具有维持机体正常免疫功能的作用。 蛋白质的合成是指生物按照从脱氧核糖核酸(DNA)转录得到的信使核糖核酸(mRNA)上的遗传信息合成蛋白质的过程。这个过程包括氨基酸的活化、多肽链合成的起始、肽链的延长、肽链的终止和释放以及蛋白质合成后的加工修饰等步骤。 蛋白质降解是指食物中的蛋白质经过蛋白质降解酶的作用降解为多肽和氨基酸然后被人体吸收的过程。这个过程在细胞的生理活动中发挥着极其重要的作用,例如将蛋白质降解后成为小分子的氨基酸,并被循环利用;处理错误折叠的蛋白质以及多余组分,使之降解,以防机体产生错误应答。 总的来说,蛋白质是生物体内不可或缺的一类重要物质,对于维持生物体的正常生理功能具有至关重要的作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值