Esperar permiso del usuario
Estoy construyendo una aplicación que el muestreo GPS en el arranque. Como probablemente ya sepa, los permisos se solicitan durante el tiempo de ejecución desde Android M y superiores.
Por lo tanto, en mi caso estoy empezando con comprobar si se necesitan permisos, como esto:
- Excepción grave: java.lang.SecurityException: Falta permiso para insertar credenciales
- Permiso de lectura y escritura para almacenamiento y uso de galería para malvavisco
- ¿Debo declarar el permiso "com.android.alarm.permission.SET_ALARM" cuando se utiliza el Administrador de alarmas en Android?
- Solicitar permisos de ubicación de un servicio Android M
- Permiso personalizado con intención implícita
private void permissionForAndroidM() { if (Build.VERSION.SDK_INT > 22) { String[] allPermissionNeeded = { Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO}; List<String> permissionNeeded = new ArrayList<>(); for (String permission : allPermissionNeeded) if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) permissionNeeded.add(permission); if (permissionNeeded.size() > 0) { requestPermissions(permissionNeeded.toArray(new String[0]), 0); } } }
Pero Android sigue ejecutando el código y pidiendo datos GPS (= bloqueo, porque el usuario no aceptó la solicitud de permiso).
Encuentro muchas soluciones sobre esperar la entrada del usuario (como el uso de DialogInterface.OnClickListener
, enlace , pero no se puede implementar en este caso, porque no estoy creando el diálogo).
En pocas palabras, la pregunta: ¿Cómo puedo esperar a la respuesta del usuario desde el diálogo de permisos de Android?
- ¿Dónde están almacenados los permisos en Android?
- Comprobación del código que utiliza permisos
- Java.lang.RuntimeException: inicio fallido
- El permiso de Android 6.0 (Marshmallow) READ_CONTACTS permite leer el nombre del contacto cuando se deniega el permiso
- Solicitud de permiso duplicada después del cambio de orientación
- ¿Hay una manera de obtener el uso de la CPU de la aplicación con Android 7 (turrón)
- Permiso de Android.INTERACT_ACROSS_USERS denegación
- El cambio de permiso dinámico de marshmallow de Android mata todos los procesos de aplicación
Puede manejar el método de sobrescritura de la respuesta del usuario.
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
De su actividad.
Android sigue ejecutando el código y solicitando datos GPS (= bloqueo, porque el usuario no aceptó la solicitud de permiso).
Como muchas cosas en Android, requestPermissions()
es asíncrono. El usuario ni siquiera se le ha pedido los permisos en el momento en que devuelve este método.
¿Cómo puedo esperar la respuesta del usuario desde el diálogo de permisos de Android?
No lo haces.
Si usted encuentra que ya tiene el permiso, usted hace su trabajo. Si encuentras que tienes que pedir permiso, te demoras en hacer ese trabajo hasta obtener el permiso, en onRequestPermissionsResult()
.
Lo trabajé de la manera siguiente:
1- Creó un ayudante Boolean
para verificar los permisos otorgados:
public class UtilPermissions { public static boolean hasPermissions(Context context, String... allPermissionNeeded) { if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && allPermissionNeeded != null) for (String permission : allPermissionNeeded) if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) return false; return true; } }
2- Creó una pantalla Splash
como:
public class Splash extends Activity { private static final int PERMISSION_ALL = 0; private Handler h; private Runnable r; /* SharedPreferences mPrefs; final String settingScreenShownPref = "settingScreenShown"; final String versionCheckedPref = "versionChecked"; */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); h = new Handler(); r = new Runnable() { @Override public void run() { Toast.makeText(Splash.this, "Runnable started", Toast.LENGTH_SHORT).show(); /* // (OPTIONAL) these lines to check if the `First run` ativity is required int versionCode = BuildConfig.VERSION_CODE; String versionName = BuildConfig.VERSION_NAME; mPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); SharedPreferences.Editor editor = mPrefs.edit(); Boolean settingScreenShown = mPrefs.getBoolean(settingScreenShownPref, false); int savedVersionCode = mPrefs.getInt(versionCheckedPref, 1); if (!settingScreenShown || savedVersionCode != versionCode) { startActivity(new Intent(Splash.this, FirstRun.class)); editor.putBoolean(settingScreenShownPref, true); editor.putInt(versionCheckedPref, versionCode); editor.commit(); } else */ startActivity(new Intent(Splash.this, MainActivity.class)); finish(); } }; String[] PERMISSIONS = { READ_PHONE_STATE, MODIFY_AUDIO_SETTINGS, ACCESS_FINE_LOCATION, READ_SMS }; if(!UtilPermissions.hasPermissions(this, PERMISSIONS)){ ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL); } else h.postDelayed(r, 1500); } // Put the below OnRequestPermissionsResult code here }
3- Creó OnRequestPermissionsResult
como se muestra a continuación:
@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { int index = 0; Map<String, Integer> PermissionsMap = new HashMap<String, Integer>(); for (String permission : permissions){ PermissionsMap.put(permission, grantResults[index]); index++; } if((PermissionsMap.get(ACCESS_FINE_LOCATION) != 0) || PermissionsMap.get(READ_SMS) != 0){ Toast.makeText(this, "Location and SMS permissions are a must", Toast.LENGTH_SHORT).show(); finish(); } else { h.postDelayed(r, 1500); } }
4- Definir la pantalla Splash
como Launcher
en AndroidManifest.xml
como:
<activity android:name=".MainActivity" android:label="@string/app_name" android:theme="@style/AppTheme.NoActionBar"> </activity> <activity android:name=".Splash" android:configChanges="orientation|keyboardHidden|screenSize" android:theme="@style/SplashTheme"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
5- En styles.xml
definió el SplashTheme
como:
<style name="SplashTheme" parent="Theme.AppCompat.NoActionBar"> <item name="android:windowBackground">@drawable/Splash</item> </style>
6- El @drawable/Splash.xmls
es:
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@color/lightgray"/> <item> <bitmap android:gravity="center" android:src="@mipmap/ic_launcher"/> </item> </layer-list>
7- En los values/colors.xmls
el color claro se ha definido como a continuación:
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="lightgray">#D3D3D3</color> </resources>
- Ocultar y mostrar lineal
- ¿Cómo obtener el nivel de la batería después de conectarse al dispositivo BLE?