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;
}
}
このコードでは、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");
Androidのバグ があるようです。ネストされたフラグメントはonRequestPermissionsResult()
コールバックをサポートしていません。 DialogFragment
の場合、回避策は、ホストアクティビティのメソッド呼び出しをダイアログに表示させたいフラグメントがあるように見え、アクティビティはDialogFragment
自体を表示します。
サポートライブラリのFragment
内にいる場合は、 requestPermissions()
を直接呼び出すと、フラグメントの onRequestPermissionsResult()
がコールバックされます。
ActivityCompat.requestPermissions()
を呼び出すと、Activity
の- onRequestPermissionsResult()
がコールバックされます。
この issue は Android Support Library 23.3. 以降のバージョンで修正されているようです。
サポートv4フラグメントを使用している場合、ネストされたフラグメントはonRequestPermissionsResult()へのコールバックを受け取るようになりました。
編集:@AndrewS、更新方法は次のとおりです。
Build.gradle(app)ファイルで、次の行を変更して、最新バージョンである最新のサポートライブラリ24.0.0を使用します。
dependencies {
compile 'com.Android.support:appcompat-v7:24.0.0'
}
ネストされたフラグメントなしでこの問題が発生しました。アクティビティでダイアログフラグメントが表示され、結果が渡されませんでした。
追加中super.onRequestPermissionsResult(requestCode, permissions, grantResults);
アクティビティのonRequestPermissionsResult()
に問題を解決しました。
編集:
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);
}
}
ネストされたフラグメントに問題がある場合は、親フラグメントから許可をリクエストできます
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);
}
}
}
}
私を助けたのはこれでした。ネストされたフラグメントから許可をリクエストするときは、次のようにgetParentを使用します
fragment.getParentFragment().requestPermissions((new String[]
{Manifest.permission.READ_CONTACTS}), requestCode);
次に、親フラグメントonRequestPermissionResultをオーバーライドし、対応するrequestCodeを確認します。
それがあなたにも役立つことを願っています。
フラグメントのrequestPermissions
メソッドのドキュメントを見ると、マニフェストでアクセス許可を宣言する必要があることがわかります。
そうでない場合、フラグメント自体の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
をオーバーライドすると、フラグメントの_は反応しなくなります。
このようにしてやった
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);
}
}
}
Ninoハンドラーの回答の最後の部分に加えて、まだこれに問題がある人のために、ダイアログフラグメントの親アクティビティ/フラグメントでonRequestPermissionsResultをオーバーライドする場合は、そこでsuper.onRequestPermissionsResultを呼び出すようにしてください。
ダイアログフラグメントの親アクティビティでonRequestPermissionsResultをオーバーライドしていましたが、そこでスーパーメソッドを呼び出すことを怠っていました。スーパーメソッドを呼び出すように変更すると、ダイアログフラグメントのonRequestPermissionsResultに適切に委任されます。