Llamar el show de DialogFragment () desde dentro onRequestPermissionsResult () provoca IllegalStateException en Marshmallow
Pasos:
- Solicitar un permiso de
Fragment
oActivity
- Mostrar un DialogFragment desde dentro
onRequestPermissionsResult()
-
java.lang.IllegalStateException
se lanza: No se puede realizar esta acción después deonSaveInstanceState
Esto no sucede cuando muestro el diálogo después de algún retraso (usando postDelayed). De acuerdo con http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html ) en los dispositivos post-Honeycomb PODEMOS commit()
entre onPause()
y onStop()
sin ninguna onStop()
O EXCEPCIÓN. Aquí hay un enlace a la fuente del proyecto de ejemplo, el archivo de registro y el problema grabado. Https://drive.google.com/folderview?id=0BwvvuYbQTUl6STVSZF9TX2VUeHM&usp=sharing
- Permisos de Android GET_ACCOUNTS y USE_CREDENTIALS se muestran automáticamente
- Apoyar Android de nivel de Api nivel 23 a 22 en la consola de desarrolladores
- ¿Cómo UID de una aplicación determinada durante la instalación en Android?
- Mi aplicación para Android, de repente, requiere permisos no establecidos en AndroidManifest.xml. ¿Por qué?
- Ventana de superposición del sistema Android
También he abierto un problema https://code.google.com/p/android/issues/detail?id=190966 pero se ha marcado como WorkingAsIntended y sugieren que sólo capturar excepción. Pero esto no soluciona el problema. Conozco otras maneras de solucionarlo, pero ¿no es este error Android?
ACTUALIZACIÓN El estado del error se vuelve a asignar. Espero que se arreglen pronto. Mi solución temporal es
new Handler().postDelayed(new Runnable() { @Override public void run() { // do your fragment transaction here } }, 200);
- El instalador de paquetes se bloquea en Android M después de solicitar permiso READ_SMS
- Android Marshmallow, nivel de protección "peligroso" y componentes / aplicaciones del sistema
- ¿Cómo elimino mi propio calendario personalizado corrompido mediante programación?
- ACCESS_FINE_LOCATION permiso
- FIleObserver y ContentObserver no funcionan en Android Marshmallow
- Java.lang.RuntimeException: inicio fallido
- Cómo conceder permisos sólo al creador de un URI
- ¿Necesita V2 Maps Library el permiso ACCESS_NETWORK_STATE?
El error se acepta y se solucionará, sin embargo, estoy en desacuerdo con las soluciones postDelayed y temporizador. La mejor manera de hacer esto sería introducir un indicador de estado en la Actividad, en el que se establece en la devolución de llamada, y utilizar en onResume o similar. Por ejemplo:
private boolean someFlag; public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { // some code checking status someFlag = true; }
Y luego en onResume:
protected void onResume() { if(someFlag == true) { doSomething(); someFlag = false; } }
Probar algo como esto:
// ... private Runnable mRunnable; @Override public void onResume() { super.onResume(); if (mRunnable != null) { mRunnable.run(); mRunnable = null; } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (/* PERMISSION_DENIED */) { mRunnable = /* new Runnable which show dialogFragment*/; } }
Se trata de un error en Android https://code.google.com/p/android/issues/detail?id=190966&q=label%3AReportedBy-Developer&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars
Por lo tanto, por ahora, las soluciones son necesarias. Puede utilizar la solución de @ldulcic. O puede usar el método postDelay de Handler. Se prefiere la segunda opción.
Puesto que usted está utilizando un DialogFragment
, usted debe guardar un indicador o un estado y que demuestre su diálogo en onPostResume
. Debe hacer esto en onPostResume
en lugar de onResume
u otros métodos de ciclo de vida.
Como se indica claramente en la documentación , si se cometen transacciones en métodos de ciclo de vida de actividad distintos de onPostResume
o onResumeFragments
(para FragmentActivity), en algunos casos el método se puede llamar antes de que el estado de la actividad se haya restaurado completamente.
Por lo tanto, si muestra su diálogo onPostResume usted estará bien.
También creo que esto es un error de Android. No puedo creer que hayan marcado el problema WorkingAsIntended . La única solución para ahora es retrasar la ejecución del código en onRequestPermissionsResult()
hasta que la gente de android corrija esto correctamente.
Esta es mi forma de resolver este problema si alguien se pregunta cómo retrasar la ejecución:
@Override public void onRequestPermissionsResult (int requestCode, String [] permisos, int [] grantResults) { If (requestCode == PERMISSION_CODE) { If (/ * PERMISIÓN PERMITIDA / DENEGADA * /) { Nuevo Timer (). Schedule (new TimerTask () { @Override public void run () { // EJECUTAR ACCIONES (LIKE FRAGMENT TRANSACTION ETC.) } }, 0); } }
Esto esencialmente retrasa la ejecución hasta que onRequestPermissionsResult()
termine para que no obtengamos java.lang.IllegalStateException
. Esto funciona en mi aplicación.
He superado esto en lo que creo que es una forma mucho más determinista. En lugar de usar temporizadores, básicamente coloqué el resultado hasta Activity.onResumeFragments () (o podrías hacerlo en Activity.onResume () si no usas fragmentos). Hice onResumeFragments () porque también encaminar el resultado fuera al fragmento específico que pidió el permiso así que necesito estar seguro que los fragmentos están listos.
Aquí está onRequestPermissionsResult ():
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { // This is super ugly, but google has a bug that they are calling this method BEFORE // onResume... which screws up fragment lifecycle big time. So work around it. But also // be robust enough to still work if/when they fix the bug. if (mFragmentsResumed) { routePermissionsResult(requestCode, permissions, grantResults); } else { mQueuedPermissionGrantResults = grantResults; mQueuedPermissionRequestCode = requestCode; mQueuedPermissions = permissions; } }
Entonces aquí está onResumeFragments ():
@Override protected void onResumeFragments() { super.onResumeFragments(); mFragmentsResumed = true; if (mQueuedPermissionGrantResults != null) { routePermissionsResult(mQueuedPermissionRequestCode, mQueuedPermissions, mQueuedPermissionGrantResults); }
Y para completar, aquí está onPause (), que borra el mFragmentsResumed flag:
@Override protected void onPause() { super.onPause(); mFragmentsResumed = false; }
Utilicé el indicador mFragmentsResumed porque no quiero que este código deje de funcionar si y cuando google corrige el error (cambiar el orden de las invocaciones del ciclo de vida haría que el código no funcionara si simplemente estaba estableciendo las variables en cola en onRequestPermissionsResult pero onResumeFragments was Llamado antes de esto).
- Ciclo de vida de la actividad – onCreate invitó a cada reorientación
- Cómo deshabilitar el modo de paisaje en React Native Android modo dev?