Android 6.0 múltiples permisos
Sé que Android 6.0 tiene nuevos permisos y sé que puedo llamarlos con algo como esto
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[] {
Manifest.permission.WRITE_EXTERNAL_STORAGE
}, PERMISSION_WRITE_STORAGE);
}
Hoy vi una aplicación de Google que necesita 3 permisos: contactos, sms y cámara. Está haciendo una página 1-3 y los llama a todos juntos al mismo tiempo para activarlos.
¿Alguien puede decirme cómo puedo activar 4 permisos al mismo tiempo como SMS, cámara, contactos y almacenamiento?
Ejemplo (olvidé el nombre de la aplicación de Google :()
La aplicación necesita sms, contactos y cámara
la aplicación me pidió (e hizo un cuadro de diálogo en las páginas 1-3) activar sms, activar contactos y luego la cámara. Entonces, esta aplicación de Google estaba reuniendo los 3 permisos requeridos y mi pregunta es ¿cómo puedo lograr lo mismo?
Simplemente incluya los 4 permisos en la ActivityCompat.requestPermissions(...)
llamada y Android los agrupará automáticamente como mencionó.
Tengo un método auxiliar para verificar varios permisos y ver si alguno de ellos no está concedido.
public static boolean hasPermissions(Context context, String... permissions) {
if (context != null && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
O en Kotlin:
fun hasPermissions(context: Context, vararg permissions: String): Boolean = permissions.all {
ActivityCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
}
Luego simplemente envíele todos los permisos. Android pedirá sólo los que necesita.
// The request code used in ActivityCompat.requestPermissions()
// and returned in the Activity's onRequestPermissionsResult()
int PERMISSION_ALL = 1;
String[] PERMISSIONS = {
android.Manifest.permission.READ_CONTACTS,
android.Manifest.permission.WRITE_CONTACTS,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
android.Manifest.permission.READ_SMS,
android.Manifest.permission.CAMERA
};
if (!hasPermissions(this, PERMISSIONS)) {
ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
}
Aquí hay un ejemplo detallado con múltiples solicitudes de permiso: -
La aplicación necesita 2 permisos al inicio. SEND_SMS y ACCESS_FINE_LOCATION (ambos se mencionan en manifest.xml).
Estoy usando Support Library v4 , que está preparada para manejar Android anterior a Marshmallow, por lo que no es necesario verificar las versiones de compilación.
Tan pronto como se inicia la aplicación, solicita varios permisos juntos. Si se conceden ambos permisos, continúa el flujo normal.
public static final int REQUEST_ID_MULTIPLE_PERMISSIONS = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(checkAndRequestPermissions()) {
// carry on the normal flow, as the case of permissions granted.
}
}
private boolean checkAndRequestPermissions() {
int permissionSendMessage = ContextCompat.checkSelfPermission(this,
Manifest.permission.SEND_SMS);
int locationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
List<String> listPermissionsNeeded = new ArrayList<>();
if (locationPermission != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
if (permissionSendMessage != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.SEND_SMS);
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),REQUEST_ID_MULTIPLE_PERMISSIONS);
return false;
}
return true;
}
ContextCompat.checkSelfPermission(), ActivityCompat.requestPermissions(), ActivityCompat.shouldShowRequestPermissionRationale() son parte de la biblioteca de soporte.
En caso de que no se concedan uno o más permisos, ActivityCompat.requestPermissions() solicitará permisos y el control pasará al método de devolución de llamada onRequestPermissionsResult().
Debe verificar el valor del indicador shouldShowRequestPermissionRationale() en el método de devolución de llamada onRequestPermissionsResult().
Sólo hay dos casos:--
Caso 1: -Cada vez que el usuario haga clic en Denegar permisos (incluida la primera vez), devolverá verdadero. Entonces, cuando el usuario lo niegue, podemos mostrar más explicaciones y seguir preguntando nuevamente.
Caso 2: -Solo si el usuario selecciona "nunca vuelve a preguntar", devolverá falso. En este caso, podemos continuar con la funcionalidad limitada y guiar al usuario para que active los permisos desde la configuración para obtener más funcionalidades, o podemos finalizar la configuración, si los permisos son triviales para la aplicación.
CASO 1
CASO-2
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
Log.d(TAG, "Permission callback called-------");
switch (requestCode) {
case REQUEST_ID_MULTIPLE_PERMISSIONS: {
Map<String, Integer> perms = new HashMap<>();
// Initialize the map with both permissions
perms.put(Manifest.permission.SEND_SMS, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
// Fill with actual results from user
if (grantResults.length > 0) {
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
// Check for both permissions
if (perms.get(Manifest.permission.SEND_SMS) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "sms & location services permission granted");
// process the normal flow
//else any one or both the permissions are not granted
} else {
Log.d(TAG, "Some permissions are not granted ask again ");
//permission is denied (this is the first time, when "never ask again" is not checked) so ask again explaining the usage of permission
// // shouldShowRequestPermissionRationale will return true
//show the dialog or snackbar saying its necessary and try again otherwise proceed with setup.
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.SEND_SMS) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
showDialogOK("SMS and Location Services Permission required for this app",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
checkAndRequestPermissions();
break;
case DialogInterface.BUTTON_NEGATIVE:
// proceed with logic by disabling the related features or quit the app.
break;
}
}
});
}
//permission is denied (and never ask again is checked)
//shouldShowRequestPermissionRationale will return false
else {
Toast.makeText(this, "Go to settings and enable permissions", Toast.LENGTH_LONG)
.show();
// //proceed with logic by disabling the related features or quit the app.
}
}
}
}
}
}
private void showDialogOK(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(this)
.setMessage(message)
.setPositiveButton("OK", okListener)
.setNegativeButton("Cancel", okListener)
.create()
.show();
}
Código pequeño:
public static final int MULTIPLE_PERMISSIONS = 10; // code you want.
String[] permissions= new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION};
if (checkPermissions())
// permissions granted.
}
private boolean checkPermissions() {
int result;
List<String> listPermissionsNeeded = new ArrayList<>();
for (String p:permissions) {
result = ContextCompat.checkSelfPermission(getActivity(),p);
if (result != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(p);
}
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),MULTIPLE_PERMISSIONS );
return false;
}
return true;
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissionsList[], int[] grantResults) {
switch (requestCode) {
case MULTIPLE_PERMISSIONS:{
if (grantResults.length > 0) {
String permissionsDenied = "";
for (String per : permissionsList) {
if(grantResults[0] == PackageManager.PERMISSION_DENIED){
permissionsDenied += "\n" + per;
}
}
// Show permissionsDenied
updateViews();
}
return;
}
}
}
Lista de permisos de Android, permisos normales y permisos peligrosos en API 23
en un fragmento
public class Homefragment extends Fragment {
View hfrag;
Context context;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//first we must check the permissions are already granted
hfrag = inflater.inflate(R.layout.home, container, false);
context = getActivity();
checkAndRequestPermissions();
}
}
private boolean checkAndRequestPermissions() {
int permissionSendMessage = ContextCompat.checkSelfPermission(context,
Manifest.permission.READ_SMS);
int contactpermission = ContextCompat.checkSelfPermission(context, Manifest.permission.GET_ACCOUNTS);
int writepermission = ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE);
int callpermission = ContextCompat.checkSelfPermission(context, Manifest.permission.CALL_PHONE);
int receivepermission = ContextCompat.checkSelfPermission(context, Manifest.permission.RECEIVE_SMS);
int locationpermission = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION);
List<String> listPermissionsNeeded = new ArrayList<>();
if (locationpermission != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
if (contactpermission != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.GET_ACCOUNTS);
}
if (writepermission != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (permissionSendMessage != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.READ_SMS);
}
if (receivepermission != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.RECEIVE_SMS);
}
if (callpermission != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.CALL_PHONE);
}
if (!listPermissionsNeeded.isEmpty()) {
requestPermissions(listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), REQUEST_ID_MULTIPLE_PERMISSIONS);
return false;
}
return true;
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_ID_MULTIPLE_PERMISSIONS) {
if (grantResults.length > 0) {
for (int i = 0; i < permissions.length; i++) {
if (permissions[i].equals(Manifest.permission.GET_ACCOUNTS)) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.e("msg", "accounts granted");
}
} else if (permissions[i].equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.e("msg", "storage granted");
}
} else if (permissions[i].equals(Manifest.permission.CALL_PHONE)) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.e("msg", "call granted");
}
} else if (permissions[i].equals(Manifest.permission.RECEIVE_SMS)) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.e("msg", "sms granted");
}
} else if (permissions[i].equals(Manifest.permission.ACCESS_FINE_LOCATION)) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.e("msg", "location granted");
}
}
}
}
}
}
}
Es fácil, hazlo de esta manera.
private static final int REQUEST_READ_PHONE_STATE = 110 , REQUEST_ACCESS_FINE_LOCATION = 111, REQUEST_WRITE_STORAGE = 112;
En tu onCreate
//request permission
boolean hasPermissionPhoneState = (ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED);
if (!hasPermissionPhoneState) {
ActivityCompat.requestPermissions(LoginActivity.this,
new String[]{Manifest.permission.READ_PHONE_STATE},
REQUEST_READ_PHONE_STATE);
}
boolean hasPermissionLocation = (ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED);
if (!hasPermissionLocation) {
ActivityCompat.requestPermissions(LoginActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_ACCESS_FINE_LOCATION);
}
boolean hasPermissionWrite = (ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
if (!hasPermissionWrite) {
ActivityCompat.requestPermissions(LoginActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_WRITE_STORAGE);
}
Luego verifique el resultado
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode)
{
case REQUEST_READ_PHONE_STATE: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
Toast.makeText(LoginActivity.this, "Permission granted.", Toast.LENGTH_SHORT).show();
//reload my activity with permission granted or use the features what required the permission
finish();
startActivity(getIntent());
} else
{
Toast.makeText(LoginActivity.this, "The app was not allowed to get your phone state. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
}
}
case REQUEST_ACCESS_FINE_LOCATION: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
Toast.makeText(LoginActivity.this, "Permission granted.", Toast.LENGTH_SHORT).show();
//reload my activity with permission granted or use the features what required the permission
finish();
startActivity(getIntent());
} else
{
Toast.makeText(LoginActivity.this, "The app was not allowed to get your location. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
}
}
case REQUEST_WRITE_STORAGE: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
Toast.makeText(LoginActivity.this, "Permission granted.", Toast.LENGTH_SHORT).show();
//reload my activity with permission granted or use the features what required the permission
finish();
startActivity(getIntent());
} else
{
Toast.makeText(LoginActivity.this, "The app was not allowed to write to your storage. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
}
}
}
}