web-dev-qa-db-ja.com

onRequestPermissionsResultがダイアログフラグメントで呼び出されない

Android Mランタイム許可の作業を開始しました。ここで、requestPermissionsDialog 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;
    }

} 

このコードでは、Dialog FragmentクラスのrequestPermissionsメソッドを呼び出しています。したがって、同じクラスで結果が得られると期待しています。

どんな助けも大歓迎です。前もって感謝します!


編集:ここでは、他の人にとってより役立つように、詳細を追加しています。以前は、getChildFragmentManager()を使用してDialogFragmentを表示しました。

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

しかし、As @ CommonWareは、DialogFragmentを表示するためにアクティビティを使用するように要求しました。次の変更を加えましたが、機能します。

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

Androidのバグ があるようです。ネストされたフラグメントはonRequestPermissionsResult()コールバックをサポートしていません。 DialogFragmentの場合、回避策は、ホストアクティビティのメソッド呼び出しをダイアログに表示させたいフラグメントがあるように見え、アクティビティはDialogFragment自体を表示します。

54
CommonsWare

サポートライブラリのFragment内にいる場合は、 requestPermissions() を直接呼び出すと、フラグメントの onRequestPermissionsResult() がコールバックされます。

ActivityCompat.requestPermissions() を呼び出すと、Activityの-​​ onRequestPermissionsResult() がコールバックされます。

106
minipif

この issueAndroid Support Library 23.3. 以降のバージョンで修正されているようです。

サポートv4フラグメントを使用している場合、ネストされたフラグメントはonRequestPermissionsResult()へのコールバックを受け取るようになりました。

編集:@AndrewS、更新方法は次のとおりです。

Build.gradle(app)ファイルで、次の行を変更して、最新バージョンである最新のサポートライブラリ24.0.0を使用します。

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

ネストされたフラグメントなしでこの問題が発生しました。アクティビティでダイアログフラグメントが表示され、結果が渡されませんでした。

追加中
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
アクティビティのonRequestPermissionsResult()に問題を解決しました。

5
Eric B.

編集:

GoogleはonRequestPermissionsResult を呼び出さないという問題を修正したため、サポートライブラリ23.3.0の新しいバージョンを使用することをお勧めしますが、何らかの理由で古いバージョンを使用する必要がある場合バージョン、下のOriginの回答をご覧ください。

元の回答:

私は次の回避策を使用しています( 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);
    }
}
5
Oleksandr

ネストされたフラグメントに問題がある場合は、親フラグメントから許可をリクエストできます

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

私を助けたのはこれでした。ネストされたフラグメントから許可をリクエストするときは、次のようにgetParentを使用します

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

次に、親フラグメントonRequestPermissionResultをオーバーライドし、対応するrequestCodeを確認します。

それがあなたにも役立つことを願っています。

4
udit

フラグメントの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をオーバーライドすると、フラグメントの_は反応しなくなります。

1
luckyhandler

このようにしてやった

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

Ninoハンドラーの回答の最後の部分に加えて、まだこれに問題がある人のために、ダイアログフラグメントの親アクティビティ/フラグメントでonRequestPermissionsResultをオーバーライドする場合は、そこでsuper.onRequestPermissionsResultを呼び出すようにしてください。

ダイアログフラグメントの親アクティビティでonRequestPermissionsResultをオーバーライドしていましたが、そこでスーパーメソッドを呼び出すことを怠っていました。スーパーメソッドを呼び出すように変更すると、ダイアログフラグメントのonRequestPermissionsResultに適切に委任されます。

0
D.J.M. Francis