web-dev-qa-db-ja.com

v4.Fragmentにランタイムパーミッションを要求し、コールバックをFragmentに移動しますか?

矛盾を引き起こす奇妙な問題があります。ネイティブFragmentsに切り替えて修正する必要がありましたが、バグがあります。

私の元の問題:v4 Fragments.を使用してナビゲーションドロワーをセットアップしました。フラグメントの1つで許可を求めるためにActivityCompat.requestPermissions(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION, 1);を呼び出しますが、許可を許可または拒否しても何も起こりません。コールバックonRequestPermissionsResult()は呼び出されません。代わりに、フラグメントが添付されているアクティビティで呼び出されます。役に立たないが、フラグメントで動作するためにコールバックが必要です。

これを念頭に置いて、FragmentCompatを使用する必要があると言われましたが、それはnative Fragments (v13+)でのみ動作するため、ナビゲーションドロワーをv4サポートライブラリフラグメントではなくネイティブフラグメントから動作するように変更しました。 ただし、AppCompatActivityを使用しているため、addToBackStack()や前のフラグメントに戻るなど、特定の機能が動作しません。

簡単に言えば、誰もがv4.Fragmentを使用し、Fragmentで許可を求め、Fragmentにコールバックを取得する方法を知っていますか?これはAndroidのバグであり、まだ対処されていないように感じますが、100%ではありません。

私のコードを見る必要があるかどうかを教えてください、それは実行時のアクセス許可に必要な標準的なメソッドです。私の理解からはうまくいきませんが、v4 Fragmentsで作業したいと思います。

55
RED_

この動作は、v4 Fragmentサポートクラス FragmentのrequestPermissions に存在するようです。 Activity/FragmentCompatの実装は、11〜23のAPIレベルで拡張機能を備えたネイティブクラスを使用したい人のために存在します。

18
NasaGeek

これを親アクティビティに追加するとうまくいきます:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    if (fragments != null) {
        for (Fragment fragment : fragments) {
            fragment.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }
}

ソース: https://code.google.com/p/Android/issues/detail?id=189121#c5

67
Samuel Gaona

fragment v4でpermissionResultを取得する必要がある場合は、必ず使用してください

Fragment.requestPermission(String[], int);

の代わりに

AppCompat.requestPermission(Activity, String[], int)

this answer!

18
DoruChidean

コードのこの部分を使用できます

requestPermissions(new String[]{Manifest.permission.GET_ACCOUNTS}, PERMISSION_REQUEST_CODE);
11
Abubakar

サポートフラグメント内のアクセス許可を確認し、コールバックを取得する必要があるときに、最近同じ状況に直面しました。

ContextCompatcheckSelfPermissionに使用してから、@ NasaGeekがAndroid.support.v4.app.FragmentrequestPermissionsを呼び出して許可を要求し、onRequestPermissionsResultにコールバックすることができたv4フラグメント。

お役に立てれば。

ありがとう。

7

現時点では、最も安定したソリューションは手作業で行っています。私自身は、親フラグメントから子フラグメントに通知するだけで解決しました。

if (fragment.getParentFragment() != null) {
                            Fragment parentFragment = fragment.getParentFragment();
                            try {
                                ChildFragmentPermissionRegistry registry = (ChildFragmentPermissionRegistry) parentFragment;
                                registry.registerPermissionListener((ChildFragmentPermissionCallback) fragment);
                                parentFragment.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, STORAGE_PERMISSION_REQUEST_CODE);
                            } catch (ClassCastException e) {
                                Log.e(PermissionVerifier.class.getSimpleName(), e.getMessage());
                            }
                        } else {
                            fragment.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, STORAGE_PERMISSION_REQUEST_CODE);
                        }

親フラグメントがChildFragmentPermissionRegistryインターフェースを実装し、子フラグメントを登録する場合、

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (callback != null) {
        callback.onRequestPermissionsResult(requestCode, permissions, grantResults);
        callback = null;
    }
}

および子フラグメントはChildFragmentPermissionCallbackを実装します

インターフェイスは次のようなものです。

public interface ChildFragmentPermissionCallback {
    void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults);
}

public interface ChildFragmentPermissionRegistry {
    void registerPermissionListener(ChildFragmentPermissionCallback callback);
}
2

v4.Fragmentはうまく機能します。 v4.Fragmentのネストされたフラグメントに問題があります。許可が求められますが、ネストされたフラグメントでonRequestPermissionsResult()コールバックが呼び出されることはありません!

問題が開かれました

2
android_dev

Googleで最近修正されたかどうかはわかりませんが、何のトリックもせずに期待どおりの結果を得ることができます。

最も重要なことは、アクティビティでsuper.onRequestPermissionsResult(requestCode, permissions, grantResults);を呼び出すことです。そのため、フラグメントから要求された場合、結果をフラグメントに渡します。

だから、私がやっていることは:

1)フラグメントで、v4 fragment.requestPermissions(permissions, requestCode)を使用して許可を求めます

2)アクティビティのonRequestPermissionsResultで、super.onRequestPermissionsResult(requestCode, permissions, grantResults);を呼び出す必要があります

3)フラグメントのonRequestPermissionsResultに、結果を処理するコードを記述します。

1
YunhaoLIU

私の場合、フラグメントに許可を要求し、フラグメントで応答を取得する必要もあります。

しかし、Android 8.1で実行されている私の電話

これを確認するためにもう1つの条件を追加する必要がありました

だから最終的には私の解決策があります

private void doOnWazeButtonClick()
{
    int permissionStatus = PackageManager.PERMISSION_DENIED;

    if (getContext() != null)
    {
        permissionStatus = ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION);
    }

    if (permissionStatus == PackageManager.PERMISSION_GRANTED)
    {
        showContentWaze();
    }
    else
    {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
        {
            Objects.requireNonNull(getActivity()).requestPermissions(new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_CODE_PERMISSION_ACCESS_FINE_LOCATION);
        }
        else
        {
            requestPermissions(new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_CODE_PERMISSION_ACCESS_FINE_LOCATION);
        }
    }
}