47

Ho iniziato a lavorare sull'autorizzazione di runtime di Android M. Qui sto affrontando il problema che se requestPermissions viene chiamato dalla classe alloranon viene chiamato nella classe . Ma se requestPermissions viene chiamato dalla classe Activity o dalla classe Fragment, il metodo onRequestPermissionsResult viene chiamato nella stessa classe.onRequestPermissionsResult non chiamato nel frammento di dialogo

Ecco il mio codice di esempio:

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; 
    } 

} 

Qui nel codice sto chiamando requestPermissions metodo Dialog Fragment di classe. Quindi mi aspetto di ottenere risultati nella stessa classe.

Qualsiasi aiuto è apprezzato. Grazie in anticipo!


EDIT: Qui sto aggiungendo ulteriori dettagli, in modo che sarà più utile agli altri. Precedentemente ho usato getChildFragmentManager() per mostrare DialogFragment.

ContactPickerDialog dialog = new ContactPickerDialog(); 
dialog.show(getChildFragmentManager(), "Contact Picker"); 

ma come @CommonWare mi ha chiesto di utilizzare l'attività per mostrare la DialogFragment. Ho fatto le seguenti modifiche e funziona.

ContactPickerDialog dialog = new ContactPickerDialog(); 
dialog.show(getActivity().getSupportFragmentManager(), "Contact Picker"); 
+0

È questo il 'DialogFragment' essere dimostrato da un altro frammento (vale a dire, annidato frammenti, 'getChildFragmentManager()') o direttamente da un'attività? – CommonsWare

+0

Viene mostrato da un altro frammento della finestra di dialogo usando getChildFragmentManager(). –

+2

Se dovessi indovinare, il problema è più con i frammenti nidificati, più che con un 'DialogFragment'. Potresti provare ad avere il frammento esistente che dice all'attività di mostrare il 'DialogFragment', per vedere se il problema scompare. – CommonsWare

risposta

49

Sembra che ci sia a bug in Android, dove i frammenti annidati non supportano il onRequestPermissionsResult() callback. Per un valore DialogFragment, sembra che il frammento desideri mostrare alla finestra di dialogo un metodo sull'attività di hosting e l'attività mostra lo stesso DialogFragment.

+0

Ho usato la classe di acitivity e build in Android 6.0 usando eclipse IDE, ho chiamato requestPermission(), ma onRequestPermissionsResult() non è eseguito. – Vasant

+0

@Vasant Il problema è stato risolto nella libreria di supporto 23.3.0. Se si utilizzano i frammenti di supporto v4, i frammenti nidificati ora riceveranno i callback su onRequestPermissionsResult(). – VishalKale

+0

funziona bene per me. Serve per usare FragmentActivity al posto di Activity. – Vasant

98

Se ci si trova all'interno di una libreria di supporto Fragment, chiamare direttamente lo requestPermissions() e il frammento verrà frammentato.

Se si chiama ActivityCompat.requestPermissions(), quindi è il onRequestPermissionsResult()Activity che verrà richiamato.

+0

puoi vedere nel mio codice, ho usato requestPermissions() di DialogFrament ma onRequestPermissionsResult() non viene chiamato. Come segnalato da CommonsWare, ** i frammenti nidificati non supportano la callback onRequestPermissionsResult() **. –

+5

Grazie per questo. Mi auguro che http://developer.android.com/training/permissions/requesting.html abbia menzionato che 'android.support.v4.app.Fragment # requestPermissions' esiste anche – Jon

+1

funziona solo per API23 + – dexxtr

4

Una cosa che mi ha aiutato è stato questo. Quando si richiede l'autorizzazione da un nidificato uso frammento getParent in questo modo

fragment.getParentFragment().requestPermissions((new String[] 
       {Manifest.permission.READ_CONTACTS}), requestCode); 

e poi ignorare il frammento onRequestPermissionResult genitore e controllare per il corrispondente requestCode.

Spero che ti aiuti pure.

4

Se avete problema con frammento nidificato, è possibile richiedere il permesso dal frammento genitore

getParentFragment().requestPermissions(new String[]{permission}, requestCode); 

e poi in avanti callback per frammento bambino

@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); 
      } 
     } 
    } 
} 
+1

getParentFragment() restituisce null in un DialogFragment creato su un frammento – Roel

+0

Sembra funzionare per il frammento annidato quando getParentFragment()! = Null. –

+0

Nel mio caso getParentFragment() == null e l'elenco frammenti è vuoto. – CoolMind

5

EDIT:

suggerisco utilizzare una nuova versione di Support Library 23.3.0, perché Google fixed issue with not calling onRequestPermissionsResult, ma se per alcuni motivi è necessario utilizzare una versione precedente, consultare la risposta di origine di seguito.

RISPOSTA ORIGINALE:

Sto usando prossima soluzione alternativa (insieme a easyPermissions biblioteca):

BaseFragment:

@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); 
      } 
     } 
    } 
} 

BaseActivity:

@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); 
    } 
} 

Usage:

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); 
    } 
} 
13

Questo issue sembra essere fissato in Android Support Library 23.3.0 o versioni successive.

Se stai usando supporto Frammenti v4, frammenti annidati ora ricevere callback per onRequestPermissionsResult().

Modifica: @AndrewS, ecco come aggiornare.

Nel file build.gradle (app), modificare la riga seguente per usare l'ultima libreria di supporto 24.0.0, che è la versione più recente:

dependencies { 
    compile 'com.android.support:appcompat-v7:24.0.0' 
} 
+0

Grazie per l'aggiornamento. –

+0

come aggiornare questa libreria a 23.3.0? Il mio studio dice che non ci sono aggiornamenti e la versione corrente è 23.2.1 – AndrewS

+1

@AndrewS Ho aggiornato la risposta spiegando come aggiornare. –

3

ho avuto questo problema senza frammenti nidificate, dove la l'attività mostrava il frammento della finestra di dialogo e il risultato non veniva superato.

Aggiunta
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
alla Attività di onRequestPermissionsResult() risolto il problema.

0

ho preso fatto come questo

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(); 
     } 
    } 
} 

Mia classe Permission

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); 
     } 
    } 
} 
0

Se si chiama DialogFragment da un uso Fragment questo:

YourDialogFragment dialogFragment = YourDialogFragment.newInstance(); 
dialogFragment.show(getActivity().getFragmentManager(), YourDialogFragment.TAG); 
dialogFragment.setParentFragment(this); 

scrivere anche nel frammento:

@Override 
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 
    super.onRequestPermissionsResult(requestCode, permissions, grantResults); 

    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
     ... 
    } 
} 

In YourDialogFragment scrivere ulteriore metodo per passare un frammento di genitore:

public void setParentFragment(Fragment fragment) { 
    this.fragment = fragment; 
} 

Più tardi nel YourDialogFragment quando le autorizzazioni che chiedono chiamano:

if (fragment != null) { 
    fragment.requestPermissions(new String[]{permission}, REQUEST_CODE); 
}