onRequestPermissionsResult未在对话框片段中调用

时间:2015-10-16 11:33:00

标签: android android-fragments android-dialogfragment android-6.0-marshmallow

我已经开始研究Android M运行时权限了。在这里,我面临的问题是,如果从requestPermissions类调用Dialog Fragment,则onRequestPermissionsResult不会在同一Dialog fragment类中调用requestPermissions。但是,如果从Activity类或Fragment类调用onRequestPermissionsResult,则会在同一个类中调用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; } } 方法。

以下是我的示例代码:

requestPermissions

在代码中,我调用Dialog Fragment类的ContactPickerDialog dialog = new ContactPickerDialog(); dialog.show(getChildFragmentManager(), "Contact Picker"); 方法。所以我期待在同一个班级得到结果。

感谢任何帮助。提前谢谢!

修改 在这里,我将添加更多细节,以便对其他人更有帮助。 以前我使用getChildFragmentManager()来显示DialogFragment。

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

但是 @CommonWare 要求我使用activity来显示DialogFragment。我做了以下更改并且有效。

JComboBox execBrokerCombobox = new JComboBox();
String[] obj = new String[5];
for (i = 0; i < 5; i++) {
   obj[i] = "Option" + (i+1);
}
AutoCompleteSupport.install(jexecBrokerCombobox, GlazedLists.eventListOf(obj));

11 个答案:

答案 0 :(得分:106)

如果您位于支持库的Fragment内,请直接致电requestPermissions(),系统会回复您的片段onRequestPermissionsResult()

如果您致电ActivityCompat.requestPermissions(),那么它将会被回拨Activity onRequestPermissionsResult()

答案 1 :(得分:54)

似乎有a bug in Android,其中嵌套片段不支持onRequestPermissionsResult()回调。对于DialogFragment,解决方法似乎是让片段想要显示对话框调用托管活动的方法,并且活动显示DialogFragment本身。

答案 2 :(得分:13)

issue似乎已修复Android Support Library 23.3.0及以上版本。

  

如果您正在使用Support v4 Fragments,则现在将嵌套片段   接收onRequestPermissionsResult()的回调。

编辑:@AndrewS,这里有你可以更新的方式。

在build.gradle(app)文件中,更改以下行以使用最新版本的最新支持库24.0.0:

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

答案 3 :(得分:5)

修改

我建议使用新版本的支持库23.3.0,因为Google fixed issue with not calling onRequestPermissionsResult,但如果由于某些原因需要使用旧版本,请参阅下面的原始答案。

原始答案:

我正在使用下一个解决方法(与easyPermissions库一起使用):

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

<强>用法:

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

答案 4 :(得分:4)

有一件事对我有帮助。 当您从嵌套片段请求权限时,请使用getParent,如此

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

然后覆盖父片段onRequestPermissionResult并检查相应的requestCode。

希望它也能帮到你。

答案 5 :(得分:4)

如果嵌套片段有问题,可以从父片段

请求权限
getParentFragment().requestPermissions(new String[]{permission}, requestCode);

然后将回调转发给子片段

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

答案 6 :(得分:4)

我遇到了没有嵌套片段的问题,其中活动显示了对话框片段,结果未通过。

添加
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
活动的onRequestPermissionsResult()解决了这个问题。

答案 7 :(得分:1)

如果您查看该片段的requestPermissions方法的文档,您会发现仍然需要在清单中声明权限:

enter image description here

如果不是这种情况,则不会调用该片段自己的onRequestPermissionsResult

相反,活动的onRequestPermissionsResult被调用,但没有任何效果。

因此,应按照以下步骤在片段内划分权限:

1。在清单中声明权限

<uses-permission android:name="android.permission.CAMERA"/>

在应用程序标签之前输入此内容。

2。检查片段中的权限

if (ActivityCompat.checkSelfPermission(context, permission) 
        != PackageManager.PERMISSION_GRANTED) {

    requestPermissions(
        arrayOf(Manifest.permission.CAMERA), 
        REQUEST_CODE_CAMERA_PERMISSION)
}

3。等待片段中的权限结果

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。确保您不覆盖活动的 onRequestPermissionsResult

覆盖活动的onRequestPermissionsResult将导致片段的片段不响应。

答案 8 :(得分:0)

我这样做了

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

我的班级许可

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

答案 9 :(得分:0)

除了Nino Handler的答案的结尾部分以及对于仍然对此有疑问的任何人,请确保如果您确实在对话框片段的父活动/片段中覆盖了onRequestPermissionsResult,请在此处调用super.onRequestPermissionsResult。< / p>

我在对话框片段的父活动中重写onRequestPermissionsResult,但忽略了在那里调用super方法。一旦将其更改为调用super方法,它将正确地委派给对话框片段中的onRequestPermissionsResult。

答案 10 :(得分:0)

我在Android Manifest中添加了composer.lock,它对我有用,我不知道它如何影响其他功能。