Java 如何在android API 19(KitKat)中保持权限?

Java 如何在android API 19(KitKat)中保持权限?,java,android,sqlite,android-4.4-kitkat,storage-access-framework,Java,Android,Sqlite,Android 4.4 Kitkat,Storage Access Framework,在我的应用程序中,我将图像的路径存储在SQlite数据库中以供进一步使用。我得到的道路是 content://com.android.providers.media.documents/document/image%3A71964 当我从数据库中检索此路径并尝试从该路径检索图像时 java.lang.SecurityException: Permission Denial: opening provider com.android.providers.media.MediaDocumentsP

在我的应用程序中,我将图像的路径存储在SQlite数据库中以供进一步使用。我得到的道路是

content://com.android.providers.media.documents/document/image%3A71964
当我从数据库中检索此路径并尝试从该路径检索图像时

java.lang.SecurityException: Permission Denial: opening provider
com.android.providers.media.MediaDocumentsProvider 
from ProcessRecord{42c84ec8 23911:com.gots.gb/u0a248} (pid=23911, uid=10248) 
requires android.permission.MANAGE_DOCUMENTS or android.permission.MANAGE_DOCUMENTS
08-21 02:14:38.530: W/System.err(24452): java.lang.SecurityException:
No permission grant found for UID 10248 and Uri 
content://com.android.providers.media.documents/document/image:71964
根据需要,我需要通过添加以下代码来持久化权限

final int takeFlags = intent.getFlags()
        & (Intent.FLAG_GRANT_READ_URI_PERMISSION
        | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// Check for the freshest data.
getContentResolver().takePersistableUriPermission(uri, takeFlags);
当我将此代码添加到ImageAdapter类时,它扩展了BaseAdapter

java.lang.SecurityException: Permission Denial: opening provider
com.android.providers.media.MediaDocumentsProvider 
from ProcessRecord{42c84ec8 23911:com.gots.gb/u0a248} (pid=23911, uid=10248) 
requires android.permission.MANAGE_DOCUMENTS or android.permission.MANAGE_DOCUMENTS
08-21 02:14:38.530: W/System.err(24452): java.lang.SecurityException:
No permission grant found for UID 10248 and Uri 
content://com.android.providers.media.documents/document/image:71964
这是我的ImageAdapter代码的相关部分

public View getView(int position, View convertView, ViewGroup parent) {
    ImageView imageView ;


    if (convertView == null){
        imageView = new ImageView(mContext);
        imageView.setLayoutParams(new GridView.LayoutParams(185, 185));
        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        imageView.setPadding(8, 8, 8, 8);

    }
    else{
        imageView = (ImageView)convertView ;
    }

    InputStream is = null;
    Bitmap bitmap = null ;

    try {

        Log.d(TAG,String.valueOf(list.get(position)));
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        final int takeFlags = intent.getFlags()
                & (Intent.FLAG_GRANT_READ_URI_PERMISSION
                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        // Check for the freshest data.

        if (Build.VERSION.SDK_INT >= 19){
            mContext.getContentResolver().takePersistableUriPermission(list.get(position), takeFlags);
        }


        is = mContext.getContentResolver().openInputStream(list.get(position));

        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 8;
        bitmap = BitmapFactory.decodeStream(is,null, options);
        is.close();
        imageView.setImageBitmap(bitmap);

        return imageView;

    }
    catch (Exception e) {
        e.printStackTrace();

        return null;
    }
我做错了什么?
谢谢,我相信我已经解决了。请求的目的是:

Intent intent;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
    intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
    intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
    intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
}else{
    intent = new Intent(Intent.ACTION_GET_CONTENT);
}
intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setType("image/*");
startActivityForResult(Intent.createChooser(intent, getResources().getString(R.string.form_pick_photos)), REQUEST_PICK_PHOTO);
onActivityResult

...
// kitkat fixed (broke) content access; to keep the URIs valid over restarts need to persist access permission
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    final int takeFlags = data.getFlags() & Intent.FLAG_GRANT_READ_URI_PERMISSION;
    ContentResolver resolver = getActivity().getContentResolver();
    for (Uri uri : images) {
        resolver.takePersistableUriPermission(uri, takeFlags);
    }
}
...
我还没有测试这个pre-kitkat,我的手机正在运行5.1,有人能在旧款手机上验证吗?

下面列出的代码

// kitkat fixed (broke) content access; to keep the URIs valid over restarts need to persist access permission
if(Utils.isKitkat())
{
    final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION);
    ContentResolver resolver = getActivity().getContentResolver();
    for (Uri uri : images)
    {
        resolver.takePersistableUriPermission(uri, takeFlags);
    }
}
对我来说效果很好,但我注意到,授予我的应用程序的最大持久uri数量限制为128。如果选择的uri超过128个,则会出现以下错误:

java.lang.SecurityException: Permission Denial: opening provider........

就在我试图处理一个无法持久化权限的图像时。你能想出解决办法吗?

当你最初得到
Uri
时,而不是当你以后试图使用
Uri
时,试着调用
takePersistableUriPermission()
。另外,请不要在主应用程序线程上调用
ContentResolver
,就像您在
getView()
中的几个点中所做的那样。特别是,
openInputStream()
和您的
BitmapFactory
工作肯定需要移动到后台线程。@Commonware我收到此错误
请求的标志0x1,但只允许0x0
错误。我正在尝试使用
ACTION\u GET\u CONTENT
从图库中检索图像。我还没有玩过这些东西(它在我的待办事项列表中很重要),但我猜图库没有向您提供持久权限。请不要在回答中提问。如果与问题相符,请对问题添加注释,否则打开一个新问题。如果您实际上不需要同时使用所有128个URI,那么也许您应该调用您不需要的URI…非常干净且好的解决方案。有一件事:
Utils.isKitkat()
在没有其他库的情况下不可用。使用
Build.VERSION.SDK\u INT>=19
而不是是,该方法对生成版本进行简单检查。添加到@Erich comment,您可以使用Build.VERSION.SDK\u INT>=Build.VERSION\u CODES.KITKAT使其更具可读性。我收到一条错误消息,表示找不到UID xxxx和Uri 0的持久权限授予@content://media/external/video/media/xxxx.. 有什么问题吗??Tia你保留URI多久了?我想我是在重新安装时使用URI的。