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);
}
Solo agregue setData(contentUri);
y según el requisito, agregue addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
o addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
Esto resuelve la java.lang.SecurityException: denegación de permiso
Verificado
Esto se hace de acuerdo con https://developer.android.com/reference/android/support/v4/content/FileProvider.html#Permissions
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);