studio permission_granted permission permisos dar almacenamiento android android-fileprovider

permission_granted - permisos bluetooth android studio



Android-proveedor de archivos-denegaciĆ³n de permiso (9)

java.lang.SecurityException: denegación de permiso: ...

Consulte https://stackoverflow.com/a/44455957/966789 (Android agregó un nuevo modelo de permiso para Android 6.0 Marshmallow)

Para solicitar permisos en tiempo de ejecución:

String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE}; requestPermissions(permissions, WRITE_REQUEST_CODE);

Tengo dos aplicaciones: app1 y app2.

App2 tiene:

<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.android.provider.ImageSharing" android:exported="false" android:grantUriPermissions="true" > <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/paths" /> </provider>

paths.xml:

<paths> <files-path name="my_images" path="images/"/> </paths>

App2 recibe una solicitud en su Actividad de la App1 para obtener URI para una imagen. La actividad de App2 hace lo siguiente una vez que se decide el URI:

Intent intent = new Intent(); intent.setDataAndType(contentUri, getContentResolver().getType(contentUri)); int uid = Binder.getCallingUid(); String callingPackage = getPackageManager().getNameForUid(uid); getApplicationContext().grantUriPermission(callingPackage, contentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION); setResult(Activity.RESULT_OK, intent); finish();

Al recibir el resultado de App2, App1 hace lo siguiente:

Uri imageUri = data.getData(); if(imageUri != null) { ImageView iv = (ImageView) layoutView.findViewById(R.id.imageReceived); iv.setImageURI(imageUri); }

En App1, al regresar de App2, recibo la siguiente excepción:

java.lang.SecurityException: denegación de permiso: proveedor de apertura android.support.v4.content.FileProvider de ProcessRecord {52a99eb0 3493: com.android.App1.app/u0a57} (pid = 3493, uid = 10057) que no se exporta desde uid 10058

Qué estoy haciendo mal ?


Cómo capturas imágenes usando una cámara en Nougat

y kit kat y malvavisco sigue estos pasos. En primer lugar, proveedor de etiquetas publicitarias bajo etiqueta de aplicación en MainfestFile.

<provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.provider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths"/> </provider>

crea un nombre de archivo con (provider_paths.xml) debajo de la carpeta res

<paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="external_files" path="."/>

He resuelto este problema, viene en kit kitkat versión

private void takePicture() { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (takePictureIntent.resolveActivity(getPackageManager()) != null) { Uri photoURI = null; try { File photoFile = createImageFileWith(); path = photoFile.getAbsolutePath(); photoURI = FileProvider.getUriForFile(MainActivity.this, getString(R.string.file_provider_authority), photoFile); } catch (IOException ex) { Log.e("TakePicture", ex.getMessage()); } takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) { takePictureIntent.setClipData(ClipData.newRawUri("", photoURI)); takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION|Intent.FLAG_GRANT_READ_URI_PERMISSION); } startActivityForResult(takePictureIntent, PHOTO_REQUEST_CODE); } } private File createImageFile() throws IOException { // Create an image file name String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.ENGLISH).format(new Date()); String imageFileName = "JPEG_" + timeStamp + "_"; File storageDir = new File(Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_DCIM), "Camera"); File image = File.createTempFile( imageFileName, /* prefix */ ".jpg", /* suffix */ storageDir /* directory */ ); // Save a file: path for use with ACTION_VIEW intents mCurrentPhotoPath = "file:" + image.getAbsolutePath(); return image; }


Android <= Lollipop (API 22)

Hay un excelente artículo de Lorenzo Quiroli que resuelve este problema para versiones anteriores de Android.

Descubrió que debe configurar manualmente el ClipData del Intento y establecer los permisos para él, así:

if ( Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP ) { takePictureIntent.setClipData( ClipData.newRawUri( "", photoURI ) ); takePictureIntent.addFlags( Intent.FLAG_GRANT_WRITE_URI_PERMISSION|Intent.FLAG_GRANT_READ_URI_PERMISSION ); }

Probé esto en API 17 y funcionó muy bien. No se pudo encontrar una solución en ningún lado que funcionó.


Debe configurar el nombre del paquete específico, luego podrá acceder a él.

Intent sIntent = new Intent("com.appname.ACTION_RETURN_FILE").setData(uri); List<ResolveInfo> resInfoList = activity.getPackageManager().queryIntentActivities(sIntent, PackageManager.MATCH_DEFAULT_ONLY); for (ResolveInfo resolveInfo : resInfoList) { activity.grantUriPermission(FILE_PROVIDER_ID, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); } sIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); activity.setResult(RESULT_OK, sIntent);


Gracias @CommonsWare por su consejo.

El problema fue con el paquete de llamadas. Por alguna razón, Binder.callingUid() y getPackageManager().getNameForUid(uid) me está dando el nombre del paquete de App2 lugar de App1 .

Intenté llamarlo en OnCreate de onCreate así como también en onResume , pero no me onResume .

Usé lo siguiente para resolverlo:

getApplicationContext().grantUriPermission(getCallingPackage(), contentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);

Resulta que la actividad tiene API dedicada para esto. Mira here .


Primero, trataría de grantUriPermission() de grantUriPermission() y simplemente poner el FLAG_GRANT_READ_URI_PERMISSION en el Intent mismo a través de addFlags() o setFlag() .

Si por alguna razón eso no funciona, puede intentar mover su lógica getCallingUid() a onCreate() lugar de donde la tenga, y ver si puede encontrar la "persona que llama" allí.


Resulta que la única forma de resolver esto es otorgando permisos a todos los paquetes que puedan necesitarlo, como este:

List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); for (ResolveInfo resolveInfo : resInfoList) { String packageName = resolveInfo.activityInfo.packageName; context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); }



Solucioné el problema de esa manera:

context.grantUriPermission("com.android.App1.app", fileUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);