Android marshmallow solicitud de permiso?
Actualmente estoy trabajando en una aplicación que requiere varios permisos "peligrosos". Así que traté de agregar "pedir permiso" como se requiere en Android Marshmallow (Nivel API 23), pero no pude encontrar la forma de hacerlo.
¿Cómo puedo pedir permiso usando el nuevo modelo de permiso en mi aplicación?
- Cómo solicitar permisos de un servicio en Android Marshmallow
- Forzar la aplicación a reiniciar desde la primera Actividad (cuando se deniega un permiso)
- Android Fatal Error - No se puede realizar esta acción después de onSaveInstanceState
- Android M - estilo de diálogo de permiso personalizado
- ¿Cuál es el caso de uso de ContextCompat.checkSelfPermission?
- Excepción de seguridad al intentar acceder a una imagen de Picasa en un dispositivo que ejecuta 4.2
- Android: ¿qué elegir para los valores de la petición?
- Servicios de Android Play FusedLocatioAPI getLastLocation se bloquea con SecurityException
- Perder el permiso de Notificación de acceso después de reiniciar
- Permiso denegado (¿falta el permiso de INTERNET?): Pero se da permiso
- Excepción grave: java.lang.SecurityException: Falta permiso para insertar credenciales
- ¿Cuándo utilizar el permiso READ_GSERVICES?
- FIleObserver y ContentObserver no funcionan en Android Marshmallow
Abra un diálogo con el siguiente código:
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
Obtenga el resultado de la actividad como a continuación:
@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case 1: { // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // permission was granted, yay! Do the // contacts-related task you need to do. } else { // permission denied, boo! Disable the // functionality that depends on this permission. Toast.makeText(MainActivity.this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show(); } return; } // other 'case' lines to check for other // permissions this app might request } }
Más información: https://developer.android.com/training/permissions/requesting.html
Esta estructura que estoy utilizando para comprobar si mi aplicación tiene permiso y que solicitar si no tiene permiso. Así que en mi código principal de donde quiero comprobar escribir siguiente:
int MyVersion = Build.VERSION.SDK_INT; if (MyVersion > Build.VERSION_CODES.LOLLIPOP_MR1) { if (!checkIfAlreadyhavePermission()) { requestForSpecificPermission(); } }
El módulo checkIfAlreadyhavePermission () se implementa como:
private boolean checkIfAlreadyhavePermission() { int result = ContextCompat.checkSelfPermission(this, Manifest.permission.GET_ACCOUNTS); if (result == PackageManager.PERMISSION_GRANTED) { return true; } else { return false; } }
El módulo requestForSpecificPermission () se implementa como:
private void requestForSpecificPermission() { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.GET_ACCOUNTS, Manifest.permission.RECEIVE_SMS, Manifest.permission.READ_SMS, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 101); }
Y Anulación en Actividad:
@Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { switch (requestCode) { case 101: if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { //granted } else { //not granted } break; default: super.onRequestPermissionsResult(requestCode, permissions, grantResults); } }
Consulte este enlace para obtener más detalles: http://revisitingandroid.blogspot.in/2017/01/how-to-check-and-request-for-run-time.html
A partir de android marshmallow tenemos que solicitar al usuario permisos específicos, también podemos comprobar a través de código si el permiso ya se da. Echa un vistazo a la lista de permisos necesarios en la mayoría de los casos
Android.permission-group.CALENDAR android.permission.READ_CALENDAR android.permission.WRITE_CALENDAR
Android.permission-group.CAMERA android.permission.CAMERA
Android.permission-group.CONTACTS android.permission.READ_CONTACTS android.permission.WRITE_CONTACTS android.permission.GET_ACCOUNTS
Android.permission-group.LOCATION android.permission.ACCESS_FINE_LOCATION android.permission.ACCESS_COARSE_LOCATION
Android.permission-group.MICROPHONE android.permission.RECORD_AUDIO
Android.permission-group.PHONE android.permission.READ_PHONE_STATE android.permission.CALL_PHONE android.permission.READ_CALL_LOG android.permission.WRITE_CALL_LOG android.permission.ADD_VOICEMAIL android.permission.USE_SIP android.permission.PROCESS_OUTGOING_CALLS
Android.permission-group.SENSORS android.permission.BODY_SENSORS
Android.permission-group.SMS android.permission.SEND_SMS android.permission.RECEIVE_SMS android.permission.READ_SMS android.permission.RECEIVE_WAP_PUSH android.permission.RECEIVE_MMS android.permission.READ_CELL_BROADCASTS
Android.permission-group.STORAGE android.permission.READ_EXTERNAL_STORAGE android.permission.WRITE_EXTERNAL_STORAGE
Aquí es una muestra si necesitamos comprobar si hay algún permiso
if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_CALENDAR) != PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, Manifest.permission.WRITE_CALENDAR)) { AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context); alertBuilder.setCancelable(true); alertBuilder.setMessage("Write calendar permission is necessary to write event!!!"); alertBuilder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { @TargetApi(Build.VERSION_CODES.JELLY_BEAN) public void onClick(DialogInterface dialog, int which) { ActivityCompat.requestPermissions((Activity)context, new String[]{Manifest.permission.WRITE_CALENDAR}, MY_PERMISSIONS_REQUEST_WRITE_CALENDAR); } }); } else { ActivityCompat.requestPermissions((Activity)context, new String[]{Manifest.permission.WRITE_CALENDAR}, MY_PERMISSIONS_REQUEST_WRITE_CALENDAR); } }
Android-M es decir, la API 23 introdujo permisos de tiempo de ejecución para reducir las fallas de seguridad en el dispositivo android, donde los usuarios ahora pueden administrar directamente los permisos de la aplicación en runtime.so si el usuario niega un permiso particular de su aplicación que tiene que obtener pidiendo el diálogo de permiso Que mencionaste en tu consulta.
Por lo tanto, compruebe antes de la acción, por ejemplo, compruebe que tiene permiso para acceder al enlace de recursos y si su aplicación no tiene ese permiso en particular, puede solicitar el enlace de permisos y manejar la respuesta de solicitud de permisos como a continuación.
@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case MY_PERMISSIONS_REQUEST_READ_CONTACTS: { // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // permission was granted, yay! Do the // contacts-related task you need to do. } else { // permission denied, boo! Disable the // functionality that depends on this permission. } return; } // other 'case' lines to check for other // permissions this app might request } }
Así que finalmente, es una buena práctica para pasar por cambios de comportamiento si usted está planeando trabajar con nuevas versiones para evitar la fuerza se cierra 🙂
Permisos Mejores Prácticas.
Puede descargar la aplicación de muestra oficial aquí .
He utilizado este envoltorio (recomendado) escrito por los desarrolladores de google. Su súper fácil de usar.
https://github.com/googlesamples/easypermissions
Función que trata de la comprobación y pedir permiso si es necesario
public void locationAndContactsTask() { String[] perms = { Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_CONTACTS }; if (EasyPermissions.hasPermissions(this, perms)) { // Have permissions, do the thing! Toast.makeText(this, "TODO: Location and Contacts things", Toast.LENGTH_LONG).show(); } else { // Ask for both permissions EasyPermissions.requestPermissions(this, getString(R.string.rationale_location_contacts), RC_LOCATION_CONTACTS_PERM, perms); } }
Feliz codificación
Desde Android Marshmallow (API 23) y por defecto, por defecto, todos los permisos peligrosos (según documento oficial doc ) están deshabilitados. Después de la instalación cuando la aplicación está abierta por primera vez, debe conceder permiso en Run Time.
He logrado esto de la siguiente manera:
public class MarshMallowPermission { public static final int EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_GALLERY = 0; public static final int EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_CAMERA = 1; public static final int EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_LOAD_PROFILE = 2; public static final int CAMERA_PERMISSION_REQUEST_CODE = 3; public static final int LOCATION_PERMISSION_REQUEST_CODE = 4; Activity activity; Context mContext; public MarshMallowPermission(Activity activity) { this.activity = activity; this.mContext = activity; } public boolean checkPermissionForExternalStorage(){ int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE); if (result == PackageManager.PERMISSION_GRANTED){ return true; } else { return false; } } public boolean checkPermissionForCamera(){ int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA); if (result == PackageManager.PERMISSION_GRANTED){ return true; } else { return false; } } public boolean checkLocationPermission(){ int result = ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION); if (result == PackageManager.PERMISSION_GRANTED){ return true; } else { return false; } } public void requestPermissionForExternalStorage(int requestCode){ if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)){ Toast.makeText(mContext.getApplicationContext(), "External Storage permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show(); } else { ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},requestCode); } } public void requestPermissionForCamera(){ if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.CAMERA)){ Toast.makeText(mContext.getApplicationContext(), "Camera permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show(); } else { ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.CAMERA},CAMERA_PERMISSION_REQUEST_CODE); } } public void requestPermissionForLocation(){ if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.ACCESS_FINE_LOCATION) && ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.ACCESS_COARSE_LOCATION)){ Toast.makeText(mContext.getApplicationContext(), "Location permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show(); } else { ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION}, LOCATION_PERMISSION_REQUEST_CODE); } } }
IN Su clase de actividad:
public class MainActivity extends AppCompatActivity{ private MarshMallowPermission marshMallowPermission; @Override protected void onCreate(Bundle savedInstanceState) { Log.d("NavHome", "Oncreate_nav"); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); marshMallowPermission = new MarshMallowPermission(MainActivity.this); if (!marshMallowPermission.checkPermissionForExternalStorage()) { marshMallowPermission.requestPermissionForExternalStorage(MarshMallowPermission.EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_LOAD_PROFILE); } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case MarshMallowPermission.EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_LOAD_PROFILE: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { //permission granted successfully } else { //permission denied } break; } } }
Estoy usando esto como una clase base de Fragmento. Sólo pido permisos de un fragmento, pero se puede refactorizar y hacer una versión de actividad similar.
public class BaseFragment extends Fragment { private static final int PERMISSION_REQUEST_BLOCK_INTERNAL = 555; private static final String PERMISSION_SHARED_PREFERENCES = "permissions"; @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == PERMISSION_REQUEST_BLOCK_INTERNAL) { boolean allPermissionsGranted = true; for (int iGranting : grantResults) { if (iGranting != PermissionChecker.PERMISSION_GRANTED) { allPermissionsGranted = false; break; } } if (allPermissionsGranted && permissionBlock != null) { permissionBlock.run(); } permissionBlock = null; } } public void runNowOrAskForPermissionsFirst(String permission, Runnable block) { if (hasPermission(permission)) { block.run(); } else if (!hasPermissionOrWillAsk(permission)) { permissionBlock = block; askForPermission(permission, PERMISSION_REQUEST_BLOCK_INTERNAL); } } public boolean hasPermissionOrWillAsk(String permission) { boolean hasPermission = hasPermission(permission); boolean hasAsked = hasPreviouslyAskedForPermission(permission); boolean shouldExplain = shouldShowRequestPermissionRationale(permission); return hasPermission || (hasAsked && !shouldExplain); } private boolean hasPermission(String permission) { return (ContextCompat.checkSelfPermission(getContext(), permission) == PackageManager.PERMISSION_GRANTED); } private boolean hasPreviouslyAskedForPermission(String permission) { SharedPreferences prefs = getContext().getSharedPreferences(PERMISSION_SHARED_PREFERENCES, Context.MODE_PRIVATE); return prefs.getBoolean(permission, false); } private void askForPermission(String permission, int requestCode) { SharedPreferences.Editor editor = getContext().getSharedPreferences(PERMISSION_SHARED_PREFERENCES, Context.MODE_PRIVATE).edit(); editor.putBoolean(permission, true); editor.apply(); requestPermissions(new String[] { permission }, requestCode); } }
Hay dos métodos clave que debe usar:
-
HasPermissionOrWillAsk – Use esto para ver si un permiso ha sido solicitado y lo niega por un usuario que no quiere que se le pregunte de nuevo. Esto es útil para deshabilitar la interfaz de usuario cuando el usuario ha dado su respuesta final sobre NO querer una característica.
-
RunNowOrAskForPermissionsFirst – Usa esto para ejecutar algún código que requiera permisos. Si el usuario ya ha concedido permiso, el código se ejecutará inmediatamente. De lo contrario, el código se ejecutará más tarde si el usuario concede permiso. O no en absoluto. Es bueno porque especificas el código en un solo lugar.
He aquí un ejemplo:
mFragment.runNowOrAskForPermissionsFirst(Manifest.permission.ACCESS_FINE_LOCATION, new Runnable() { @Override public void run() { ...do something if we have permission... } });
Feliz de recibir comentarios sobre esto. No es que este ejemplo específico sea un poco simplificado, ya que también debe comprobar si los Servicios de ubicación están habilitados en el dispositivo. (Es diferente de los permisos.) Además, sólo admite un permiso a la vez, pero sería sencillo modificarlo si lo necesita para admitir más de uno a la vez.
Puede ser una manera más limpia. Agrega todos tus permisos en un array como
private static final String[] INITIAL_PERMS={ android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION }; private static final int INITIAL_REQUEST=1337;
Cualquiera que sea su permision es crear un método para cada permision
@RequiresApi(api = Build.VERSION_CODES.M) private boolean canAccessFineLocation() { return(hasPermission(Manifest.permission.ACCESS_FINE_LOCATION)); } @RequiresApi(api = Build.VERSION_CODES.M) private boolean canAccessCoarseLocation() { return(hasPermission(Manifest.permission.ACCESS_COARSE_LOCATION)); } @RequiresApi(api = Build.VERSION_CODES.M) private boolean hasPermission(String perm) { return(PackageManager.PERMISSION_GRANTED == checkSelfPermission(perm)); }
Llame a este método en onCreate
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){ if(!canAccessCoarseLocation() || !canAccessFineLocation()){ requestPermissions(INITIAL_PERMS, INITIAL_REQUEST); } }
Ahora reemplace onRequestPermissionsResult
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if(requestCode == INITIAL_REQUEST){ if (canAccessFineLocation() && canAccessCoarseLocation()) { //call your method } else { //show Toast or alert that this permissions is neccessary } } }
Para obtener permiso múltiple a la vez, puede utilizarlo. Este trabajo para mí .. Tengo otra solución. Si usted da su targetSdkVersion abajo 22 que trabaja para mí. Y su comportamiento es como obtener permiso de manifest.xml. Probado y funciona para mí.
final private int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124; private void insertDummyContactWrapper() { List<String> permissionsNeeded = new ArrayList<String>(); final List<String> permissionsList = new ArrayList<String>(); if (!addPermission(permissionsList, Manifest.permission.ACCESS_FINE_LOCATION)) permissionsNeeded.add("GPS"); if (!addPermission(permissionsList, Manifest.permission.READ_CONTACTS)) permissionsNeeded.add("Read Contacts"); if (!addPermission(permissionsList, Manifest.permission.WRITE_CONTACTS)) permissionsNeeded.add("Write Contacts"); if (permissionsList.size() > 0) { if (permissionsNeeded.size() > 0) { // Need Rationale String message = "You need to grant access to " + permissionsNeeded.get(0); for (int i = 1; i < permissionsNeeded.size(); i++) message = message + ", " + permissionsNeeded.get(i); showMessageOKCancel(message, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { requestPermissions(permissionsList.toArray(new String[permissionsList.size()]), REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS); } }); return; } requestPermissions(permissionsList.toArray(new String[permissionsList.size()]), REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS); return; } insertDummyContact(); } private boolean addPermission(List<String> permissionsList, String permission) { if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { permissionsList.add(permission); // Check for Rationale Option if (!shouldShowRequestPermissionRationale(permission)) return false; } return true; } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { switch (requestCode) { case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS: { Map<String, Integer> perms = new HashMap<String, Integer>(); // Initial perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED); perms.put(Manifest.permission.READ_CONTACTS, PackageManager.PERMISSION_GRANTED); perms.put(Manifest.permission.WRITE_CONTACTS, PackageManager.PERMISSION_GRANTED); // Fill with results for (int i = 0; i < permissions.length; i++) perms.put(permissions[i], grantResults[i]); // Check for ACCESS_FINE_LOCATION if (perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && perms.get(Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED && perms.get(Manifest.permission.WRITE_CONTACTS) == PackageManager.PERMISSION_GRANTED) { // All Permissions Granted insertDummyContact(); } else { // Permission Denied Toast.makeText(MainActivity.this, "Some Permission is Denied", Toast.LENGTH_SHORT) .show(); } } break; default: super.onRequestPermissionsResult(requestCode, permissions, grantResults); } }
Para más detalles. Revise el enlace abajo
Hay una buena biblioteca que se puede utilizar en caso de que los permisos se deben preguntar cuando el permiso es necesario por un servicio de fondo. Aunque una limitación de la biblioteca es que no se puede utilizar para determinar si los permisos se dan actualmente a la aplicación o no. Siempre pregunta al usuario si la aplicación ya no los tiene.
Déle una oportunidad, ya que hace la vida más simple: Permisos de Android
Para manejar el permiso de tiempo de ejecución, google ha proporcionado un proyecto de biblioteca. Puedes consultar esto desde aquí https://github.com/googlesamples/easypermissions
EasyPermissions se instala agregando la siguiente dependencia al archivo build.gradle:
dependencies { compile 'pub.devrel:easypermissions:0.3.0' }
Para comenzar a usar EasyPermissions, haga que su Actividad (o Fragmento) anule el método onRequestPermissionsResult:
public class MainActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); // Forward results to EasyPermissions EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this); } @Override public void onPermissionsGranted(int requestCode, List<String> list) { // Some permissions have been granted // ... } @Override public void onPermissionsDenied(int requestCode, List<String> list) { // Some permissions have been denied // ... } }
Aquí obtendrá un ejemplo práctico de cómo funciona esta biblioteca https://github.com/milon87/EasyPermission
if (CommonMethod.isNetworkAvailable(MainActivity.this)) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { int permissionCheck = ContextCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.CAMERA); if (permissionCheck == PackageManager.PERMISSION_GRANTED) { //showing dialog to select image callFacebook(); Log.e("permission", "granted MarshMallow"); } else { ActivityCompat.requestPermissions(MainActivity.this, new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE, android.Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.CAMERA}, 1); } } else { Log.e("permission", "Not Required Less than MarshMallow Version"); callFacebook(); } } else { CommonMethod.showAlert("Internet Connectivity Failure", MainActivity.this); }
- Android FragmentTransaction Animación personalizada (Nombre del animador desconocido: Traducir)
- El número de referencias de método en un archivo .dex no puede exceder 64k API 17