web-dev-qa-db-fra.com

Comment conserver l'autorisation dans l'API Android 19 (KitKat)?

Dans mon application, je stocke le chemin de l'image dans ma base de données SQlite pour une utilisation ultérieure. Le chemin que je reçois est

content://com.Android.providers.media.documents/document/image%3A71964

Lorsque je récupère ce chemin de la base de données et que j'essaie de récupérer l'image de ce chemin, Android renvoie

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

Selon https://developer.Android.com/guide/topics/providers/document-provider.html#permissions Je dois conserver l'autorisation en ajoutant le code suivant

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);

Quand j'ai ajouté ce code à ma classe ImageAdapter, qui étend BaseAdapter, Android lance

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

Ceci est la partie pertinente de mon code 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;
    }

qu'est-ce que je fais mal? Merci

15
Pdksock

Je crois que je l'ai résolu. L'intention de la demande:

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);

et 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);
    }
}
...

Je n'ai pas testé cette pré-KitKat, mon téléphone tourne sous 5.1, est-ce que quelqu'un peut vérifier cela sur des téléphones plus anciens?

25
DariusL

Le code énuméré ci-dessous,

// 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);
    }
}

de toute façon, j’ai remarqué que le nombre maximal d’URI persistants octroyés à mon application est limité à 128. Si je sélectionne plus de 128 uri, j’obtiens l’erreur suivante:

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

juste au moment où j'essaie de traiter une image pour laquelle je n'ai pas pu conserver l'autorisation. Pouvez-vous trouver une solution?

0
David