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

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

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

问题

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

public class MyActivity extends AppCompatActivity {
    @Override
    public boolean onOptionsItemSelected(MenuItem menuItem) {
        int n_requestCode;

        switch(menuItem.getItemId()) {
            // ...
            case R.id.delete_file:
                n_requestCode = 108;
                startSAFActionOpenDocumentTree(n_requestCode);
                break;
            // ...
        }
        // ...
    }

    public void startSAFActionOpenDocumentTree(int n_requestCode) {
        Intent intent;

        intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);	
        startActivityForResult(intent, n_requestCode);
    }

    private void startSAFActionOpenDocument(int n_requestCode) {
        Intent intent = null;

        intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        startActivityForResult(intent, n_requestCode);
    }

    protected void onActivityResult(int n_requestCode, int n_resultCode, Intent data) {
        android.net.Uri uri;
        ContentResolver contentResolver;

        if (n_requestCode == 108) {
            n_requestCode = 109;
            startSAFActionOpenDocument(n_requestCode);
        } else if (n_requestCode == 109) {
            uri = data.getData();                      
            contentResolver = getContentResolver();

            try {
                contentResolver.delete(uri, null, null);
            } catch (Exception exn) {
                exn.printStackTrace();
            }
        }
    }
}

因此,使用案例如下:

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

问题如下:

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

W/System.err: java.lang.UnsupportedOperationException: Delete not supported
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:167)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
at android.content.ContentProviderProxy.delete(ContentProviderNative.java:544)
at android.content.ContentResolver.delete(ContentResolver.java:1330)
at [...]MyActivity.onActivityResult(MyActivity.java:[...])
at android.app.Activity.dispatchActivityResult(Activity.java:6490)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3695)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742)
at android.app.ActivityThread.access$1400(ActivityThread.java:150)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393)
W/System.err:   at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
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:

public class MyActivity extends AppCompatActivity
{
@Override
public boolean onOptionsItemSelected(MenuItem menuItem)
{
int n_requestCode;
switch(menuItem.getItemId())
{
[...]
case R.id.delete_file:
n_requestCode = 108;
startSAFActionOpenDocumentTree(n_requestCode);
break;
[...]
}
[...]
}
public void startSAFActionOpenDocumentTree(int n_requestCode)
{
Intent intent;
intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);	
startActivityForResult(intent, n_requestCode);
}
private void startSAFActionOpenDocument(int n_requestCode)
{
Intent intent = null;
intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
startActivityForResult(intent, n_requestCode);
}
protected void onActivityResult(int n_requestCode, int n_resultCode, Intent data)
{
android.net.Uri uri;
ContentResolver contentResolver;
if(n_requestCode == 108)
{
n_requestCode = 109;
startSAFActionOpenDocument(n_requestCode);
}
else if(n_requestCode == 109)
{
uri = data.getData();                      
contentResolver = getContentResolver();
try
{
contentResolver.delete(uri, null, null);
}
catch(Exception exn)
{
exn.printStackTrace();
}
}
}
}

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:

W/System.err: java.lang.UnsupportedOperationException: Delete not supported
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:167)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
at android.content.ContentProviderProxy.delete(ContentProviderNative.java:544)
at android.content.ContentResolver.delete(ContentResolver.java:1330)
at [...]MyActivity.onActivityResult(MyActivity.java:[...])
at android.app.Activity.dispatchActivityResult(Activity.java:6490)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3695)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742)
at android.app.ActivityThread.access$1400(ActivityThread.java:150)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393)
W/System.err:   at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
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

操作不受支持是该消息。

请尝试改为:

DocumentFile srcDoc = DocumentFile.fromSingleUri(context, data.getData());

if (srcDoc.delete()) {

}

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

英文:

The operation is not supported is the message.

Try instead:

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

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

答案2

得分: 2

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

文件已删除。

public class MyActivity extends AppCompatActivity
{    
    @Override
    public boolean onOptionsItemSelected(MenuItem menuItem)
    {
        int n_requestCode;

        switch(menuItem.getItemId())
        {
            [...]
            case R.id.delete_file:
                n_requestCode = 109;
                startSAFActionOpenDocument(n_requestCode);
                break;
            [...]
        }
        [...]
    }

    private void startSAFActionOpenDocument(int n_requestCode)
    {
        Intent intent = null;

        intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        startActivityForResult(intent, n_requestCode);
    }

    protected void onActivityResult(int n_requestCode, int n_resultCode, Intent data)
    {
        DocumentFile srcDoc;

        if(n_requestCode == 109)
        {
            srcDoc = DocumentFile.fromSingleUri(this, data.getData());
            try
            {
                srcDoc.delete();
            }
            catch(Exception exn)
            {
                exn.printStackTrace();
            }                
        }
    }
}
英文:

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

The file is deleted.

public class MyActivity extends AppCompatActivity
{    
@Override
public boolean onOptionsItemSelected(MenuItem menuItem)
{
int n_requestCode;
switch(menuItem.getItemId())
{
[...]
case R.id.delete_file:
n_requestCode = 109;
startSAFActionOpenDocument(n_requestCode);
break;
[...]
}
[...]
}
private void startSAFActionOpenDocument(int n_requestCode)
{
Intent intent = null;
intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
startActivityForResult(intent, n_requestCode);
}
protected void onActivityResult(int n_requestCode, int n_resultCode, Intent data)
{
DocumentFile srcDoc;
if(n_requestCode == 109)
{
srcDoc = DocumentFile.fromSingleUri(this, data.getData());
try
{
srcDoc.delete();
}
catch(Exception exn)
{
exn.printStackTrace();
}                
}
}
}

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:

确定