首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

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

  • 24-03-18 02:22
  • 3181
  • 14224
blog.csdn.net

1.manifeast文件

(1)app权限

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

(2)application配置

  1. <application
  2. ...
  3. android:requestLegacyExternalStorage="true"
  4. android:usesCleartextTraffic="true"
  5. ...>

(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

代码如下:

  1. private static final int REQUEST_EXTERNAL_STORAGE = 1;
  2. private static String[] PERMISSIONS_STORAGE = {
  3. Manifest.permission.READ_EXTERNAL_STORAGE,
  4. Manifest.permission.WRITE_EXTERNAL_STORAGE
  5. };
  6. private boolean havePermission = false;
  1. @Override
  2. protected void onResume() {
  3. super.onResume();
  4. checkPermission();
  5. }
  1. private AlertDialog dialog;
  2. private void checkPermission() {
  3. //检查权限(NEED_PERMISSION)是否被授权 PackageManager.PERMISSION_GRANTED表示同意授权
  4. if (Build.VERSION.SDK_INT >= 30) {
  5. if (!Environment.isExternalStorageManager()) {
  6. if (dialog != null) {
  7. dialog.dismiss();
  8. dialog = null;
  9. }
  10. dialog = new AlertDialog.Builder(this)
  11. .setTitle("提示")//设置标题
  12. .setMessage("请开启文件访问权限,否则无法正常使用本应用!")
  13. .setNegativeButton("取消", new DialogInterface.OnClickListener() {
  14. @Override
  15. public void onClick(DialogInterface dialog, int i) {
  16. dialog.dismiss();
  17. }
  18. })
  19. .setPositiveButton("确定", new DialogInterface.OnClickListener() {
  20. @Override
  21. public void onClick(DialogInterface dialog, int which) {
  22. dialog.dismiss();
  23. Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
  24. startActivity(intent);
  25. }
  26. }).create();
  27. dialog.show();
  28. } else {
  29. havePermission = true;
  30. Log.i("swyLog", "Android 11以上,当前已有权限");
  31. }
  32. } else {
  33. if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
  34. if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
  35. //申请权限
  36. if (dialog != null) {
  37. dialog.dismiss();
  38. dialog = null;
  39. }
  40. dialog = new AlertDialog.Builder(this)
  41. .setTitle("提示")//设置标题
  42. .setMessage("请开启文件访问权限,否则无法正常使用本应用!")
  43. .setPositiveButton("确定", new DialogInterface.OnClickListener() {
  44. @Override
  45. public void onClick(DialogInterface dialog, int which) {
  46. dialog.dismiss();
  47. ActivityCompat.requestPermissions(BrowserActivity.this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
  48. }
  49. }).create();
  50. dialog.show();
  51. } else {
  52. havePermission = true;
  53. Log.i("swyLog", "Android 6.0以上,11以下,当前已有权限");
  54. }
  55. } else {
  56. havePermission = true;
  57. Log.i("swyLog", "Android 6.0以下,已获取权限");
  58. }
  59. }
  60. }
  1. @Override
  2. public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
  3. super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  4. switch (requestCode) {
  5. case REQUEST_EXTERNAL_STORAGE: {
  6. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
  7. havePermission = true;
  8. Toast.makeText(this, "授权成功!", Toast.LENGTH_SHORT).show();
  9. } else {
  10. havePermission = false;
  11. Toast.makeText(this, "授权被拒绝!", Toast.LENGTH_SHORT).show();
  12. }
  13. return;
  14. }
  15. }
  16. }

3.文件操作

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

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

(2)保存文件

  1. private void saveLoginAccount(String json) {
  2. if (TextUtils.isEmpty(json)) {
  3. return;
  4. }
  5. Log.i("swyLog", "saveLoginAccount called");
  6. String value = encodeToString(json);
  7. Log.i("swyLog", "save 明文:" + json);
  8. Log.i("swyLog", "save 密文:" + value);
  9. File storage = new File(FILE_SAVE_PATH);
  10. if (!storage.exists()) {
  11. storage.mkdirs();
  12. }
  13. File tmepfile = new File(storage.getPath());
  14. if (!tmepfile.exists()) {
  15. tmepfile.mkdirs();
  16. }
  17. File file = new File(tmepfile, FILE_NAME);
  18. if (file.exists()) {
  19. Log.i("swyLog", "删除原有文件");
  20. file.delete();
  21. }
  22. if (!file.exists()) {
  23. Log.i("swyLog", "文件删除成功");
  24. try {
  25. file.createNewFile();
  26. } catch (IOException e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. FileOutputStream fileOutputStream = null;
  31. try {
  32. fileOutputStream = new FileOutputStream(file);
  33. fileOutputStream.write(value.getBytes());
  34. } catch (Exception e) {
  35. e.printStackTrace();
  36. } finally {
  37. if (fileOutputStream != null) {
  38. try {
  39. fileOutputStream.close();
  40. } catch (IOException e) {
  41. e.printStackTrace();
  42. }
  43. }
  44. }
  45. }

(3)读取文件

  1. private String uploadLoginAccount() {
  2. Log.i("swyLog", "uploadLoginAccount called");
  3. InputStream inputStream = null;
  4. Reader reader = null;
  5. BufferedReader bufferedReader = null;
  6. try {
  7. File storage = new File(FILE_SAVE_PATH);
  8. if (!storage.exists()) {
  9. return "";
  10. }
  11. File file = new File(storage, FILE_NAME);
  12. if (!file.exists()) {
  13. return "";
  14. }
  15. inputStream = new FileInputStream(file);
  16. reader = new InputStreamReader(inputStream);
  17. bufferedReader = new BufferedReader(reader);
  18. StringBuilder result = new StringBuilder();
  19. String temp;
  20. while ((temp = bufferedReader.readLine()) != null) {
  21. result.append(temp);
  22. }
  23. String value = decodeToString(result.toString());
  24. Log.i("swyLog", "upload 密文:" + result);
  25. Log.i("swyLog", "upload 明文:" + value);
  26. return value;
  27. } catch (Exception e) {
  28. e.printStackTrace();
  29. } finally {
  30. if (reader != null) {
  31. try {
  32. reader.close();
  33. } catch (IOException e) {
  34. e.printStackTrace();
  35. }
  36. }
  37. if (inputStream != null) {
  38. try {
  39. inputStream.close();
  40. } catch (IOException e) {
  41. e.printStackTrace();
  42. }
  43. }
  44. if (bufferedReader != null) {
  45. try {
  46. bufferedReader.close();
  47. } catch (IOException e) {
  48. e.printStackTrace();
  49. }
  50. }
  51. }
  52. return "";
  53. }

(4)删除文件

  1. private void deleteLoginAccount() {
  2. Log.i("swyLog", "deleteLoginAccount called");
  3. File storage = new File(FILE_SAVE_PATH);
  4. if (!storage.exists()) {
  5. storage.mkdirs();
  6. }
  7. File tmepfile = new File(storage.getPath());
  8. if (!tmepfile.exists()) {
  9. tmepfile.mkdirs();
  10. }
  11. File file = new File(tmepfile, FILE_NAME);
  12. if (file.exists()) {
  13. try {
  14. Log.i("swyLog", "删除原有文件");
  15. file.delete();
  16. } catch (Exception e) {
  17. e.printStackTrace();
  18. }
  19. }
  20. if (!file.exists()) {
  21. Log.i("swyLog", "文件删除成功");
  22. }
  23. }

(5)base64 加解密方法

  1. /**
  2. * 字符Base64加密
  3. *
  4. * @param str
  5. * @return
  6. */
  7. public static String encodeToString(String str) {
  8. try {
  9. return Base64.encodeToString(str.getBytes("UTF-8"), Base64.DEFAULT);
  10. } catch (UnsupportedEncodingException e) {
  11. e.printStackTrace();
  12. }
  13. return "";
  14. }
  15. /**
  16. * 字符Base64解密
  17. *
  18. * @param str
  19. * @return
  20. */
  21. public static String decodeToString(String str) {
  22. try {
  23. return new String(Base64.decode(str.getBytes("UTF-8"), Base64.DEFAULT));
  24. } catch (UnsupportedEncodingException e) {
  25. e.printStackTrace();
  26. }
  27. return "";
  28. }

说明:我这里是从项目中复制的代码,作用是,将字符串加密之后,保存到sd卡种,加密的原因自然不言而喻,因为有些信息是不方便直接展示给用户看的。

注:本文转载自blog.csdn.net的邵旺运的文章"https://blog.csdn.net/weixin_53324308/article/details/129966403"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

105
移动开发
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top