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

Author: AndyOHart, 2015-09-22

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!

 535
Author: yavor87,
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)

 92
Author: Tieru,
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);
 56
Author: Sanjay Mangaroliya,
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.

 46
Author: Simon Featherstone,
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.

 35
Author: Dusan Zivkovic,
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);
 31
Author: Ben.Slama.Jihed,
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);

 15
Author: Don AkKi,
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);
    }
...
 14
Author: TouchBoarder,
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);
 12
Author: Marta Rodriguez,
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);

}
 12
Author: almisoft,
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

 9
Author: AndyOHart,
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);
 9
Author: Shahab Rauf,
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);
    }
 6
Author: Sumit khare,
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);
 4
Author: PounKumar Purushothaman,
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);
        }
    }
}
 2
Author: Chandler,
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(....)
 2
Author: Hamza Elmi,
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();
    }
}
 1
Author: user2002721,
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.

 1
Author: Remario,
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)

 1
Author: grgrssll,
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

 0
Author: Abhishek Dubey,
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, ....

  1. Compruebe si hasSystemFeature (if module exist in phone)
  2. Compruebe si el usuario tiene acceso al módulo
  3. Enviar solicitud de permisos (pedir al usuario que permita el uso del módulo )

Características

  1. Trabajar con Actividades y Fragmentos
  2. Tiene una sola respuesta de resultado
  3. 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 -> {
//                }
//            }
        }
    }
}
 0
Author: Vasily Bodnarchuk,
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();
        }
    }
}
 0
Author: ndheti,
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