android - permisos - onRequestPermissionsResult no se llama en el fragmento de diálogo
runtime permission android studio (10)
Además de la parte final de la respuesta de Nino Handler y para cualquier persona que todavía tenga problemas con esto, asegúrese de que si anula onRequestPermissionsResult en la actividad / fragmento principal de su fragmento de diálogo, llame a super.onRequestPermissionsResult allí.
Estaba anulando onRequestPermissionsResult en la actividad principal de mi fragmento de diálogo, pero no pude llamar al método super allí. Una vez que lo cambié para llamar al súper método, lo delegó correctamente en onRequestPermissionsResult en mi fragmento de diálogo.
He comenzado a trabajar con el permiso de ejecución de Android M.
Aquí me enfrento al problema de que si se llama a
requestPermissions
desde la clase
Dialog Fragment
, entonces
onRequestPermissionsResult
no se llama en la misma clase de
Dialog fragment
.
Pero si se llama a
requestPermissions
desde la clase
Activity
o la clase
Fragment
, el método
onRequestPermissionsResult
se llama en la misma clase.
Aquí está mi código de muestra:
public class ContactPickerDialog extends DialogFragment {
private static final int READ_CONTACTS_REQUEST_CODE = 12;
private Context mContext;
private void loadContact() {
if(hasPermission(mContext, Manifest.permission.READ_CONTACTS)){
new ContactSyncTask().execute();
} else {
this.requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, READ_CONTACTS_REQUEST_CODE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
Logger.d("TAG", "dialog onRequestPermissionsResult");
switch (requestCode) {
case READ_CONTACTS_REQUEST_CODE:
// Check Permissions Granted or not
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
new ContactSyncTask().execute();
} else {
// Permission Denied
Toast.makeText(getActivity(), "Read contact permission is denied", Toast.LENGTH_SHORT).show();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
private static boolean hasPermission(Context context, String permission){
return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
}
}
Aquí en el código estoy llamando
requestPermissions
método
requestPermissions
de la clase
Dialog Fragment
.
Así que espero obtener resultados en la misma clase.
Cualquier ayuda es apreciada. ¡Gracias por adelantado!
EDITAR: Aquí estoy agregando más detalles, para que sea más útil para los demás. Anteriormente he usado getChildFragmentManager () para mostrar el DialogFragment.
ContactPickerDialog dialog = new ContactPickerDialog();
dialog.show(getChildFragmentManager(), "Contact Picker");
Pero como @CommonWare me pidió que utilizara la actividad para mostrar el DialogFragment. He realizado los siguientes cambios y funciona.
ContactPickerDialog dialog = new ContactPickerDialog();
dialog.show(getActivity().getSupportFragmentManager(), "Contact Picker");
Este issue parece estar solucionado en la Biblioteca de soporte de Android 23.3.0 y versiones superiores.
Si está utilizando fragmentos de Support v4, los fragmentos anidados ahora recibirán devoluciones de llamada a onRequestPermissionsResult ().
Editar: @AndrewS, así es como puedes actualizar.
En su archivo build.gradle (aplicación), cambie la siguiente línea para usar la última biblioteca de soporte 24.0.0, que es la última versión:
dependencies {
compile ''com.android.support:appcompat-v7:24.0.0''
}
Lo hice así
public class DialogFragmentSMS extends DialogFragment implements View.OnClickListener {
public static DialogFragmentSMS frag;
private static View view;
private static ViewGroup parent;
private EditText editTextMensagem;
private String celular;
private final static int SMS_REQUEST = 20;
public DialogFragmentSMS() {
}
public static DialogFragmentSMS newInstance(String celular)
{
Bundle args = new Bundle();
args.putString("celular", celular);
frag = new DialogFragmentSMS();
frag.setArguments(args);
return frag;
}
@Override
public void onCreate(Bundle saveInstaceState)
{
super.onCreate(saveInstaceState);
}
@Override
public void onClick(View v) {
if (!PermissaoUtils.hasPermission(getActivity(), Manifest.permission.SEND_SMS)) {
//PermissaoUtils.requestPermissions(getActivity(), new String[]{Manifest.permission.SEND_SMS}, SMS_REQUEST);
frag.requestPermissions(new String[]{Manifest.permission.SEND_SMS}, SMS_REQUEST);
}else{
if (validaCampos()) {
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage("0" + celular, null, editTextMensagem.getText().toString(), null, null);
Toast.makeText(getActivity(), R.string.sms_enviado, Toast.LENGTH_SHORT).show();
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
frag.dismiss();
}
}
}
Mi permiso de clase
public class PermissaoUtils
{
public static boolean useRunTimePermissions() {
return Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1;
}
public static boolean hasPermission(Activity activity, String permission) {
if (useRunTimePermissions()) {
return activity.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;
}
return true;
}
public static void requestPermissions(Activity activity, String[] permission, int requestCode) {
if (useRunTimePermissions()) {
activity.requestPermissions(permission, requestCode);
}
}
}
Parece que hay
un error en Android
, donde los fragmentos anidados no admiten la devolución de llamada
onRequestPermissionsResult()
.
Para un
DialogFragment
, una solución parece ser que el fragmento que quiere mostrar el diálogo llame a un método en la actividad de alojamiento, y la actividad muestra el
DialogFragment
sí.
Si echa un vistazo a la documentación del método
requestPermissions
del fragmento, descubrirá que todavía tiene que declarar los permisos en su Manifiesto:
Si este no es el caso, no se invocará el propio
onRequestPermissionsResult
del fragmento.
En cambio, se llama a
onRequestPermissionsResult
la actividad pero no tendrá ningún efecto.
Por lo tanto, obtener un permiso desde un fragmento debe hacerse de la siguiente manera:
1. Declara el permiso en tu manifiesto
<uses-permission android:name="android.permission.CAMERA"/>
Ingrese esto antes de la etiqueta de la aplicación.
2. Verifique el permiso en su fragmento
if (ActivityCompat.checkSelfPermission(context, permission)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(
arrayOf(Manifest.permission.CAMERA),
REQUEST_CODE_CAMERA_PERMISSION)
}
3. Espere a que el permiso dé como resultado su fragmento
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
when (requestCode) {
REQUEST_CODE_CAMERA_PERMISSION -> {
val granted = grantResults.isNotEmpty()
&& permissions.isNotEmpty()
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
&& !ActivityCompat.shouldShowRequestPermissionRationale(activity, permissions[0])
when (granted) {
true -> openCamera()
else -> proceedWithoutPermission()
}
}
}
4. Asegúrese de no anular la actividad
onRequestPermissionsResult
onRequestPermissionsResult
el
onRequestPermissionsResult
la actividad hará que el fragmento del fragmento no reaccione.
Si está dentro de un
Fragment
de la biblioteca de soporte, llame a
requestPermissions()
directamente, y se le devolverá la llamada a su Fragment
onRequestPermissionsResult()
.
Si llama a
ActivityCompat.requestPermissions()
, entonces se
onRequestPermissionsResult()
la
Activity
onRequestPermissionsResult()
.
Si tiene problemas con el fragmento anidado, puede solicitar permiso del fragmento primario
getParentFragment().requestPermissions(new String[]{permission}, requestCode);
y luego reenviar la devolución de llamada al fragmento hijo
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grants) {
List<Fragment> fragments = getChildFragmentManager().getFragments();
if (fragments != null) {
for (Fragment fragment : fragments) {
if (fragment != null) {
fragment.onRequestPermissionsResult(requestCode, permissions, grants);
}
}
}
}
Tuve este problema sin fragmentos anidados, donde la actividad mostraba el fragmento de diálogo y no se pasaba el resultado.
Agregando
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
a la actividad
onRequestPermissionsResult()
resolvió el problema.
Una cosa que me ayudó fue esto. Cuando solicite permiso de un fragmento anidado, use getParent así
fragment.getParentFragment().requestPermissions((new String[]
{Manifest.permission.READ_CONTACTS}), requestCode);
y luego anule el fragmento primario enRequestPermissionResult y verifique el requestCode correspondiente.
Espero que te ayude también.
EDITAR:
Sugiero usar una nueva versión de Support Library 23.3.0, porque
Google solucionó el problema de no llamar a
onRequestPermissionsResult
, pero si por alguna razón necesita usar una versión anterior, consulte la respuesta de origen a continuación.
RESPUESTA ORIGINAL:
Estoy usando la próxima solución (junto con la biblioteca easyPermissions ):
Fragmento Base:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
/** child v4.fragments aren''t receiving this due to bug. So forward to child fragments manually
* https://code.google.com/p/android/issues/detail?id=189121
*/
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
List<Fragment> fragments = getChildFragmentManager().getFragments();
if (fragments != null) {
// it is possible that fragment might be null in FragmentManager
for (Fragment fragment : fragments) {
if (fragment != null) {
fragment.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
}
Actividad base:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
Fragment fragment = getSupportFragmentManager().findFragmentById(getFragmentContainer())
if (fragment != null) {
fragment.onRequestPermissionsResult(requestCode&0xff, permissions, grantResults);
}
}
Uso:
public class SomeFragment extends BaseFragment implements EasyPermissions.PermissionCallbacks {
private static final int PICK_CONTACT = 1;
private static final int READ_CONTACTS_PERM = 2;
// some code
@AfterPermissionGranted(READ_CONTACTS_PERM)
private void pickContactWithPermissionsCheck() {
if (EasyPermissions.hasPermissions(getContext(), Manifest.permission.READ_CONTACTS)) {
// Have permission
pickContactForResult();
} else {
// Request one permission
EasyPermissions.requestPermissions(this, getString(R.string.read_contacts_permission_explanation),
READ_CONTACTS_PERM, Manifest.permission.READ_CONTACTS);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// FIXME problem with incorrect requestCode coming to callback for Nested fragments
// More information here - https://code.google.com/p/android/issues/detail?id=189121
if (isVisible() && Arrays.asList(permissions).contains(Manifest.permission.READ_CONTACTS)) {
requestCode = READ_CONTACTS_PERM;
}
// EasyPermissions handles the request result.
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
}