Android 保存/读取本地SD卡文件(兼容Android 13)

这篇具有很好参考价值的文章主要介绍了Android 保存/读取本地SD卡文件(兼容Android 13)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.manifeast文件

(1)app权限

<!--存储权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>

(2)application配置

<application
	...
    android:requestLegacyExternalStorage="true"
    android:usesCleartextTraffic="true"
    ...>

(3)组件配置

注意:Android 12以上,组件创建会自动生成以下属性

android:exported="true"

表示”是否支持其它应用调用当前组件”

如果不添加改属性,会报错。

2.动态申请文件存储权限

说明,Android的权限根据版本号分为三种

1:Android6.0之前

2:Android6.0-Android 10

3:Android 11以后

其中,6.0之前不需要动态申请权限,只需要在manifest文件中申请即可。从6.0之后,app需要动态申请权限,即弹框询问用户,是否给用户授权。Android 11以后,对权限的控制进一步收紧,很多的权限申请发生改变,例如,此前操作文件,只需要声明读写权限即可,但是现在划分了图片、音频、视频等等,并且操作普通文件的权限也变为MANAGE_EXTERNAL_STORAGE

代码如下:

private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE
};
private boolean havePermission = false;
@Override
protected void onResume() {
    super.onResume();
    checkPermission();
}
private AlertDialog dialog;

private void checkPermission() {
    //检查权限(NEED_PERMISSION)是否被授权 PackageManager.PERMISSION_GRANTED表示同意授权
    if (Build.VERSION.SDK_INT >= 30) {
        if (!Environment.isExternalStorageManager()) {
            if (dialog != null) {
                dialog.dismiss();
                dialog = null;
            }
            dialog = new AlertDialog.Builder(this)
                    .setTitle("提示")//设置标题
                    .setMessage("请开启文件访问权限,否则无法正常使用本应用!")
                    .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int i) {
                            dialog.dismiss();
                        }
                    })
                    .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                            Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
                            startActivity(intent);
                        }
                    }).create();
            dialog.show();
        } else {
            havePermission = true;
            Log.i("swyLog", "Android 11以上,当前已有权限");
        }
    } else {
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                //申请权限
                if (dialog != null) {
                    dialog.dismiss();
                    dialog = null;
                }
                dialog = new AlertDialog.Builder(this)
                        .setTitle("提示")//设置标题
                        .setMessage("请开启文件访问权限,否则无法正常使用本应用!")
                        .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                                ActivityCompat.requestPermissions(BrowserActivity.this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
                            }
                        }).create();
                dialog.show();
            } else {
                havePermission = true;
                Log.i("swyLog", "Android 6.0以上,11以下,当前已有权限");
            }
        } else {
            havePermission = true;
            Log.i("swyLog", "Android 6.0以下,已获取权限");
        }
    }
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);    
switch (requestCode) {
        case REQUEST_EXTERNAL_STORAGE: {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                havePermission = true;
                Toast.makeText(this, "授权成功!", Toast.LENGTH_SHORT).show();
            } else {
                havePermission = false;
                Toast.makeText(this, "授权被拒绝!", Toast.LENGTH_SHORT).show();
            }
            return;
        }
    }
}

3.文件操作

(1)定义文件保存的路径及文件名

private String FILE_SAVE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/MobileReport/";
private String FILE_NAME = "user.txt";

(2)保存文件

private void saveLoginAccount(String json) {
    if (TextUtils.isEmpty(json)) {
        return;
    }
    Log.i("swyLog", "saveLoginAccount called");
    String value = encodeToString(json);
    Log.i("swyLog", "save 明文:" + json);
    Log.i("swyLog", "save 密文:" + value);
    File storage = new File(FILE_SAVE_PATH);
    if (!storage.exists()) {
        storage.mkdirs();
    }
    File tmepfile = new File(storage.getPath());
    if (!tmepfile.exists()) {
        tmepfile.mkdirs();
    }
    File file = new File(tmepfile, FILE_NAME);
    if (file.exists()) {
        Log.i("swyLog", "删除原有文件");
        file.delete();
    }
    if (!file.exists()) {
        Log.i("swyLog", "文件删除成功");
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    FileOutputStream fileOutputStream = null;
    try {
        fileOutputStream = new FileOutputStream(file);
        fileOutputStream.write(value.getBytes());
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (fileOutputStream != null) {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

(3)读取文件

private String uploadLoginAccount() {
    Log.i("swyLog", "uploadLoginAccount called");
    InputStream inputStream = null;
    Reader reader = null;
    BufferedReader bufferedReader = null;
    try {
        File storage = new File(FILE_SAVE_PATH);
        if (!storage.exists()) {
            return "";
        }
        File file = new File(storage, FILE_NAME);
        if (!file.exists()) {
            return "";
        }
        inputStream = new FileInputStream(file);
        reader = new InputStreamReader(inputStream);
        bufferedReader = new BufferedReader(reader);
        StringBuilder result = new StringBuilder();
        String temp;
        while ((temp = bufferedReader.readLine()) != null) {
            result.append(temp);
        }
        String value = decodeToString(result.toString());
        Log.i("swyLog", "upload 密文:" + result);
        Log.i("swyLog", "upload 明文:" + value);
        return value;
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (bufferedReader != null) {
            try {
                bufferedReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return "";
}

(4)删除文件

private void deleteLoginAccount() {
    Log.i("swyLog", "deleteLoginAccount called");
    File storage = new File(FILE_SAVE_PATH);
    if (!storage.exists()) {
        storage.mkdirs();
    }
    File tmepfile = new File(storage.getPath());
    if (!tmepfile.exists()) {
        tmepfile.mkdirs();
    }
    File file = new File(tmepfile, FILE_NAME);
    if (file.exists()) {
        try {
            Log.i("swyLog", "删除原有文件");
            file.delete();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    if (!file.exists()) {
        Log.i("swyLog", "文件删除成功");
    }
}

(5)base64 加解密方法

/**
 * 字符Base64加密
 *
 * @param str
 * @return
 */
public static String encodeToString(String str) {
    try {
        return Base64.encodeToString(str.getBytes("UTF-8"), Base64.DEFAULT);
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return "";
}

/**
 * 字符Base64解密
 *
 * @param str
 * @return
 */
public static String decodeToString(String str) {
    try {
        return new String(Base64.decode(str.getBytes("UTF-8"), Base64.DEFAULT));
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return "";
}

说明:我这里是从项目中复制的代码,作用是,将字符串加密之后,保存到sd卡种,加密的原因自然不言而喻,因为有些信息是不方便直接展示给用户看的。文章来源地址https://www.toymoban.com/news/detail-452683.html

到了这里,关于Android 保存/读取本地SD卡文件(兼容Android 13)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python对csv文件一键多值保存为json本地文件再读取加速效率(3)

    🌸 欢迎来到Python办公自动化专栏—Python处理办公问题,解放您的双手 🏳️‍🌈 博客主页:一晌小贪欢的博客主页 👍 该系列文章专栏:Python办公自动化专栏 文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏 ❤️ 欢迎各位佬关注! ❤️ 1、给我一张表格直

    2024年02月11日
    浏览(136)
  • javacv 基础04-读取mp4,avi等视频文件并截图保存图片到本地

    javacv 读取mp4,avi等视频文件并截图保存图片到本地 代码如下: 运行结果: 测试视频mp4 下载

    2024年02月11日
    浏览(58)
  • Android Studio实现读取本地相册文件并展示

    原文链接 效果 代码 activity_main.xml 需要有一个按钮和image来展示图片 MainActivity

    2024年02月12日
    浏览(45)
  • UniApp写入读取android本地文件,不会被清除

           项目背景,我们是用uniapp编写的收银程序,然后打包到android工程,再打包成apk包安装到用户的收银机上,收银机是android系统。由于项目需求,每次升级我们收银系统版本后,之前连接的打印机和LED显示屏的缓存数据都会被重新清除,因为升级相当于重新安装apk。所以

    2024年02月13日
    浏览(32)
  • 远程xml读取解析,将image url下载到本地,延时队列定时删除文件,图片访问路径保存在数据库中

    远程xml部分内容 mq发布端定时任务发送消息 mq消费端 1,远程xml读取 2,xml解析,将image中图片url保存在集合中 3,遍历集合,当本地不存在此图片时,下载图片至本地 4,将图片路径传给延时队列,用于稍后删除图片 5,保存自定义图片访问路径等信息到数据库 XMLUtil读取远程

    2024年02月15日
    浏览(47)
  • Android保存图片到相册,兼容Android10及以上版本

    Android 共享存储空间 访问共享存储空间中的媒体文件 MediaStore是android系统提供的一个多媒体数据库,专门用于存放多媒体信息的,通过ContentResolver即可对数据库进行操作。 MediaStore.Files: 共享的文件,包括多媒体和非多媒体信息; MediaStore.Audio: 存放音频信息; MediaStore.Image: 存放

    2024年02月11日
    浏览(51)
  • Android框架mqtt库无法兼容高版本android13的问题

    最近使用mqtt库,测试的时候发现在Android12及以下正常,但在13上闪退,闪退日志如下 提示很明显是version 31版本在创建PendingIntent的时候需要做适配,于是全局搜索把适配代码加上,代码如下 加上之后还是报同样的错误,几经周折才发现mqtt库里也用到了PendingIntent且没有做适配

    2024年02月07日
    浏览(35)
  • UE4实现截屏并保存到相册Android/iOS兼容

    通过Edit-Plugins-NewPlugin创建3个空的Plugin: MyNative插件,实现截屏功能,并提供对外调用的接口 MyNativeAndroid插件,实现Android端保存图片到相册功能 MyNativeIos插件,实现iOS端保存图片到相册功能 1.在MyNative.uplugin注册引用到2个插件MyNativeAndroid和MyNativeIos 2.在MyNative.Build.cs分平台引用

    2024年02月15日
    浏览(47)
  • STM32挂载SD卡基于Fatfs文件系统读取文件信息

    🔖本例程基于正点原子标准库修改而来。 📍FatFs 相关API函数网站: http://elm-chan.org/fsw/ff/00index_e.html 🌴分别测试了SD卡模块以及Mini SD卡模块。 🌿STM32f1单片机和TF卡、SD卡连接采用SPI通讯方式。 SD模块: Mini SD卡模块: 👉🏻如果需要采用SDIO驱动方式,那么需要采用下面这种

    2024年02月10日
    浏览(39)
  • 高通 Android 8/9/12/13 兼容U盘识别extfat模式

    Android本身不支持extfat格式 需要通过nofuse 打kernel补丁方式去实现  Android 8/9 1、kernel/msm-4.9/arch/arm64/configs/sdm670-perf_defconfig 增加代码如下( 需要提交编译kernel记得git add sdm670-perf_defconfig 不需要commit哈!否则编译会还原这个文件,切记!) 2、kernel/msm-4.9/arch/arm64/configs/sdm670_def

    2024年02月04日
    浏览(73)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包