Android读写文件,适配Q以上

Android Q升级了文件系统,访问文件不仅仅是说动态权限了,有各种限制。权限什么的就不赘述了,下面介绍一下在10以上的系统中访问文件。

首先是打开文件管理器

    /**
     * 打开文件管理器 存储卡和外接U盘都可以访问
     */
    public void openFileManager() {
        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("text/*");
        startActivityForResult(intent, REQUEST_CODE_FILE);
    }

这个setType可以根据自己的需要,设置MIME类型,设置要访问什么类型的文件。具体MIME可以参考MIME类型-CSDN博客

然后会打开文件管理器,这里面可以访问手机存储的文件或者外插U盘内的文件,就根据自己需求选择文件就可以了。

选中的文件会在onActivityResult中返回

@Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK && requestCode == REQUEST_CODE_FILE){
            //拿到需要解析的文件
            Uri uri = data.getData();
            String filePath= FileHelper.getFileAbsolutePath(this,uri);
            if (!TextUtils.isEmpty(filePath)){
                parseFile = new File(filePath);
                binding.tvFileName.setText(parseFile.getName());
                readFile();
            }
        }
    }

这里关键的一点就是把拿到的uri转换成filePath了,转换成路径之后就可以读文件,根据需求进行操作了。这个FileHelper转自Android打开系统文件管理器,并获取选中文件的路径,适配Android10及以上无法获取路径_intent.settype获取文件-CSDN博客

package com.......utils;


import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.FileUtils;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.provider.OpenableColumns;

import androidx.annotation.RequiresApi;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * ================================================
 * Description:通过uri获取本地文件的绝对路径
 * <p>
 * ================================================
 */
public class FileHelper {

    /**
     * 根据Uri获取文件绝对路径,解决Android4.4以上版本Uri转换
     *
     * @param context
     * @param imageUri
     */
    public static String getFileAbsolutePath(Context context, Uri imageUri) {
        if (context == null || imageUri == null) {
            return null;
        }

        if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT) {
            return getRealFilePath(context, imageUri);
        }

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT && android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && DocumentsContract.isDocumentUri(context, imageUri)) {
            if (isExternalStorageDocument(imageUri)) {
                String docId = DocumentsContract.getDocumentId(imageUri);
                String[] split = docId.split(":");
                String type = split[0];
                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }
            } else if (isDownloadsDocument(imageUri)) {
                String id = DocumentsContract.getDocumentId(imageUri);
                Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
                return getDataColumn(context, contentUri, null, null);
            } else if (isMediaDocument(imageUri)) {
                String docId = DocumentsContract.getDocumentId(imageUri);
                String[] split = docId.split(":");
                String type = split[0];
                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }
                String selection = MediaStore.Images.Media._ID + "=?";
                String[] selectionArgs = new String[]{split[1]};
                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        } // MediaStore (and general)
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
            return uriToFileApiQ(context,imageUri);
        }
        else if ("content".equalsIgnoreCase(imageUri.getScheme())) {
            // Return the remote address
            if (isGooglePhotosUri(imageUri)) {
                return imageUri.getLastPathSegment();
            }
            return getDataColumn(context, imageUri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(imageUri.getScheme())) {
            return imageUri.getPath();
        }
        return null;
    }

    //此方法 只能用于4.4以下的版本
    private static String getRealFilePath(final Context context, final Uri uri) {
        if (null == uri) {
            return null;
        }
        final String scheme = uri.getScheme();
        String data = null;
        if (scheme == null) {
            data = uri.getPath();
        } else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
            data = uri.getPath();
        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
            String[] projection = {MediaStore.Images.ImageColumns.DATA};
            Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null);

//            Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);
            if (null != cursor) {
                if (cursor.moveToFirst()) {
                    int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
                    if (index > -1) {
                        data = cursor.getString(index);
                    }
                }
                cursor.close();
            }
        }
        return data;
    }


    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    private static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    private static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
        Cursor cursor = null;
        String column = MediaStore.Images.Media.DATA;
        String[] projection = {column};
        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
            if (cursor != null && cursor.moveToFirst()) {
                int index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(index);
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return null;
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    private static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is Google Photos.
     */
    private static boolean isGooglePhotosUri(Uri uri) {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }


    /**
     * Android 10 以上适配 另一种写法
     * @param context
     * @param uri
     * @return
     */
    public static String getFileFromContentUri(Context context, Uri uri) {
        if (uri == null) {
            return null;
        }
        String filePath;
        String[] filePathColumn = {MediaStore.MediaColumns.DATA, MediaStore.MediaColumns.DISPLAY_NAME};
        ContentResolver contentResolver = context.getContentResolver();
        Cursor cursor = contentResolver.query(uri, filePathColumn, null,
                null, null);
        if (cursor != null) {
            cursor.moveToFirst();
            try {
                filePath = cursor.getString(cursor.getColumnIndex(filePathColumn[0]));
                return filePath;
            } catch (Exception e) {
            } finally {
                cursor.close();
            }
        }
        return "";
    }

    /**
     * Android 10 以上适配
     * @param context
     * @param uri
     * @return
     */
    @RequiresApi(api = Build.VERSION_CODES.Q)
    private static String uriToFileApiQ(Context context, Uri uri) {
        File file = null;
        //android10以上转换
        if (uri.getScheme().equals(ContentResolver.SCHEME_FILE)) {
            file = new File(uri.getPath());
        } else if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
            //把文件复制到沙盒目录
            ContentResolver contentResolver = context.getContentResolver();
            Cursor cursor = contentResolver.query(uri, null, null, null, null);
            if (cursor.moveToFirst()) {
                String displayName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
                try {
                    InputStream is = contentResolver.openInputStream(uri);
                    File cache = new File(context.getExternalCacheDir().getAbsolutePath(), Math.round((Math.random() + 1) * 1000) + displayName);
                    FileOutputStream fos = new FileOutputStream(cache);
                    FileUtils.copy(is, fos);
                    file = cache;
                    fos.close();
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return file.getAbsolutePath();
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

没指定spring-boot-maven-plugin版本导致编译失败,这坑你踩过没

文章目录 1. 前言2. 组件版本信息3. 事件经过3.1 本地通过maven命令打包3.2 定位问题步骤3.2.1 核对spring-boot-maven-plugin版本信息3.2.2 spring-boot-maven-plugin版本错误原因 3.3 解决方案 4.结论 1. 前言 我们在平时开发过程中关注的比较多的是项目开发时依赖包的版本以…

为什么选择快速应用开发:提高业务响应速度与竞争力的关键

如今&#xff0c;企业想要持续蓬勃发展&#xff0c;就需要具备快速满足客户期望的能力。无论是十几年历史的重要市场占有者推出新的APP&#xff0c;还是在疫情期间从线下转向线上电商营销&#xff0c;企业都需要主动适应市场。随着为客户提供新的服务方式&#xff0c;员工也需要…

【LUA】mac状态栏添加天气

基于网络上的版本修改的&#xff0c;找不到出处了。第一个摸索的lua脚本&#xff0c;调了很久。 主要修改&#xff1a;如果风速不大&#xff0c;就默认不显示&#xff0c;以及调整为了一些格式 local urlApi http://.. --这个urlApi去申请个免费的就可以了 然后打开对应的json…

Scratch:启蒙少儿编程的图形化魔法

在当今这个数字化时代&#xff0c;编程已经成为了一项重要的基础技能。就像学习阅读和写作一样&#xff0c;掌握编程能够打开通往未来世界的大门。对于孩子们来说&#xff0c;Scratch作为一种图形化编程语言&#xff0c;不仅简单有趣&#xff0c;而且非常适合作为编程学习的入门…

Vue3 Suspense 优雅地处理异步组件加载

✨ 专栏介绍 在当今Web开发领域中&#xff0c;构建交互性强、可复用且易于维护的用户界面是至关重要的。而Vue.js作为一款现代化且流行的JavaScript框架&#xff0c;正是为了满足这些需求而诞生。它采用了MVVM架构模式&#xff0c;并通过数据驱动和组件化的方式&#xff0c;使…

基于51单片机智能电子秤

实物显示效果&#xff1a; https://www.bilibili.com/video/BV1Wb4y1A7Aw/?vd_source6ff7cd03af95cd504b60511ef9373a1d 功能介绍&#xff1a; &#xff08;1&#xff09;用键盘设计单价&#xff1b; &#xff08;2&#xff09;称重后同时显示该物品的重量、单价和总额&…

JAVA编程题之用户登录,用户信息存储在本地文件

实现用户登录&#xff1a;键盘输入要登录的用户名与密码 properties类型文件常在框架内用作配置文件. public static void main(String[] args) throws Exception {FileInputStream fis new FileInputStream("user.properties");Properties properties new Prope…

Hive3.1.3基础(续)

参考B站尚硅谷 分区表和分桶表 分区表 Hive中的分区就是把一张大表的数据按照业务需要分散的存储到多个目录&#xff0c;每个目录就称为该表的一个分区。在查询时通过where子句中的表达式选择查询所需要的分区&#xff0c;这样的查询效率会提高很多。 分区表基本语法 分区表…

一、对人工智能大模型了解与认知

黑8说 月黑风高&#xff0c;乌云密布&#xff0c;树木低垂&#xff0c;黯淡沉闷。这黎明前的风暴&#xff0c;预示着新时代的变革即将到来。 在一个8线小城市的办公室中 黑8对主任说&#xff1a; 世界上有男人、女人、人妖&#xff0c;米国有1/3男&#xff0c;2/3女…&#xff…

HCIP实验7-三层架构实验

搭建实验拓扑图 实验开始 配置r1,r2的IP地址及环回 r1 [r1]interface LoopBack 0 [r1-LoopBack0]ip address 1.1.1.1 32 [r1]interface g0/0/0 [r1-GigabitEthernet0/0/0]ip address 23.1.1.1 24 [r1]interface g0/0/1 [r1-GigabitEthernet0/0/1]ip address 34.1.1.1 24 [r1…

Bitbucket第一次代码仓库创建/提交/创建新分支/合并分支/忽略ignore

1. 首先要在bitbucket上创建一个项目&#xff0c;这个我没有权限创建&#xff0c;是找的管理员创建的。 管理员创建之后&#xff0c;这个项目给了我权限&#xff0c;我就可以创建我的代码仓库了。 2. 点击这个Projects下的具体项目名字&#xff0c;就会进入这样一个页面&#…

11k+ star 一款不错的笔记leanote安装教程

特点 支持普通模式 支持markdown模式 支持搜索 安装教程 1.安装mongodb 1.1.下载 #下载 cd /opt wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.0.1.tgz 1.2解压 tar -xvf mongodb-linux-x86_64-3.0.1.tgz 1.3配置mongodb环境变量 vim /etc/profile 增…

java集合ArrayList和HashSet的fail-fast与fail-safe以及ConcurrentModificationException

在 java 的集合工具类中&#xff0c;例如对 ArrayList 或者 HashSet 进行删除元素后再遍历元素时&#xff0c;会抛出 ConcurrentModificationException 异常。 fail-fast ArrayList public class TestList {public static void main(String[] args) {ArrayList<Integer>…

Java 基于SpringBoot+Vue的母婴商城系统,附源码,文档

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

宝塔面板一键部署幻兽帕鲁联机服务器教程

幻兽帕鲁是一款深受玩家喜爱的多人在线游戏&#xff0c;玩家可以自行搭建联机服务器&#xff0c;邀请亲朋好友一起在世界探索畅玩&#xff0c;为了方便玩家更快速的部署自己的幻兽帕鲁联机服务器&#xff0c;宝塔面板推出了幻兽帕鲁一键部署服务&#xff0c;一键即可安装并调整…

2024.1.24 GNSS 学习笔记

1.伪距观测值公式 2.载波相位观测值公式 3.单点定位技术(Single Point Positionin, SPP) 仅使用伪距观测值&#xff0c;不使用其他的辅助信息获得ECEF框架下绝对定位技术。 使用广播星历的轨钟进行定位&#xff0c;考虑到轨钟的米级精度&#xff0c;所以对于<1米的误差&…

【STM32】STM32学习笔记-W25Q64简介(37)

00. 目录 文章目录 00. 目录01. SPI简介02. W25Q64简介03. 硬件电路04. W25Q64框图05. Flash操作注意事项06. 预留07. 附录 01. SPI简介 在大容量产品和互联型产品上&#xff0c;SPI接口可以配置为支持SPI协议或者支持I 2 S音频协议。SPI接口默认工作在SPI方式&#xff0c;可以…

ASP.NET Core 7 Web 使用Session

ASP.NET Core 好像不能像20年前那样直接使用Session函数&#xff0c;我使用如下方法 1、在NuGet安装以下2个包 2、在Program.cs注册 //注册Session builder.Services.AddSession(options > {options.IdleTimeout TimeSpan.FromMinutes(60);options.Cookie.HttpOnly fals…

放个烟花迎接龙年春节吧

不知不觉即将迎来2024龙年春节了。龙的形象在中国传统文化中有着广泛的应用&#xff0c;比如在传统文化中&#xff0c;龙代表着权力、威严、吉祥和神灵的象征&#xff0c;同时也是生命力和繁荣的象征。 今天的文章将用原生JavaScript和Canvas API实现一个烟花的效果&#xff0…

使用Docker部署MySQL并结合内网穿透实现远程访问本地数据库

文章目录 前言1 .安装Docker2. 使用Docker拉取MySQL镜像3. 创建并启动MySQL容器4. 本地连接测试4.1 安装MySQL图形化界面工具4.2 使用MySQL Workbench连接测试 5. 公网远程访问本地MySQL5.1 内网穿透工具安装5.2 创建远程连接公网地址5.3 使用固定TCP地址远程访问 前言 本文主…