Deleting a file given a Storage Access Framework uri and using content resolver fails

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

Deleting a file given a Storage Access Framework uri and using content resolver fails

问题

我正在尝试使用“存储访问框架(Storage Access Framework)”来删除文件。
以下是一些代码元素:

  1. public class MyActivity extends AppCompatActivity {
  2. @Override
  3. public boolean onOptionsItemSelected(MenuItem menuItem) {
  4. int n_requestCode;
  5. switch(menuItem.getItemId()) {
  6. // ...
  7. case R.id.delete_file:
  8. n_requestCode = 108;
  9. startSAFActionOpenDocumentTree(n_requestCode);
  10. break;
  11. // ...
  12. }
  13. // ...
  14. }
  15. public void startSAFActionOpenDocumentTree(int n_requestCode) {
  16. Intent intent;
  17. intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
  18. startActivityForResult(intent, n_requestCode);
  19. }
  20. private void startSAFActionOpenDocument(int n_requestCode) {
  21. Intent intent = null;
  22. intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
  23. intent.addCategory(Intent.CATEGORY_OPENABLE);
  24. intent.setType("*/*");
  25. startActivityForResult(intent, n_requestCode);
  26. }
  27. protected void onActivityResult(int n_requestCode, int n_resultCode, Intent data) {
  28. android.net.Uri uri;
  29. ContentResolver contentResolver;
  30. if (n_requestCode == 108) {
  31. n_requestCode = 109;
  32. startSAFActionOpenDocument(n_requestCode);
  33. } else if (n_requestCode == 109) {
  34. uri = data.getData();
  35. contentResolver = getContentResolver();
  36. try {
  37. contentResolver.delete(uri, null, null);
  38. } catch (Exception exn) {
  39. exn.printStackTrace();
  40. }
  41. }
  42. }
  43. }

因此,使用案例如下:

  • 用户点击活动菜单中ID为 R.id.delete_file 的条目。
  • 然后用户必须选择一个目录
  • 然后在此目录中选择一个文件。这是代码中检索到一个 android.net.Uri 的地方。
  • 给定此 URI,我想删除相应的文件。

问题如下:

contentResolver.delete(uri, null, null); 引发以下异常:

  1. W/System.err: java.lang.UnsupportedOperationException: Delete not supported
  2. at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:167)
  3. at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
  4. at android.content.ContentProviderProxy.delete(ContentProviderNative.java:544)
  5. at android.content.ContentResolver.delete(ContentResolver.java:1330)
  6. at [...]MyActivity.onActivityResult(MyActivity.java:[...])
  7. at android.app.Activity.dispatchActivityResult(Activity.java:6490)
  8. at android.app.ActivityThread.deliverResults(ActivityThread.java:3695)
  9. at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742)
  10. at android.app.ActivityThread.access$1400(ActivityThread.java:150)
  11. at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393)
  12. W/System.err: at android.os.Handler.dispatchMessage(Handler.java:102)
  13. at android.os.Looper.loop(Looper.java:148)
  14. at android.app.ActivityThread.main(ActivityThread.java:5417)
  15. at java.lang.reflect.Method.invoke(Native Method)
  16. at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
  17. at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

请注意,代码的另一个位置,我使用 java.io.File 类的 delete() 方法,并且参数是文件路径(字符串),而不是 android.net.Uri,并且对于完全相同的文件,删除操作是可行的。

能否请您帮助我解决这个问题?谢谢。

英文:

I am trying to delete a file using Storage Access Framework.
Below are some elements of code:

  1. public class MyActivity extends AppCompatActivity
  2. {
  3. @Override
  4. public boolean onOptionsItemSelected(MenuItem menuItem)
  5. {
  6. int n_requestCode;
  7. switch(menuItem.getItemId())
  8. {
  9. [...]
  10. case R.id.delete_file:
  11. n_requestCode = 108;
  12. startSAFActionOpenDocumentTree(n_requestCode);
  13. break;
  14. [...]
  15. }
  16. [...]
  17. }
  18. public void startSAFActionOpenDocumentTree(int n_requestCode)
  19. {
  20. Intent intent;
  21. intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
  22. startActivityForResult(intent, n_requestCode);
  23. }
  24. private void startSAFActionOpenDocument(int n_requestCode)
  25. {
  26. Intent intent = null;
  27. intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
  28. intent.addCategory(Intent.CATEGORY_OPENABLE);
  29. intent.setType("*/*");
  30. startActivityForResult(intent, n_requestCode);
  31. }
  32. protected void onActivityResult(int n_requestCode, int n_resultCode, Intent data)
  33. {
  34. android.net.Uri uri;
  35. ContentResolver contentResolver;
  36. if(n_requestCode == 108)
  37. {
  38. n_requestCode = 109;
  39. startSAFActionOpenDocument(n_requestCode);
  40. }
  41. else if(n_requestCode == 109)
  42. {
  43. uri = data.getData();
  44. contentResolver = getContentResolver();
  45. try
  46. {
  47. contentResolver.delete(uri, null, null);
  48. }
  49. catch(Exception exn)
  50. {
  51. exn.printStackTrace();
  52. }
  53. }
  54. }
  55. }

Hence, the use case is the following:

  • The user taps the activity menu entry which id is R.id.delete_file.
  • Then the user has to select a directory
  • and then a file in this directory. This is where an android.net.Uri is retrieved in the code.
  • Given this uri, I would like to delete the corresponding file.

The problem is the following:

The contentResolver.delete(uri, null, null); raises the following exception:

  1. W/System.err: java.lang.UnsupportedOperationException: Delete not supported
  2. at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:167)
  3. at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
  4. at android.content.ContentProviderProxy.delete(ContentProviderNative.java:544)
  5. at android.content.ContentResolver.delete(ContentResolver.java:1330)
  6. at [...]MyActivity.onActivityResult(MyActivity.java:[...])
  7. at android.app.Activity.dispatchActivityResult(Activity.java:6490)
  8. at android.app.ActivityThread.deliverResults(ActivityThread.java:3695)
  9. at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742)
  10. at android.app.ActivityThread.access$1400(ActivityThread.java:150)
  11. at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393)
  12. W/System.err: at android.os.Handler.dispatchMessage(Handler.java:102)
  13. at android.os.Looper.loop(Looper.java:148)
  14. at android.app.ActivityThread.main(ActivityThread.java:5417)
  15. at java.lang.reflect.Method.invoke(Native Method)
  16. at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
  17. at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

Note that, at another place in the code, I use the delete() method of the java.io.File class with an argument that is a file path (a String), not an android.net.Uri and the deletion works for the very same file.

Can you please help me solve that problem? Thanks.

答案1

得分: 4

操作不受支持是该消息。

请尝试改为:

  1. DocumentFile srcDoc = DocumentFile.fromSingleUri(context, data.getData());
  2. if (srcDoc.delete()) {
  3. }

您的回答可能有效,但代码过于复杂。
此外,用户无需首先选择目录。

英文:

The operation is not supported is the message.

Try instead:

  1. DocumentFile srcDoc = DocumentFile.fromSingleUri(context, data.getData());
  2. if ( srcDoc.delete() )
  3. {
  4. }

Your answer may work but code is too complicated.
Also the user does not have to select the directory first.

答案2

得分: 2

我使用了DocumentFile类代替ContentResolver来找到这个解决方案。

文件已删除。

  1. public class MyActivity extends AppCompatActivity
  2. {
  3. @Override
  4. public boolean onOptionsItemSelected(MenuItem menuItem)
  5. {
  6. int n_requestCode;
  7. switch(menuItem.getItemId())
  8. {
  9. [...]
  10. case R.id.delete_file:
  11. n_requestCode = 109;
  12. startSAFActionOpenDocument(n_requestCode);
  13. break;
  14. [...]
  15. }
  16. [...]
  17. }
  18. private void startSAFActionOpenDocument(int n_requestCode)
  19. {
  20. Intent intent = null;
  21. intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
  22. intent.addCategory(Intent.CATEGORY_OPENABLE);
  23. intent.setType("*/*");
  24. startActivityForResult(intent, n_requestCode);
  25. }
  26. protected void onActivityResult(int n_requestCode, int n_resultCode, Intent data)
  27. {
  28. DocumentFile srcDoc;
  29. if(n_requestCode == 109)
  30. {
  31. srcDoc = DocumentFile.fromSingleUri(this, data.getData());
  32. try
  33. {
  34. srcDoc.delete();
  35. }
  36. catch(Exception exn)
  37. {
  38. exn.printStackTrace();
  39. }
  40. }
  41. }
  42. }
英文:

I found this solution using the class DocumentFile instead of ContentResolver.

The file is deleted.

  1. public class MyActivity extends AppCompatActivity
  2. {
  3. @Override
  4. public boolean onOptionsItemSelected(MenuItem menuItem)
  5. {
  6. int n_requestCode;
  7. switch(menuItem.getItemId())
  8. {
  9. [...]
  10. case R.id.delete_file:
  11. n_requestCode = 109;
  12. startSAFActionOpenDocument(n_requestCode);
  13. break;
  14. [...]
  15. }
  16. [...]
  17. }
  18. private void startSAFActionOpenDocument(int n_requestCode)
  19. {
  20. Intent intent = null;
  21. intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
  22. intent.addCategory(Intent.CATEGORY_OPENABLE);
  23. intent.setType("*/*");
  24. startActivityForResult(intent, n_requestCode);
  25. }
  26. protected void onActivityResult(int n_requestCode, int n_resultCode, Intent data)
  27. {
  28. DocumentFile srcDoc;
  29. if(n_requestCode == 109)
  30. {
  31. srcDoc = DocumentFile.fromSingleUri(this, data.getData());
  32. try
  33. {
  34. srcDoc.delete();
  35. }
  36. catch(Exception exn)
  37. {
  38. exn.printStackTrace();
  39. }
  40. }
  41. }
  42. }

huangapple
  • 本文由 发表于 2020年8月25日 21:12:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/63579633.html
匿名

发表评论

匿名网友

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

确定