请求在Android 13文件系统上获得写入权限的方法

huangapple go评论118阅读模式
英文:

How to request write permission on the file system Android 13

问题

Here is the translated content from your text:

  1. 我正在将我的 Android 应用定向为 Android 13 (API 33)。
  2. 我已从列表生成了一个 Excel 文件并保存了它,但它不能在 API 33 上保存,但在 Android 33 以下可以保存得很好。
  3. > 如果需要,已使用以下库
  4. >
  5. > implementation 'org.apache.poi:poi:4.0.0'
  6. > implementation 'org.apache.poi:poi-ooxml:4.0.0'
  7. > 清单权限
  8. >
  9. > <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  10. > <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
  11. 检查权限
  12. private void checkPermission() {
  13. if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
  14. if (getApplicationContext().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
  15. String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
  16. requestPermissions(permissions, 1);
  17. } else {
  18. importData();
  19. }
  20. } else {
  21. importData();
  22. }
  23. }
  24. 创建 Excel 文件和存储
  25. private void importData() {
  26. // 从编辑文本获取数据
  27. try {
  28. userList.add(new SheetModel("kawcher", "0181238383", "nmkawcher112@gmail.com"));
  29. userList.add(new SheetModel("shuvo", "0171238383", "demo1@gmail.com"));
  30. userList.add(new SheetModel("hasan", "0161238383", "demo2@gmail.com"));
  31. userList.add(new SheetModel("habib", "0151238383", "demo3@gmail.com"));
  32. userList.add(new SheetModel("selim", "0131238383", "demo4@gmail.com"));
  33. userList.add(new SheetModel("tayeb", "0121238383", "demo5@gmail.com"));
  34. userList.add(new SheetModel("abul kalam", "0191238383", "demo6@gmail.com"));
  35. userList.add(new SheetModel("Kamal", "0101238383", "demo7@gmail.com"));
  36. } catch (Exception e) {
  37. e.printStackTrace();
  38. }
  39. if (userList.size() > 0) {
  40. createXlFile();
  41. } else {
  42. Toast.makeText(this, "列表为空", Toast.LENGTH_SHORT).show();
  43. }
  44. }
  45. private void createXlFile() {
  46. // File filePath = new File(Environment.getExternalStorageDirectory() + "/Demo.xls");
  47. Workbook wb = new HSSFWorkbook();
  48. Cell cell = null;
  49. Sheet sheet = null;
  50. sheet = wb.createSheet("演示 Excel 表");
  51. // 现在的列和行
  52. Row row = sheet.createRow(0);
  53. cell = row.createCell(0);
  54. cell.setCellValue("个人姓名");
  55. cell = row.createCell(1);
  56. cell.setCellValue("电话号码");
  57. cell = row.createCell(2);
  58. cell.setCellValue("电子邮件地址");
  59. // 列宽
  60. sheet.setColumnWidth(0, (20 * 200));
  61. sheet.setColumnWidth(1, (30 * 200));
  62. sheet.setColumnWidth(2, (30 * 200));
  63. for (int i = 0; i < userList.size(); i++) {
  64. Row row1 = sheet.createRow(i + 1);
  65. cell = row1.createCell(0);
  66. cell.setCellValue(userList.get(i).getName());
  67. cell = row1.createCell(1);
  68. cell.setCellValue((userList.get(i).getPhoneNo()));
  69. cell = row1.createCell(2);
  70. cell.setCellValue(userList.get(i).getEmail());
  71. sheet.setColumnWidth(0, (20 * 200));
  72. sheet.setColumnWidth(1, (30 * 200));
  73. sheet.setColumnWidth(2, (30 * 200));
  74. }
  75. String folderName = "导入 Excel";
  76. String fileName = folderName + System.currentTimeMillis() + ".xls";
  77. String path = Environment.getExternalStorageDirectory() + File.separator + folderName + File.separator + fileName;
  78. File file = new File(Environment.getExternalStorageDirectory() + File.separator + folderName);
  79. if (!file.exists()) {
  80. file.mkdirs();
  81. }
  82. FileOutputStream outputStream = null;
  83. try {
  84. //
  85. outputStream = new FileOutputStream(path);
  86. wb.write(outputStream);
  87. // ShareViaEmail(file.getParentFile().getName(),file.getName());
  88. Toast.makeText(getApplicationContext(), "Excel 已创建在 " + path, Toast.LENGTH_SHORT).show();
  89. } catch (IOException e) {
  90. e.printStackTrace();
  91. Toast.makeText(getApplicationContext(), "不正常", Toast.LENGTH_LONG).show();
  92. try {
  93. outputStream.close();
  94. } catch (Exception ex) {
  95. ex.printStackTrace();
  96. }
  97. }
  98. }
  99. 错误日志:
  100. /System.err: java.io.FileNotFoundException: /storage/emulated/0/Import Excel/Import Excel1681376608447.xls: 打开失败: ENOENT(没有该文件或目录)
  101. ...

Please note that some parts of the code are still in English as they contain code elements and variable names.

英文:

I am targeting my Android app for Android 13 (API 33)

I have generated an Excel file from my list and saved it but it doesn't save in API 33 but less than API Android 33 save very well.

> If needed, these libraries have been used
>
> implementation 'org.apache.poi:poi:4.0.0'
> implementation 'org.apache.poi:poi-ooxml:4.0.0'
>

> Manifest permission
>
> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

Check Permission

  1. private void checkPermission() {
  2. if (Build.VERSION.SDK_INT &gt; Build.VERSION_CODES.M) {
  3. if (getApplicationContext().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
  4. String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
  5. requestPermissions(permissions, 1);
  6. } else {
  7. importData();
  8. }
  9. } else {
  10. importData();
  11. }
  12. }

make excel files and storage

  1. private void importData() {
  2. //get data from edit text
  3. try {
  4. userList.add(new SheetModel(&quot;kawcher&quot;, &quot;0181238383&quot;, &quot;nmkawcher112@gmail.com&quot;));
  5. userList.add(new SheetModel(&quot;shuvo&quot;, &quot;0171238383&quot;, &quot;demo1@gmail.com&quot;));
  6. userList.add(new SheetModel(&quot;hasan&quot;, &quot;0161238383&quot;, &quot;demo2@gmail.com&quot;));
  7. userList.add(new SheetModel(&quot;habib&quot;, &quot;0151238383&quot;, &quot;demo3@gmail.com&quot;));
  8. userList.add(new SheetModel(&quot;selim&quot;, &quot;0131238383&quot;, &quot;demo4@gmail.com&quot;));
  9. userList.add(new SheetModel(&quot;tayeb&quot;, &quot;0121238383&quot;, &quot;demo5@gmail.com&quot;));
  10. userList.add(new SheetModel(&quot;abul kalam&quot;, &quot;0191238383&quot;, &quot;demo6@gmail.com&quot;));
  11. userList.add(new SheetModel(&quot;Kamal&quot;, &quot;0101238383&quot;, &quot;demo7@gmail.com&quot;));
  12. }catch (Exception e){e.printStackTrace();}
  13. if (userList.size() &gt; 0) {
  14. createXlFile();
  15. } else {
  16. Toast.makeText(this, &quot;list are empty&quot;, Toast.LENGTH_SHORT).show();
  17. }
  18. }
  19. private void createXlFile() {
  20. // File filePath = new File(Environment.getExternalStorageDirectory() + &quot;/Demo.xls&quot;);
  21. Workbook wb = new HSSFWorkbook();
  22. Cell cell = null;
  23. Sheet sheet = null;
  24. sheet = wb.createSheet(&quot;Demo Excel Sheet&quot;);
  25. //Now column and row
  26. Row row = sheet.createRow(0);
  27. cell = row.createCell(0);
  28. cell.setCellValue(&quot;Person Name&quot;);
  29. cell = row.createCell(1);
  30. cell.setCellValue(&quot;Phone Number&quot;);
  31. cell = row.createCell(2);
  32. cell.setCellValue(&quot;Email Address&quot;);
  33. //column width
  34. sheet.setColumnWidth(0, (20 * 200));
  35. sheet.setColumnWidth(1, (30 * 200));
  36. sheet.setColumnWidth(2, (30 * 200));
  37. for (int i = 0; i &lt; userList.size(); i++) {
  38. Row row1 = sheet.createRow(i + 1);
  39. cell = row1.createCell(0);
  40. cell.setCellValue(userList.get(i).getName());
  41. cell = row1.createCell(1);
  42. cell.setCellValue((userList.get(i).getPhoneNo()));
  43. // cell.setCellStyle(cellStyle);
  44. cell = row1.createCell(2);
  45. cell.setCellValue(userList.get(i).getEmail());
  46. sheet.setColumnWidth(0, (20 * 200));
  47. sheet.setColumnWidth(1, (30 * 200));
  48. sheet.setColumnWidth(2, (30 * 200));
  49. }
  50. String folderName = &quot;Import Excel&quot;;
  51. String fileName = folderName + System.currentTimeMillis() + &quot;.xls&quot;;
  52. String path = Environment.getExternalStorageDirectory() + File.separator + folderName + File.separator + fileName;
  53. File file = new File(Environment.getExternalStorageDirectory() + File.separator + folderName);
  54. if (!file.exists()) {
  55. file.mkdirs();
  56. }
  57. // file.deleteOnExit();
  58. FileOutputStream outputStream = null;
  59. try {
  60. //
  61. outputStream = new FileOutputStream(path);
  62. // outputStream = new FileOutputStream(new File(getFilesDir()., path));
  63. wb.write(outputStream);
  64. // ShareViaEmail(file.getParentFile().getName(),file.getName());
  65. Toast.makeText(getApplicationContext(), &quot;Excel Created in &quot; + path, Toast.LENGTH_SHORT).show();
  66. } catch (IOException e) {
  67. e.printStackTrace();
  68. Toast.makeText(getApplicationContext(), &quot;Not OK&quot;, Toast.LENGTH_LONG).show();
  69. try {
  70. outputStream.close();
  71. } catch (Exception ex) {
  72. ex.printStackTrace();
  73. }
  74. }
  75. }

Error logcat:

  1. /System.err: java.io.FileNotFoundException: /storage/emulated/0/Import Excel/Import Excel1681376608447.xls: open
  2. failed: ENOENT (No such file or directory)
  3. at libcore.io.IoBridge.open(IoBridge.java:574)
  4. at java.io.FileOutputStream.&lt;init&gt;(FileOutputStream.java:236)
  5. at java.io.FileOutputStream.&lt;init&gt;(FileOutputStream.java:125)
  6. at com.roomack.amlaak.view.activity.MainActivity.createXlFile(MainActivity.java:1125)
  7. at com.roomack.amlaak.view.activity.MainActivity.importData(MainActivity.java:1051)
  8. at com.roomack.amlaak.view.activity.MainActivity.checkPermission(MainActivity.java:1020)
  9. at com.roomack.amlaak.view.activity.MainActivity.access$300(MainActivity.java:100)
  10. at com.roomack.amlaak.view.activity.MainActivity$18.onClick(MainActivity.java:821)
  11. at android.view.View.performClick(View.java:7560)
  12. at android.view.View.performClickInternal(View.java:7533)
  13. at ndroid.view.View.-$$Nest$mperformClickInternal(Unknown Source:0)
  14. at android.view.View$PerformClick.run(View.java:29754)
  15. W/System.err: at android.os.Handler.handleCallback(Handler.java:942)
  16. at android.os.Handler.dispatchMessage(Handler.java:99)
  17. at android.os.Looper.loopOnce(Looper.java:211)
  18. at android.os.Looper.loop(Looper.java:300)
  19. at android.app.ActivityThread.main(ActivityThread.java:8143)
  20. at java.lang.reflect.Method.invoke(Native Method)
  21. at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:580)
  22. at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1028)
  23. Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
  24. at libcore.io.Linux.open(Native Method)
  25. at libcore.io.ForwardingOs.open(ForwardingOs.java:563)
  26. at libcore.io.BlockGuardOs.open(BlockGuardOs.java:274)
  27. at libcore.io.ForwardingOs.open(ForwardingOs.java:563)
  28. at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:8019)
  29. at libcore.io.IoBridge.open(IoBridge.java:560)

答案1

得分: 1

你无法在Android 13设备上请求写入权限。

在所有应用特定目录和外部存储的所有公共目录中,您都自动具有写入权限。

英文:

You cannot request write permission on Android 13 devices.

You automatically have write permission in all app specific directories and all public directories on external storage.

答案2

得分: 0

In HomeFragment.kt中调用如下方式:

  1. binding.btHomeExport.setOnClickListener {
  2. GlobalScope.launch {
  3. exportData(requireActivity())
  4. }
  5. }

Export.kt只是一个从Java实用程序类转换为Kotlin的实用程序类,实际上只是为了移出代码:

  1. object Export {
  2. suspend fun exportData(activity: Activity) {
  3. // 其他代码...
  4. }
  5. }

今天(2023年5月22日),它在Android 33上运行,但明天可能会因Google更改API而不起作用。

英文:

In HomeFragment.kt is called like this:

  1. binding.btHomeExport.setOnClickListener {
  2. GlobalScope.launch {
  3. exportData(requireActivity())
  4. }
  5. }

The Export.kt it is just a Java utility class converted to Kotlin, practically just to move out the code:

object Export {
suspend fun exportData(activity: Activity) {

  1. try {
  2. // read again from file?
  3. val listMyDealWithMyClient = doReadFromFile(activity)
  4. val timeZoneDate = SimpleDateFormat(&quot;yyyy-MMM-dd_HH-mm-ss&quot;, Locale.getDefault())
  5. val formattedDate = timeZoneDate.format( Date())
  6. val workbook = XSSFWorkbook()
  7. val workSheet = workbook.createSheet(&quot;MyDeals_$formattedDate&quot;)
  8. val colorMap = workbook.stylesSource.indexedColors
  9. val cellStyleHeader = workbook.createCellStyle()
  10. cellStyleHeader.fillForegroundColor = IndexedColors.AQUA.getIndex()
  11. cellStyleHeader.fillPattern = FillPatternType.SOLID_FOREGROUND
  12. cellStyleHeader.font.bold = true
  13. cellStyleHeader.verticalAlignment = VerticalAlignment.CENTER
  14. cellStyleHeader.alignment = HorizontalAlignment.CENTER
  15. cellStyleHeader.setRightBorderColor( XSSFColor(byteArrayOf(0, 0, 0), colorMap))
  16. cellStyleHeader.borderRight = BorderStyle.THIN
  17. val row0 = workSheet.createRow(0)
  18. row0.height = 800

more code here, which are data procesing ...

  1. // save workbook to file:
  2. val fileName = &quot;data_$formattedDate.xlsx&quot;
  3. val fos: FileOutputStream =
  4. activity.openFileOutput(fileName, Context.MODE_PRIVATE)!!
  5. workbook.write(fos)
  6. workbook.close()
  7. withContext(Dispatchers.IO) {
  8. fos.flush()
  9. fos.close();
  10. };
  11. //need: fos.path, but it is private!
  12. val appPath = activity.application?.filesDir?.absolutePath
  13. // delete old .xlsx files
  14. val dir = appPath?.let { File(it) }
  15. dir?.listFiles()!!.forEach { file -&gt;
  16. run {
  17. if (file.name.endsWith(&quot;.xlsx&quot;)) {
  18. file.deleteOnExit()
  19. }
  20. }
  21. }
  22. val exportFile = File(appPath, fileName)
  23. val sharingIntent = Intent(Intent.ACTION_SEND)
  24. val fileUri =
  25. FileProvider.getUriForFile(//
  26. activity.applicationContext!!,
  27. activity.packageName + &quot;.fileProvider&quot;,
  28. exportFile
  29. );

VERY IMPORTANT &quot;.fileProvider&quot; must match the case with others:
Manifest:

  1. &lt;application
  2. android:allowBackup=&quot;false&quot;
  3. android:dataExtractionRules=&quot;@xml/data_extraction_rules&quot;
  4. android:fullBackupContent=&quot;@xml/backup_rules&quot;
  5. android:icon=&quot;@mipmap/ic_launcher&quot;
  6. android:label=&quot;@string/app_name&quot;
  7. android:roundIcon=&quot;@mipmap/ic_launcher_round&quot;
  8. android:supportsRtl=&quot;true&quot;
  9. android:theme=&quot;@style/Theme.MyAppTheme&quot;
  10. tools:targetApi=&quot;33&quot;&gt;
  11. &lt;provider
  12. android:name=&quot;androidx.core.content.FileProvider&quot;
  13. android:authorities=&quot;my.package.with.myid.fileProvider&quot;
  14. android:grantUriPermissions=&quot;true&quot;
  15. android:exported=&quot;false&quot;&gt;
  16. &lt;meta-data
  17. android:name=&quot;android.support.FILE_PROVIDER_PATHS&quot;
  18. android:resource=&quot;@xml/file_provider_path&quot;/&gt;
  19. &lt;/provider&gt;
  20. &lt;activity
  21. android:name=

NOT needed Read External, Write External permissions! None needed!

At res/xml create a file file_provider_path.xml

Paste the content:

  1. &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
  2. &lt;paths&gt;
  3. &lt;files-path
  4. name=&quot;files&quot;
  5. path=&quot;.&quot; /&gt;
  6. &lt;/paths&gt;

The file it wil be exported, not sure how it can be accessed by other apps. That's why I do a share / send file and I let the user choose the Intent:

  1. // add provider
  2. sharingIntent.type = &quot;*/*&quot;
  3. sharingIntent.putExtra(Intent.EXTRA_STREAM, fileUri)
  4. sharingIntent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
  5. activity.startActivity(sharingIntent)
  6. } catch (ex: Exception) {
  7. ex.printStackTrace()
  8. Toast.makeText(activity, ex.message, Toast.LENGTH_LONG).show();
  9. }
  10. }
  11. }

This is the final part of the Export.kt

Today (May 22, 2023) it is working with Android 33...tomorrow maybe not -as how Google changes their API...

I don't target other devices, just Android 33 - because it is a utility app for somebody. It were many changes at Androi pre 8, post 8, pre 9 , post 9, pre 10, post 10, pre 11, pre 12, post 12, pre 13, and +13
Spent like 10 days to put the lego pieces together 请求在Android 13文件系统上获得写入权限的方法

As testing I am sending the .xlsx file via Bluetooth to Desktop PC ( Windowws 10) and checking there the data + formatting, and is working!

huangapple
  • 本文由 发表于 2023年4月13日 17:16:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76003739.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定