Android M Permissions: onRequestPermissionsResult () no se está llamando
Estoy actualizando nuestra aplicación para usar el nuevo sistema de permisos M. Todo funciona además de onRequestPermissionsResult (). Necesito verificar un permiso al presionar un botón y, si tiene éxito, enviar un mensaje de texto. Cuando doy permiso para hacerlo, el diálogo se cierra, pero no activa el Texto de envío hasta que presione el botón nuevamente.
He depurado y establecido puntos de interrupción en el método onRequestPermissionsResult() pero nunca entra en él.
Se llama a este método primero:
private void askForPermission() {
String[] permissions = new String[]{Manifest.permission.SEND_SMS};
ActivityCompat.requestPermissions(getActivity(), permissions, PERMISSIONS_CODE);
}
Y luego mi devolución de llamada se ve así:
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSIONS_CODE) {
for (int i = 0; i < permissions.length; i++) {
String permission = permissions[i];
int grantResult = grantResults[i];
if (permission.equals(Manifest.permission.SEND_SMS)) {
if (grantResult == PackageManager.PERMISSION_GRANTED) {
onPPSButtonPress();
} else {
requestPermissions(new String[]{Manifest.permission.SEND_SMS}, PERMISSIONS_CODE);
}
}
}
}
}
¿Alguien se ha encontrado con un problema similar? Agradezco cualquier ayuda con esto. Gracias
22 answers
Me encontré con el mismo problema y acabo de encontrar la solución. Al usar la biblioteca de soporte, debe usar las llamadas al método correcto. Por ejemplo:
- Cuando esté en AppCompatActivity, debe usar ActivityCompat.requestPermissions;
- Cuando esté en android.apoyo.v4.app.Fragment , debe usar simplemente requestPermissions (este es un método de instancia de android.apoyo.v4.app.Fragmento)
Si llama ActivityCompat.requestPermissions en un fragmento, la devolución de llamada onRequestPermissionsResult se llama a la actividad y no al fragmento.
Espero que esto ayude!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-12 12:04:42
Puedes probar esto:
requestPermissions(permissions, PERMISSIONS_CODE);
Si está llamando a este código desde un fragmento, tiene su propio método requestPermissions. Creo que el problema es que usted está llamando método estático.
Consejo profesional si quieres el onRequestPermissionsResult()
en un fragmento:
FragmentCompat.requestPermissions(Fragment fragment, String[] permissions, int requestCode)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-09 10:53:31
Espero que funcione bien
Para la Actividad:
ActivityCompat.requestPermissions(this,permissionsList,REQUEST_CODE);
Para Fragmento:
requestPermissions(permissionsList,REQUEST_CODE);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-23 18:07:15
Me encontré con este problema también. Si desea que la actividad que maneja permisos no esté en el historial / recientes, entonces tendrá la tentación de cambiar su entrada AndroidManifest.xml
.
Si configura la actividad a la que llama requestPermissions
o AppCompatActivity.requestPermissions
con
android:noHistory="true"
android:excludeFromRecents="true"
En su AndroidManifest.xml
entonces onRequestPermissionsResult()
no será llamado. Esto es cierto si su Actividad se deriva de Activity
o AppCompatActivity
.
Esto se puede arreglar eliminando ambas banderas de 'AndroidManifest.xml ' y terminar su actividad con finishAndRemoveTask()
en su lugar.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-04 14:20:05
Si tienes onRequestPermissionsResult
tanto en activity como en fragment, asegúrate de llamar a super.onRequestPermissionsResult
en activity. No se requiere en fragmento, pero está en actividad.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-30 10:40:56
Dentro del fragmento, necesitas llamar a:
FragmentCompat.requestPermissions(permissionsList, RequestCode)
No:
ActivityCompat.requestPermissions(Activity, permissionsList, RequestCode);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-09 10:54:53
Si está utilizando requestPermissions en fragment, acepta 2 parámetros en lugar de 3.
Debes usar requestPermissions(permissions, PERMISSIONS_CODE);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-16 14:45:00
Si por alguna razón ha extendido una actividad personalizada ubicada en alguna biblioteca externa que no llama al super, necesitará llamar manualmente al Fragmento super.onRequestPermissionsResult a sí mismo en su Actividad onRequestPermissionsResult.
YourActivity extends SomeActivityNotCallingSuperOnRequestPermissionsResult{
Fragment requestingFragment;//the fragment requesting the permission
...
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestingFragment!=null)
requestingFragment.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-22 11:20:03
Tiene la función checkPermissions para dispositivos pre Marshmallow en FragmentCompat. Yo uso así:
FragmentCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-30 11:48:25
He descubierto que es importante donde se llama android.support.v4.app.Fragment.requestPermissions
.
Si lo haces en onCreate()
, onRequestPermissionsResult()
nunca se llama.
Solución: Llámelo en onActivityCreated()
;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_DENIED)
requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, 0);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-15 23:33:00
Este problema fue causado por NestedFragments. Básicamente la mayoría de los fragmentos que tenemos extender un HostedFragment que a su vez extiende un CompatFragment. Tener estos fragmentos anidados causó problemas que finalmente fueron resueltos por otro desarrollador en el proyecto.
Estaba haciendo algunas cosas de bajo nivel como bit switching para que esto funcione, así que no estoy muy seguro de la solución final real
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-12 12:28:51
/* use the object of your fragment to call the
* onRequestPermissionsResult in fragment after
* in activity and use different request Code for
* both Activity and Fragment */
if (isFragment)
mFragment.requestPermissions(permissions.toArray(new
String[permissions.size()]),requestPermission);
else
ActivityCompat.requestPermissions(mActivity,permissions.toArray(new
String[permissions.size()]),requestPermission);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-03 13:31:12
Esto funcionará..
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-07 00:05:56
Si está llamando a este código desde un fragmento, tiene su propio método requestPermissions.
Así que el concepto básico es, si estás en una actividad, entonces llama
ActivityCompat.requestPermissions(this,
permissionsList,
permissionscode);
Y si está en un fragmento, simplemente llame a
requestPermissions(permissionsList,
permissionscode);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-23 17:56:27
Antes de comprobar todo de acuerdo con las respuestas anteriores, asegúrese de que su código de solicitud no es 0!!!
Comprueba el código de onRequestPermissionsResult() en FragmentActivity.java:
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
int index = (requestCode>>16)&0xffff;
if (index != 0) {
index--;
String who = mPendingFragmentActivityResults.get(index);
mPendingFragmentActivityResults.remove(index);
if (who == null) {
Log.w(TAG, "Activity result delivered for unknown Fragment.");
return;
}
Fragment frag = mFragments.findFragmentByWho(who);
if (frag == null) {
Log.w(TAG, "Activity result no fragment exists for who: " + who);
} else {
frag.onRequestPermissionsResult(requestCode&0xffff, permissions, grantResults);
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-07 01:50:13
Basado en la respuesta de goodgamerguy la solución es:
myFragment.this.requestPermissions(....)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-04 13:30:26
private void showContacts() {
if (getActivity().checkSelfPermission(Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, PERMISSIONS_REQUEST_READ_CONTACTS);
} else {
doShowContacts();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == PERMISSIONS_REQUEST_READ_CONTACTS && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
doShowContacts();
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-04 00:10:40
Puede usar requestPermissions(PERMISSIONS, MULTIPLE_PERMISSIONS_CODE);
. No utilice FragmentCompat si está utilizando v4.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-21 04:07:36
ACTUALIZACIÓN: vi la respuesta de otra persona sobre llamar a super.onRequestPermissionResult () en Actividad y que corrige el problema de código de solicitud que mencioné y llama al fragmento onRequestPermissionResult.
Ignora esto:
Para mí estaba llamando al onRequestPermissionResult de la Actividad a pesar de que yo llamaba fragment.requestPermission(...), PERO devolvió el resultado con un código de solicitud incorrecto (111 convertido en 65647 ¿por qué ??? Nunca lo sabré).
Afortunadamente esto es el único permiso que solicitamos en esa pantalla, así que simplemente ignoro el código de solicitud (no tengo tiempo para averiguar por qué no es correcto en este momento)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-12 22:23:44
Tengo una solución increíble para lograr esto hacer una BaseActivity como esta.
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler(this));
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
switch (requestCode) {
case 1: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
CustomToast.getInstance().setCustomToast("Now you can share the Hack.");
} else {
Toast.makeText(this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show();
}
}
}
}
}
Ahora puedes llamar al código para pedir permiso así
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
Ahora cada vez que esto sucede en cualquier lugar, ya sea en tu fragmento o en cualquier actividad, se llamaría a la actividad base.
Gracias
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-15 07:53:56
Detalles
- Kotlin 1.2.70
- comprobado en minSdkVersion 19
- Android studio 3.1.4
Algoritmo
Módulo - cámara, ubicación, ....
- Compruebe si hasSystemFeature (if module exist in phone)
- Compruebe si el usuario tiene acceso al módulo
- Enviar solicitud de permisos (pedir al usuario que permita el uso del módulo )
Características
- Trabajar con Actividades y Fragmentos
- Tiene una sola respuesta de resultado
- Puede verificar varios módulos en una solicitud
Solución
class PermissionType(val manifest_permission: String, val packageManager: String) {
object Defined {
val camera = PermissionType(Manifest.permission.CAMERA, PackageManager.FEATURE_CAMERA)
val currentLocation = PermissionType(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.FEATURE_LOCATION_GPS)
}
}
class Permission {
enum class PermissionResult {
ACCESS_ALLOWED, ACCESS_DENIED, NO_SYSTEM_FEATURE;
}
interface ManagerDelegate {
fun permissionManagerDelegate(result: Array<Pair<String, PermissionResult>>)
}
class Manager internal constructor(private val delegate: ManagerDelegate?) {
private var context: Context? = null
private var fragment: Fragment? = null
private var activity: AppCompatActivity? = null
private var permissionTypes: Array<PermissionType> = arrayOf()
private val REQUEST_CODE = 999
private val semaphore = Semaphore(1, true)
private var result: Array<Pair<String, PermissionResult>> = arrayOf()
constructor(permissionType: PermissionType, delegate: ManagerDelegate?): this(delegate) {
permissionTypes = arrayOf(permissionType)
}
constructor(permissionTypes: Array<PermissionType>, delegate: ManagerDelegate?): this(delegate) {
this.permissionTypes = permissionTypes
}
init {
when (delegate) {
is Fragment -> {
this.fragment = delegate
this.context = delegate.context
}
is AppCompatActivity -> {
this.activity = delegate
this.context = delegate
}
}
}
private fun hasSystemFeature(permissionType: PermissionType) : Boolean {
return context?.packageManager?.hasSystemFeature(permissionType.packageManager) ?: false
}
private fun hasAccess(permissionType: PermissionType) : Boolean {
return if (Build.VERSION.SDK_INT < 23) true else {
context?.checkSelfPermission(permissionType.manifest_permission) == PackageManager.PERMISSION_GRANTED
}
}
private fun sendRequest(permissionTypes: Array<String>) {
if (fragment != null) {
fragment?.requestPermissions(permissionTypes, REQUEST_CODE)
return
}
if (activity != null){
ActivityCompat.requestPermissions(activity!!, permissionTypes, REQUEST_CODE)
}
}
fun check() {
semaphore.acquire()
AsyncTask.execute {
var permissionsForSendingRequest: Array<String> = arrayOf()
this.result = arrayOf()
for (it in permissionTypes) {
if (!hasSystemFeature(it)) {
result += Pair(it.manifest_permission, PermissionResult.NO_SYSTEM_FEATURE)
continue
}
if (hasAccess(it)) {
result += Pair(it.manifest_permission, PermissionResult.ACCESS_ALLOWED)
} else {
permissionsForSendingRequest += it.manifest_permission
}
}
if (permissionsForSendingRequest.isNotEmpty()) {
sendRequest(permissionsForSendingRequest)
} else {
delegate?.permissionManagerDelegate(result)
}
}
}
fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
when (requestCode) {
REQUEST_CODE -> {
if (grantResults.isEmpty()) {
return
}
for ((i,permission) in permissions.withIndex()) {
for (item in this.permissionTypes) {
if (permission == item.manifest_permission && i < grantResults.size) {
result += if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Pair(item.manifest_permission, PermissionResult.ACCESS_ALLOWED)
} else {
Pair(item.manifest_permission, PermissionResult.ACCESS_DENIED)
}
break
}
}
}
delegate?.permissionManagerDelegate(result)
}
}
semaphore.release()
}
}
}
Uso en la actividad (en el fragmento el mismo)
class BaseActivity : AppCompatActivity(), Permission.ManagerDelegate {
private lateinit var permissionManager: Permission.Manager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.base_activity)
permissionManager = Permission.Manager(arrayOf(PermissionType.Defined.camera, PermissionType.Defined.currentLocation), this)
permissionManager.check()
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
permissionManager.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
override fun permissionManagerDelegate(result: Array<Pair<String, Permission.PermissionResult>>) {
result.forEach {
println("!!! ${it.first} ${it.second}")
// when (it.second) {
// Permission.PermissionResult.NO_SYSTEM_FEATURE -> {
// }
//
// Permission.PermissionResult.ACCESS_DENIED -> {
// }
//
// Permission.PermissionResult.ACCESS_ALLOWED -> {
// }
// }
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-16 22:40:58
Tuve un problema similar aceptar que estaba presionando el botón para hacer una llamada, que activa el callIntent. Primero comprobé el permiso, si no se me concede pido permiso y onRequestPermissionResult llamo al permiso de verificación y llamo de nuevo.
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case Constants.PERMISSIONS_REQUEST_CALL_PHONE: {
if ( grantResults[0] == PackageManager.PERMISSION_GRANTED) {
checkPermissionsAndCall();
}
}
}
}
public void checkPermissionsAndCall(){
if (Build.VERSION.SDK_INT > 22) {
if(ContextCompat.checkSelfPermission(getContext(),
Manifest.permission.CALL_PHONE)
!= PackageManager.PERMISSION_GRANTED){
requestPermissions( new String[]{Manifest.permission.CALL_PHONE}, Constants.PERMISSIONS_REQUEST_CALL_PHONE);
}
else{
callIntent();
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-30 00:57:12