Android M-ランタイム権限を確認する-ユーザーが「二度と尋ねない」をチェックしたかどうかを判断する方法は?


307

これによると:http : //developer.android.com/preview/features/runtime-permissions.html#codingアプリはランタイム権限を確認し、まだ付与されていない場合は権限をリクエストできます。次のダイアログが表示されます。

ここに画像の説明を入力してください

ユーザーが重要な権限を拒否した場合、アプリには、権限が必要な理由と、拒否の影響についての説明が表示されます。このダイアログには2つのオプションがあります。

  1. 再試行(許可が再度要求されます)
  2. 拒否(アプリはその許可なしで動作します)。

Never ask againただし、ユーザーがチェックした場合、特にユーザーが以前に一度拒否した場合は特に、説明付きの2番目のダイアログは表示されません。ここでの質問は、ユーザーがチェックしたNever ask againかどうかをアプリがどのようにして知るのかということです。IMOはonRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)私にその情報を提供しません。

2番目の質問は次のとおりです。Googleは、アプリが権限を必要とする理由を説明するカスタムメッセージを権限ダイアログに組み込む計画を持っていますか?そうすれば、UXを向上させる2つ目のダイアログは決してありません。


9
「Googleは、アプリが権限を必要とする理由を説明するカスタムメッセージを権限ダイアログに組み込む予定はありますか?」-M許可システムに関するGoogle I | Oのプレゼンテーションで、Q&Aで誰かが尋ねたのを覚えているようですが、答えは彼らがそれについて考えているということでした。
CommonsWare

1
自分ではテストしませんでしたが、ドキュメントにはActivity.shouldShowRequestPermissionRationale(String)と記載されています。このメソッドは、アプリが以前にこの権限をリクエストし、ユーザーがリクエストを拒否した場合にtrueを返します。これは、アクセス許可が必要な理由をユーザーに説明する必要があることを示しています。ユーザーが過去にパーミッションリクエストを却下し、パーミッションリクエストシステムダイアログの[今後表示しない]オプションを選択した場合、このメソッドはfalseを返します。また、デバイスポリシーでアプリがその権限を持つことを禁止している場合も、メソッドはfalseを返します。
Fraid

1
@Fraid:Android Mのプレビュー#2でこれを追加したようです:developer.android.com/preview/support.html#preview2-notesそしてそれはおそらく私が探していたものです。今はテストできませんが、来週テストします。期待どおりの結果が得られた場合は、回答として投稿して評価を得ることができます。それまでの間、これは他の人を助けるかもしれません:youtube.com/watch?v=f17qe9vZ8RM
v=f17qe9vZ8RM

危険な権限と特別な権限の例: github.com/henrychuangtw/AndroidRuntimePermission
HenryChuang

1
開発者にとって@Alexは確かに難しいですが、ユーザーの観点からは、特定の権限を付与または拒否できることは理にかなっています。私が目にする主な問題は、アクセス許可の細分性に非常に一貫性がなく、アプリで実行しようとしていることとほとんど関係のないアクセス許可を要求してしまうことです(たとえば、接続したいときに連絡先のアクセス許可)認証のためにデバイスアカウントのリストが必要であり、アカウント権限は連絡先権限グループの一部であるため、Googleドライブ。
エマニュエルモエクリン

回答:


341

Developer Preview 2では、アプリによる権限のリクエスト方法にいくつかの変更が加えられています(http://developer.android.com/preview/support.html#preview2-notesも参照してください)。

最初のダイアログは次のようになります。

ここに画像の説明を入力してください

(今後表示しない)チェックボックスはありません(開発者プレビュー1とは異なります)。ユーザーが許可を拒否し、許可がアプリに不可欠である場合、アプリがその許可を要求する理由を説明する別のダイアログを表示できます。たとえば、次のようにします。

ここに画像の説明を入力してください

ユーザーが再度拒否した場合、アプリはそのアクセス許可が絶対に必要な場合はシャットダウンするか、制限された機能で実行し続ける必要があります。ユーザーが再検討(および再試行を選択)した場合は、再度許可が要求されます。今回のプロンプトは次のようになります。

ここに画像の説明を入力してください

2回目には、[今後は表示しない]チェックボックスが表示されます。ユーザーが再び拒否し、チェックボックスがオンになっている場合、それ以上は発生しません。チェックボックスがチェックされているかどうかは、Activity.shouldShowRequestPermissionRationale(String)を使用して、たとえば次のように判断できます。

if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_CONTACTS)) {...

それはAndroidのドキュメントが言うことです( https://developer.android.com/training/permissions/requesting.html):

詳細な説明が必要な状況を見つけるために、システムにはActivity.shouldShowRequestPermissionRationale(String)メソッドが用意されています。アプリが以前にこの権限をリクエストし、ユーザーがリクエストを拒否した場合、このメソッドはtrueを返します。これは、アクセス許可が必要な理由をユーザーに説明する必要があることを示しています。

ユーザーが過去にパーミッションリクエストを拒否し、パーミッションリクエストシステムダイアログの[今後は表示しない]オプションを選択した場合、このメソッドはfalseを返します。また、デバイスポリシーでアプリがその権限を持つことを禁止している場合も、メソッドはfalseを返します。

ユーザーが「二度と尋ねない」で拒否したかどうかを確認するには、ユーザーが権限を付与しなかったときに、onRequestPermissionsResultでshouldShowRequestPermissionRationaleメソッドをもう一度確認します。

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    if (requestCode == REQUEST_PERMISSION) {
        // for each permission check if the user granted/denied them
        // you may want to group the rationale in a single dialog,
        // this is just an example
        for (int i = 0, len = permissions.length; i < len; i++) {
            String permission = permissions[i];
            if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
            // user rejected the permission
                boolean showRationale = shouldShowRequestPermissionRationale( permission );
                if (! showRationale) {
                    // user also CHECKED "never ask again"
                    // you can either enable some fall back,
                    // disable features of your app
                    // or open another dialog explaining
                    // again the permission and directing to
                    // the app setting
                } else if (Manifest.permission.WRITE_CONTACTS.equals(permission)) {
                    showRationale(permission, R.string.permission_denied_contacts);
                    // user did NOT check "never ask again"
                    // this is a good place to explain the user
                    // why you need the permission and ask if he wants
                    // to accept it (the rationale)
                } else if ( /* possibly check more permissions...*/ ) {
                }
            }
        }
    }
}

次のコードでアプリの設定を開くことができます:

Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, REQUEST_PERMISSION_SETTING);

ユーザーを認証ページに直接送る方法はありません。


30
ユーザーが「二度と尋ねない」を選択したかどうかを確認するために、shouldShowRequestPermissionRationale()メソッドの戻り値をfalseに検証しました。しかし、許可を求めるときに初めて、その値がfalseになっています。そのため、ユーザーが[今後表示しない]チェックボックスを選択したかどうかを区別できません。提案してください??
Sagar Trehan、2015年

32
私の理解によると、shouldShowRationalePermissionRationale()メソッドは次の3つの場合にfalseを返します。1.許可を求める前にこのメソッドを初めて呼び出す場合。2.ユーザーが[今後は質問しない]を選択して、権限を拒否した場合。3.デバイスポリシーにより、アプリがその権限を持つことが禁止されている場合
Sagar Trehan

24
すべてが良い...しかし、開発者は、ユーザーが「二度と尋ねない」と言ったかどうかを本当に知る必要があります。機能にアクセスするための素敵なボタンがあります。ユーザーが初めてクリックしたとき:根拠を尋ねるべきですか?いいえ、許可を求めます。ユーザーは拒否します。ユーザーはもう一度ボタンをクリックします:根拠?うん!理論的根拠を示し、ユーザーが「OK」と言ってから、拒否して二度と質問しないでください(彼は馬鹿ですが、ユーザーはよくそうです)。後でユーザーがもう一度ボタンを押した理由は?いいえ、許可を求めます。ユーザーには何も起こりません。ユーザーに伝える方法が本当に必要です。この機能が必要な場合は、アプリの設定に移動してアクセス許可を付与してください。
Daniele Segato、2015年

4
素晴らしい@EmanuelMoecklinこれはGoogleドキュメントよりも優れています:D
Daniele Segato

4
権限をリクエストしない限り、onRequestPermissionsResultは呼び出されません。権限が初めてリクエストされたときに「もう二度と尋ねない」チェックボックスがないため、shouldShowRequestPermissionRationaleはTrueを返します(権限はリクエストされますが、二度と問い合わせることはありません)。その結果、根拠は常にユーザーが最初に許可を拒否したときに表示されますが、その後はチェックボックスがチェックされていなかった場合にのみ表示されます。
Emanuel Moecklin、2015年

95

確認してもいい shouldShowRequestPermissionRationale()ますonRequestPermissionsResult()

shouldShowRequestPermissionRationale https://youtu.be/C8lUdPVSzDk?t=2m23s

で許可が付与されているかどうかを確認しonRequestPermissionsResult()ます。もしないは、確認してくださいshouldShowRequestPermissionRationale()

  1. このメソッドが返されたtrue場合は、この特定の権限が必要な理由を説明してください。次に、ユーザーの選択に応じてrequestPermissions()
  2. 戻った場合はfalse、権限が付与されておらず、アプリを続行できないか、特定の機能が無効になっているというエラーメッセージが表示されます。

以下はサンプルコードです。

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
        case STORAGE_PERMISSION_REQUEST:
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // permission was granted :)
                downloadFile();
            } else {
                // permission was not granted
                if (getActivity() == null) {
                    return;
                }
                if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                    showStoragePermissionRationale();
                } else {
                    Snackbar snackbar = Snackbar.make(getView(), getResources().getString(R.string.message_no_storage_permission_snackbar), Snackbar.LENGTH_LONG);
                    snackbar.setAction(getResources().getString(R.string.settings), new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            if (getActivity() == null) {
                                return;
                            }
                            Intent intent = new Intent();
                            intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                            Uri uri = Uri.fromParts("package", getActivity().getPackageName(), null);
                            intent.setData(uri);
                            OrderDetailFragment.this.startActivity(intent);
                        }
                    });
                    snackbar.show();
                }
            }
            break;
    }
}

どうやら、グーグルマップは位置情報の許可のためにこれを正確に行います。


写真とYoutubeのリンクをありがとう。それは多かれ少なかれ私自身の答えと一致します。質問は、shouldShowRequestPermissionRationaleメソッドを持たない開発者プレビュー1のみが利用可能な場合に行われたことに注意する必要があります。
Emanuel Moecklin、2015年

私はアンドロイドの新人で、このonRequestPermissionsResult()メソッドに乗り換えたいです。しかし、スーパータイプのメソッドを実装する必要があるというエラーが発生します。これを使用する方法を教えてもらえますか
Andrain '18年

39

以下は、現在の許可ステータスを確認するための便利な方法です。

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({GRANTED, DENIED, BLOCKED_OR_NEVER_ASKED })
    public @interface PermissionStatus {}

    public static final int GRANTED = 0;
    public static final int DENIED = 1;
    public static final int BLOCKED_OR_NEVER_ASKED = 2;

    @PermissionStatus 
    public static int getPermissionStatus(Activity activity, String androidPermissionName) {
        if(ContextCompat.checkSelfPermission(activity, androidPermissionName) != PackageManager.PERMISSION_GRANTED) {
            if(!ActivityCompat.shouldShowRequestPermissionRationale(activity, androidPermissionName)){
                return BLOCKED_OR_NEVER_ASKED;
            }
            return DENIED;
        }
        return GRANTED;
    }

警告:ユーザーがユーザープロンプトを介して許可を承認/拒否する前の最初のアプリの起動時にBLOCKED_OR_NEVER_ASKEDを返します(SDK 23以降のデバイスの場合)

更新:

Androidサポートライブラリにも非常に類似したクラスがあるようです android.support.v4.content.PermissionCheckercheckSelfPermission()を返すを含む。

public static final int PERMISSION_GRANTED = 0;
public static final int PERMISSION_DENIED = -1;
public static final int PERMISSION_DENIED_APP_OP = -2;

1
最初の起動では、共有設定にブール値を格納しています。
Saeid Farivar 2016年

5
これはBLOCKED_OR_NEVER_ASKED、許可がまだ要求されていない場合は常に戻ります。
Saket 2017

6
はい、それが「BLOCKED_OR_NEVER_ASKED」と呼ばれる理由です。最後の文も参照してください
Patrick Favre

3
android.content.pmすでに定義PERMISSION_GRANTED = 0PERMISSION_DENIED = -1。多分セットBLOCKED_OR_NEVER_ASKED = PERMISSION_DENIED - 1か何か?
samis

警告の取り扱いについては、以下のmVckの回答を参照してください。
samis

28

ユーザーが「今後は質問しない」とマークすると、質問を再表示できなくなります。ただし、ユーザーは以前に許可を拒否しており、設定で許可を付与する必要があることをユーザーに説明できます。次のコードを使用して、設定を参照します。

@Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults) {

    if (grantResults.length > 0
            && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        // now, you have permission go ahead
        // TODO: something

    } else {

        if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                Manifest.permission.READ_CALL_LOG)) {
            // now, user has denied permission (but not permanently!)

        } else {

            // now, user has denied permission permanently!

            Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), "You have previously declined this permission.\n" +
                "You must approve this permission in \"Permissions\" in the app settings on your device.", Snackbar.LENGTH_LONG).setAction("Settings", new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                startActivity(new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + BuildConfig.APPLICATION_ID)));

            }
        });
        View snackbarView = snackbar.getView();
        TextView textView = (TextView) snackbarView.findViewById(android.support.design.R.id.snackbar_text);
        textView.setMaxLines(5);  //Or as much as you need
        snackbar.show();

        }

    }
    return;
}

androidXへの移行では、android.support.design.Rをcom.google.android.material.Rに置き換えることができます
Ridha Rezzag

26

誰かに役立つかもしれません:-

私が気付いたことは、shouldShowRequestPermissionRationale()フラグをonRequestPermissionsResult()コールバックメソッドにチェックインすると、2つの状態しか表示されないことです。

状態1:-Return true:-ユーザーが[Deny]権限をクリックしたとき(初回を含む)

状態2:-falseを返します:-ユーザーが「二度と尋ねない」を選択した場合。

詳細な実施例のリンク


2
これは、ユーザーが二度と尋ねないオプションを選択したかどうかを検出する正しい方法です。
ムハンマドババール2017年

ああ、ここで重要なのonRequestPermissionsResultは、実際に許可を要求するときではなく、でこれを処理することです。
ジョシュアピンター

26

これは、コールバックメソッド内にアクセス許可の根拠が表示されるかどうかを確認することで判断できます。また、二度と要求ないように設定された権限がある場合は、設定から権限を付与するようユーザーに要求できます。onRequestPermissionsResult()

私の完全な実装は以下のようになります。これは、単一または複数の権限要求の両方で機能します。以下を使用するか、私のライブラリを直接使用してください

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if(permissions.length == 0){
        return;
    }
    boolean allPermissionsGranted = true;
    if(grantResults.length>0){
        for(int grantResult: grantResults){
            if(grantResult != PackageManager.PERMISSION_GRANTED){
                allPermissionsGranted = false;
                break;
            }
        }
    }
    if(!allPermissionsGranted){
        boolean somePermissionsForeverDenied = false;
        for(String permission: permissions){
            if(ActivityCompat.shouldShowRequestPermissionRationale(this, permission)){
                //denied
                Log.e("denied", permission);
            }else{
                if(ActivityCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED){
                    //allowed
                    Log.e("allowed", permission);
                } else{
                    //set to never ask again
                    Log.e("set to never ask again", permission);
                    somePermissionsForeverDenied = true;
                }
            }
        }
        if(somePermissionsForeverDenied){
            final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
            alertDialogBuilder.setTitle("Permissions Required")
                    .setMessage("You have forcefully denied some of the required permissions " +
                            "for this action. Please open settings, go to permissions and allow them.")
                    .setPositiveButton("Settings", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                                    Uri.fromParts("package", getPackageName(), null));
                            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            startActivity(intent);
                        }
                    })
                    .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                        }
                    })
                    .setCancelable(false)
                    .create()
                    .show();
        }
    } else {
        switch (requestCode) {
            //act according to the request code used while requesting the permission(s).
        }
    }
}

hii @nabin私の要件は、ダウンロードボタン(pdfファイルをダウンロードする)をクリックしたときに、書き込み権限が許可または拒否されていることを確認する必要があるため、このコードの使用方法です。あなたは私をガイドすることができます
Rucha Bhatt Joshi

こんにちは@RuchaBhatt私のライブラリを見てください。github.com/nabinbhandari/Android-Permissions
Bhandari

15

すべての「状態」(最初に拒否された、単に拒否された、「二度と尋ねない」で拒否された、または永久に拒否された)を検出する場合は、次の操作を実行できます。

2つのブール値を作成する

private boolean beforeClickPermissionRat;
private boolean afterClickPermissionRat;

許可を求める前に最初のものを設定します。

beforeClickPermissionRat = shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE);

2番目のものをonRequestPermissionsResultメソッド内に設定します。

afterClickPermissionRat = shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE);

次の「テーブル」を使用して、onRequestPermissionsResult()で必要なことをすべて実行します(まだ権限がないことを確認した後)。

// before after
// FALSE  FALSE  =  Was denied permanently, still denied permanently --> App Settings
// FALSE  TRUE   =  First time deny, not denied permanently yet --> Nothing
// TRUE   FALSE  =  Just been permanently denied --> Changing my caption to "Go to app settings to edit permissions"
// TRUE   TRUE   =  Wasn't denied permanently, still not denied permanently --> Nothing

パーミッションをリクエストする前に根拠を表示したくない場合を除き、requestPermissionsを呼び出す前にshouldShowRequestPermissionRationaleをチェックしても意味がありません。ユーザーが許可を拒否した後にのみ根拠を表示することは、最近のほとんどのアプリがそれを処理する方法のようです。
Emanuel Moecklin 16

2
@EmanuelMoecklin、私が知る限り、それがすでに拒否されているかどうか(私の真理値表で説明されているように、その前後を確認することによって)または初めて拒否されたかどうか(私の場合、ユーザーをアプリの設定が完全​​に拒否された場合)
mVck

1
// TRUE FALSEまた、ユーザーが以前にそれを拒否した後に許可を許可した場合にも発生します。
samis

11

私は同じ問題を抱えていて、それを理解しました。人生をずっと単純にするために、ランタイムアクセス許可を処理するutilクラスを作成しました。

public class PermissionUtil {
    /*
    * Check if version is marshmallow and above.
    * Used in deciding to ask runtime permission
    * */
    public static boolean shouldAskPermission() {
        return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M);
    }
private static boolean shouldAskPermission(Context context, String permission){
        if (shouldAskPermission()) {
            int permissionResult = ActivityCompat.checkSelfPermission(context, permission);
            if (permissionResult != PackageManager.PERMISSION_GRANTED) {
                return true;
            }
        }
        return false;
    }
public static void checkPermission(Context context, String permission, PermissionAskListener listener){
/*
        * If permission is not granted
        * */
        if (shouldAskPermission(context, permission)){
/*
            * If permission denied previously
            * */
            if (((Activity)context).shouldShowRequestPermissionRationale(permission)) {
                listener.onPermissionPreviouslyDenied();
            } else {
                /*
                * Permission denied or first time requested
                * */
if (PreferencesUtil.isFirstTimeAskingPermission(context, permission)) {
                    PreferencesUtil.firstTimeAskingPermission(context, permission, false);
                    listener.onPermissionAsk();
                } else {
                    /*
                    * Handle the feature without permission or ask user to manually allow permission
                    * */
                    listener.onPermissionDisabled();
                }
            }
        } else {
            listener.onPermissionGranted();
        }
    }
/*
    * Callback on various cases on checking permission
    *
    * 1.  Below M, runtime permission not needed. In that case onPermissionGranted() would be called.
    *     If permission is already granted, onPermissionGranted() would be called.
    *
    * 2.  Above M, if the permission is being asked first time onPermissionAsk() would be called.
    *
    * 3.  Above M, if the permission is previously asked but not granted, onPermissionPreviouslyDenied()
    *     would be called.
    *
    * 4.  Above M, if the permission is disabled by device policy or the user checked "Never ask again"
    *     check box on previous request permission, onPermissionDisabled() would be called.
    * */
    public interface PermissionAskListener {
/*
        * Callback to ask permission
        * */
        void onPermissionAsk();
/*
        * Callback on permission denied
        * */
        void onPermissionPreviouslyDenied();
/*
        * Callback on permission "Never show again" checked and denied
        * */
        void onPermissionDisabled();
/*
        * Callback on permission granted
        * */
        void onPermissionGranted();
    }
}

また、PreferenceUtilメソッドは次のとおりです。

public static void firstTimeAskingPermission(Context context, String permission, boolean isFirstTime){
SharedPreferences sharedPreference = context.getSharedPreferences(PREFS_FILE_NAME, MODE_PRIVATE;
 sharedPreference.edit().putBoolean(permission, isFirstTime).apply();
 }
public static boolean isFirstTimeAskingPermission(Context context, String permission){
return context.getSharedPreferences(PREFS_FILE_NAME, MODE_PRIVATE).getBoolean(permission, true);
}

ここで必要なのは、適切な引数を指定してメソッド* checkPermission *を使用することだけです。

ここに例があります

PermissionUtil.checkPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    new PermissionUtil.PermissionAskListener() {
                        @Override
                        public void onPermissionAsk() {
                            ActivityCompat.requestPermissions(
                                    thisActivity,
              new String[]{Manifest.permission.READ_CONTACTS},
                            REQUEST_EXTERNAL_STORAGE
                            );
                        }
@Override
                        public void onPermissionPreviouslyDenied() {
                       //show a dialog explaining permission and then request permission
                        }
@Override
                        public void onPermissionDisabled() {
Toast.makeText(context, "Permission Disabled.", Toast.LENGTH_SHORT).show();
                        }
@Override
                        public void onPermissionGranted() {
                            readContacts();
                        }
                    });

私のアプリは、ユーザーが「二度と尋ねない」をチェックしたかどうかをどのようにして知るのですか?

ユーザーが[今後は確認しない]をオンにした場合onPermissionDisabledでコールバックされます

ハッピーコーディング:)


shouldShowRequestPermissionRationaleここでエラーが発生しました。助けてください。
Rucha Bhatt Joshi 2017年

:)協力いただきありがとうございます..私はshouldShowRequestPermissionRationale iは、コンテキストを取得するのに失敗したかもしれ、この方法を見つけるカント..しかし、それの罰金、私は他の代替解決策を見つけた
Rucha Bhattさんジョシ

1
私の悪い。shouldShowRequestPermissionRationaleは、コンテキストではなく、アクティビティを通じて利用できます。そのメソッドを呼び出す前に、コンテキストをActivityにキャストすることで私の答えを更新しました。チェックしてみてください:)
muthuraj 2017年

1
これは、によって返される最初のfalse値を回避する唯一の方法でありshouldShowRequestPermissionRationale、ユーザーに送信される要求を優先して保存します。私は同じ考えを持っていて、あなたの答えを見つけました。いい仕事人
MatPag

4

許可のすべてのケースの完全な説明

/**
 *    Case 1: User doesn't have permission
 *    Case 2: User has permission
 *
 *    Case 3: User has never seen the permission Dialog
 *    Case 4: User has denied permission once but he din't clicked on "Never Show again" check box
 *    Case 5: User denied the permission and also clicked on the "Never Show again" check box.
 *    Case 6: User has allowed the permission
 *
 */
public void handlePermission() {
    if (ContextCompat.checkSelfPermission(MainActivity.this,
            Manifest.permission.WRITE_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {
        // This is Case 1. Now we need to check further if permission was shown before or not

        if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)) {

            // This is Case 4.
        } else {
            // This is Case 3. Request for permission here
        }

    } else {
        // This is Case 2. You have permission now you can do anything related to it
    }
}

public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {

    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        // This is Case 2 (Permission is now granted)
    } else {
        // This is Case 1 again as Permission is not granted by user

        //Now further we check if used denied permanently or not
        if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            // case 4 User has denied permission but not permanently

        } else {
            // case 5. Permission denied permanently.
            // You can open Permission setting's page from here now.
        }

    }
}

4

(Kotlinで)任意のパーミッションがリクエストをブロックされているかどうかを判断するのに役立つ関数:

private fun isPermissionBlockedFromAsking(activity: Activity, permission: String): Boolean {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        return ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED
            && !activity.shouldShowRequestPermissionRationale(permission)
            && PreferenceManager.getDefaultSharedPreferences(activity).getBoolean(permission, false)
    }
    return false
}

これを使用するには、最初にアクセス権をリクエストするときに、希望するアクセス権の名前(などandroid.Manifest.permission.READ_PHONE_STATE)を使用して共有設定ブール値を設定する必要がありますtrue


説明:

Build.VERSION.SDK_INT >= Build.VERSION_CODES.M 一部のコードはAPIレベル23以上でのみ実行できるためです。

ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED 許可を得ていないことを確認します。

!activity.shouldShowRequestPermissionRationale(permission)ユーザーがアプリが再度要求することを拒否したかどうかを確認します。この関数の癖のため、次の行も必要です。

PreferenceManager.getDefaultSharedPreferences(activity).getBoolean(permission, false) 前の行はこの情報を返さないので、これは(最初の許可要求で値をtrueに設定するとともに)「Never Asked」と「Never Ask again」の状態を区別するために使用されます。


4

メソッドshouldShowRequestPermissionRationale()を使用して、ユーザーが「再確認しない」オプションを選択し、権限を拒否したかどうかを確認できます。コードの例はたくさんあるので、そのような目的での使用方法を説明したいと思います。名前とその実装によって、実際よりも複雑になると思うからです。

実行時に権限をリクエストするで説明されているとおりに、このメソッドは、「今後表示しない」オプションが表示されている場合はtrueを返し、それ以外の場合はfalseを返します。したがって、最初にダイアログが表示されたときはfalseを返し、2回目以降はtrueを返します。ユーザーがオプションの選択を拒否した場合にのみ、その時点で再びfalseを返します。

このような場合を検出するには、シーケンスfalse-true-falseを検出するか、(より簡単に)ダイアログが表示された最初の時間を追跡するフラグを設定します。その後、そのメソッドはtrueまたはfalseのいずれかを返します。falseを使用すると、オプションが選択されていることを検出できます。


3

この解決策のために私に石を投げないでください。

これは機能しますが、少し「ハッキー」です。

を呼び出すときはrequestPermissions、現在時刻を登録してください。

        mAskedPermissionTime = System.currentTimeMillis();

次に onRequestPermissionsResult

結果が承認されない場合は、時間を再度確認してください。

 if (System.currentTimeMillis() - mAskedPermissionTime < 100)

ユーザーは拒否ボタンをそれほど速くクリックできなかったので、コールバックは瞬時であるため、「もう質問しない」を選択したことがわかります。

自己責任で使用してください。


リクエストされたダイアログが5分間表示されてから拒否された場合はどうなりますか?
サクシャム2018年

次に、それが基本的な要件を満たせない場合の使用法は何ですか?コードがすべての要件を明確に満たしていなければ、受け入れられたハックになる可能性があります。
サクシャム2018年

ええ、これは悪いです。このような自動テスターはおそらくそれよりも速くクリックすることができます:developer.android.com/training/testing/crawler
stackzebra

2

私は、Android Mでパーミッションリクエストの省略形を書きました。このコードは、古いAndroidバージョンへの下位互換性も処理します。

すべての醜いコードは、パーミッションをリクエストするアクティビティにそれ自体をアタッチおよびデタッチするフラグメントに抽出さPermissionRequestManagerれます。次のように使用できます。

new PermissionRequestManager()
        // We need a AppCompatActivity here, if you are not using support libraries you will have to slightly change 
        // the PermissionReuqestManager class
        .withActivity(this)

        // List all permissions you need
        .withPermissions(android.Manifest.permission.CALL_PHONE, android.Manifest.permission.READ_CALENDAR)

        // This Runnable is called whenever the request was successfull
        .withSuccessHandler(new Runnable() {
            @Override
            public void run() {
                // Do something with your permissions!
                // This is called after the user has granted all 
                // permissions, we are one a older platform where 
                // the user does not need to grant permissions 
                // manually, or all permissions are already granted

            }
        })

        // Optional, called when the user did not grant all permissions
        .withFailureHandler(new Runnable() {
            @Override
            public void run() {
                // This is called if the user has rejected one or all of the requested permissions
                L.e(this.getClass().getSimpleName(), "Unable to request permission");

            }
        })

        // After calling this, the user is prompted to grant the rights
        .request();

ご覧くださいhttps : //gist.github.com/crysxd/385b57d74045a8bd67c4110c34ab74aa


2
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
    switch (requestCode) {
        case PERMISSIONS_REQUEST_EXTERNAL_STORAGE: {
            if (grantResults.length > 0) {
                if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                    // Denied
                } else {
                    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
                        // To what you want
                    } else {
                       // Bob never checked click
                    }
                }
            }
        }
    }
}

2

この簡単な許可ライブラリを試してください。それは3つの簡単なステップで許可に関連するすべての操作を処理します。時間を節約できました。権限関連のすべての作業を15分で完了できます。

それは拒否を処理することができ、二度と尋ねないことを処理することができる、それは許可のためにアプリ設定を呼び出すことができる、それは合理的なメッセージを与えることができる、それは拒否メッセージを与えることができる、それは受け入れられた許可のリストを与えることができる、それは拒否されたリストを与えることができる権限など

https://github.com/ParkSangGwon/TedPermission

ステップ1:依存関係を追加する

dependencies {
     compile 'gun0912.ted:tedpermission:2.1.1'
     //check the above link for latest libraries
}

手順2:権限を確認する

TedPermission.with(this)
    .setPermissionListener(permissionlistener)
    .setDeniedMessage("If you reject permission,you can not use this service\n\nPlease turn on permissions at [Setting] > [Permission]")
    .setPermissions(Manifest.permission.READ_CONTACTS, Manifest.permission.ACCESS_FINE_LOCATION)
    .check();

ステップ3:許可応答を処理する

PermissionListener permissionlistener = new PermissionListener() {
    @Override
    public void onPermissionGranted() {
        Toast.makeText(MainActivity.this, "Permission Granted", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onPermissionDenied(ArrayList<String> deniedPermissions) {
        Toast.makeText(MainActivity.this, "Permission Denied\n" + deniedPermissions.toString(), Toast.LENGTH_SHORT).show();
    }
};

すごい。それは私の時間を節約しました
Vigneswaran A 2018

使いやすく、使いやすい
Uray Febri

2

あなたはかなり聞くことができます。

リスナー

interface PermissionListener {
    fun onNeedPermission()
    fun onPermissionPreviouslyDenied(numberDenyPermission: Int)
    fun onPermissionDisabledPermanently(numberDenyPermission: Int)
    fun onPermissionGranted()
}

許可のためのMainClass

class PermissionUtil {

    private val PREFS_FILENAME = "permission"
    private val TAG = "PermissionUtil"

    private fun shouldAskPermission(context: Context, permission: String): Boolean {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val permissionResult = ActivityCompat.checkSelfPermission(context, permission)
            if (permissionResult != PackageManager.PERMISSION_GRANTED) {
                return true
            }
        }
        return false
    }

    fun checkPermission(context: Context, permission: String, listener: PermissionListener) {

        Log.i(TAG, "CheckPermission for $permission")

        if (shouldAskPermission(context, permission)) {

            // Load history permission
            val sharedPreference = context.getSharedPreferences(PREFS_FILENAME, 0)
            val numberShowPermissionDialog = sharedPreference.getInt(permission, 0)

            if (numberShowPermissionDialog == 0) {

                (context as? Activity)?.let {
                    if (ActivityCompat.shouldShowRequestPermissionRationale(it, permission)) {
                        Log.e(TAG, "User has denied permission but not permanently")
                        listener.onPermissionPreviouslyDenied(numberShowPermissionDialog)
                    } else {
                        Log.e(TAG, "Permission denied permanently.")
                        listener.onPermissionDisabledPermanently(numberShowPermissionDialog)
                    }
                } ?: kotlin.run {
                    listener.onNeedPermission()
                }

            } else {
                // Is FirstTime
                listener.onNeedPermission()
            }


            // Save history permission
            sharedPreference.edit().putInt(permission, numberShowPermissionDialog + 1).apply()


        } else {
            listener.onPermissionGranted()
        }

    }
}

この方法で使用

      PermissionUtil().checkPermission(this, Manifest.permission.ACCESS_FINE_LOCATION,
                object : PermissionListener {
                    override fun onNeedPermission() {
                        log("---------------------->onNeedPermission")

//                            ActivityCompat.requestPermissions(this@SplashActivity,
//                                    Array(1) { Manifest.permission.ACCESS_FINE_LOCATION },
//                                    118)

                    }

                    override fun onPermissionPreviouslyDenied(numberDenyPermission: Int) {
                        log("---------------------->onPermissionPreviouslyDenied")
                    }

                    override fun onPermissionDisabledPermanently(numberDenyPermission: Int) {
                        log("---------------------->onPermissionDisabled")
                    }

                    override fun onPermissionGranted() {
                        log("---------------------->onPermissionGranted")
                    }

                })

アクティビティまたはfragmnetでonRequestPermissionsResultをオーバーライドします

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
 if (requestCode == 118) {
        if (permissions[0] == Manifest.permission.ACCESS_FINE_LOCATION && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            getLastLocationInMap()
        }
        }
    }

1

代わりonRequestPermissionsResult()に、次の偽の状態に陥っているときに再度許可を要求すると、PERMISSION_DENIEDとしてコールバックを受け取ります。shouldShowRequestPermissionRationale()

Androidドキュメントから:

システムがユーザーに許可を与えるように要求する場合、ユーザーはシステムにその許可を再度要求しないように指示するオプションがあります。その場合、アプリがrequestPermissions()その許可を再度要求するために使用するときはいつでも、システムはその要求を即座に拒否します。システムがonRequestPermissionsResult()コールバックメソッドを呼び出してを渡します。PERMISSION_DENIEDこれは、ユーザーが明示的にリクエストを再度拒否した場合と同じです。これは、を呼び出したときにrequestPermissions()、ユーザーとの直接の対話が行われたと想定できないことを意味します。


1

if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)methodを使用して、never askがチェックされているかどうかを検出できます 。

詳細については、こちらを確認してください

複数の権限を確認するには、次のコマンドを使用します。

  if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)
                                || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                                || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)
                                || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO)) {
                            showDialogOK("Service Permissions are required for this app",
                                    new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            switch (which) {
                                                case DialogInterface.BUTTON_POSITIVE:
                                                    checkAndRequestPermissions();
                                                    break;
                                                case DialogInterface.BUTTON_NEGATIVE:
                                                    // proceed with logic by disabling the related features or quit the app.
                                                    finish();
                                                    break;
                                            }
                                        }
                                    });
                        }
                        //permission is denied (and never ask again is  checked)
                        //shouldShowRequestPermissionRationale will return false
                        else {
                            explain("You need to give some mandatory permissions to continue. Do you want to go to app settings?");
                            //                            //proceed with logic by disabling the related features or quit the app.
                        }

Explain()メソッド

private void explain(String msg){
        final android.support.v7.app.AlertDialog.Builder dialog = new android.support.v7.app.AlertDialog.Builder(this);
        dialog.setMessage(msg)
                .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface paramDialogInterface, int paramInt) {
                        //  permissionsclass.requestPermission(type,code);
                        startActivity(new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:com.exampledemo.parsaniahardik.marshmallowpermission")));
                    }
                })
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface paramDialogInterface, int paramInt) {
                        finish();
                    }
                });
        dialog.show();
    }

上記のコードはダイアログも表示し、ユーザーにアプリの設定画面にリダイレクトします。チェックした場合、二度と尋ねないボタンを許可した場合、アプリの設定画面にアクセスできます。


1

使用できます

shouldShowRequestPermissionRationale()

内部

onRequestPermissionsResult()

以下の例をご覧ください。

ユーザーがボタンをクリックしたときに権限があるかどうかを確認します。

@Override
public void onClick(View v) {
    if (v.getId() == R.id.appCompatBtn_changeProfileCoverPhoto) {
        if (Build.VERSION.SDK_INT < 23) { // API < 23 don't need to ask permission
            navigateTo(MainActivity.class); // Navigate to activity to change photos
        } else {
            if (ContextCompat.checkSelfPermission(SettingsActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    != PackageManager.PERMISSION_GRANTED) {
                // Permission is not granted yet. Ask for permission...
                requestWriteExternalPermission();
            } else {
                // Permission is already granted, good to go :)
                navigateTo(MainActivity.class);
            }
        } 
    }
}

ユーザーが許可ダイアログボックスに答えると、onRequestPermissionResultに移動します。

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

    if (requestCode == WRITE_EXTERNAL_PERMISSION_REQUEST_CODE) {
        // Case 1. Permission is granted.  
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {  
            if (ContextCompat.checkSelfPermission(SettingsActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    == PackageManager.PERMISSION_GRANTED) {
                // Before navigating, I still check one more time the permission for good practice.
                navigateTo(MainActivity.class);
            }
        } else { // Case 2. Permission was refused
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                // Case 2.1. shouldShowRequest... returns true because the
                // permission was denied before. If it is the first time the app is running we will 
                // end up in this part of the code. Because he need to deny at least once to get 
                // to onRequestPermissionsResult. 
                Snackbar snackbar = Snackbar.make(findViewById(R.id.relLayout_container), R.string.you_must_verify_permissions_to_send_media, Snackbar.LENGTH_LONG);
                snackbar.setAction("VERIFY", new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        ActivityCompat.requestPermissions(SettingsActivity.this
                                , new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}
                                , WRITE_EXTERNAL_PERMISSION_REQUEST_CODE);
                    }
                });
                snackbar.show();
            } else {
                // Case 2.2. Permission was already denied and the user checked "Never ask again". 
                // Navigate user to settings if he choose to allow this time.
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setMessage(R.string.instructions_to_turn_on_storage_permission)
                        .setPositiveButton(getString(R.string.settings), new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                Intent settingsIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                Uri uri = Uri.fromParts("package", getPackageName(), null);
                                settingsIntent.setData(uri);
                                startActivityForResult(settingsIntent, 7);
                            }
                        })
                        .setNegativeButton(getString(R.string.not_now), null);
                Dialog dialog = builder.create();
                dialog.show();
            }
        }
    }

}

0

また、ユーザーが「二度と尋ねない」を選択したかどうかの情報も取得したいと思います。私は醜い旗で「ほぼ解決策」を達成しましたが、その方法を説明する前に、私の動機について説明します。

最初に権限参照機能を提供したいと思います。ユーザーがそれを使用し、権限がない場合、ユーザーは上から1番目のダイアログ、または2番目と3番目の両方を取得します。ユーザーが[今後表示しない]を選択した場合、機能を無効にして別の方法で表示したいと思います。-スピナーテキストエントリによってアクションがトリガーされます。表示されたラベルテキストに「(Permission revoked)」を追加したいと思います。これはユーザーに次のように表示します。「機能はありますが、権限設定が原因で使用できません。」しかし、「二度と尋ねない」が選択されているかどうかを確認できないため、これは可能ではないようです。

私は自分の機能をアクティブな権限チェックで常に有効にすることで、一緒に暮らせるソリューションを見つけました。否定応答の場合、onRequestPermissionsResult()にトーストメッセージを表示していますが、カスタムの根拠ポップアップを表示していない場合に限られます。したがって、ユーザーが「二度と尋ねない」を選択した場合、トーストメッセージのみが表示されます。ユーザーが「二度と尋ねない」を選択することに消極的である場合、3つの通知を続けて行うと非常に苦痛になるため、オペレーティングシステムによるカスタムの根拠と許可要求のポップアップのみが取得され、トーストは取得されません。


0

カメラの動的アクセス許可を実装する必要があります。3つのケースが発生する可能性がある場合:1.許可、2。拒否、3。再度質問しない。

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

    for (String permission : permissions) {
        if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), permission)) {
            //denied
            Log.e("denied", permission);
        } else {
            if (ActivityCompat.checkSelfPermission(getActivity(), permission) == PackageManager.PERMISSION_GRANTED) {
                //allowed
                Log.e("allowed", permission);
            } else {
                //set to never ask again
                Log.e("set to never ask again", permission);
                //do something here.
            }
        }
    }
    if (requestCode != MaterialBarcodeScanner.RC_HANDLE_CAMERA_PERM) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        return;
    }
    if (grantResults.length != 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        mScannerView.setResultHandler(this);
        mScannerView.startCamera(mCameraId);
        mScannerView.setFlash(mFlash);
        mScannerView.setAutoFocus(mAutoFocus);
        return;
    } else {
        //set to never ask again
        Log.e("set to never ask again", permissions[0]);
    }
    DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int id) {
            dialog.cancel();
        }
    };
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    builder.setTitle("Error")
            .setMessage(R.string.no_camera_permission)
            .setPositiveButton(android.R.string.ok, listener)
            .show();


}

private void insertDummyContactWrapper() {
        int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.CAMERA);
        if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.CAMERA},
                    REQUEST_CODE_ASK_PERMISSIONS);
            return;
        }
        mScannerView.setResultHandler(this);
        mScannerView.startCamera(mCameraId);
        mScannerView.setFlash(mFlash);
        mScannerView.setAutoFocus(mAutoFocus);
    }

private int checkSelfPermission(String camera) {
    if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA)
            != PackageManager.PERMISSION_GRANTED) {
        return REQUEST_CODE_ASK_PERMISSIONS;
    } else {
        return REQUEST_NOT_CODE_ASK_PERMISSIONS;
    }
}

0

上記のmVckの回答を拡張すると、次のロジックは、特定の許可リクエストに対して「二度と尋ねない」がチェックされているかどうかを判断します。

bool bStorage = grantResults[0] == Permission.Granted;
bool bNeverAskForStorage =
    !bStorage && (
        _bStorageRationaleBefore == true  && _bStorageRationaleAfter == false ||
        _bStorageRationaleBefore == false && _bStorageRationaleAfter == false
    );

これは下から抜粋されています(完全な例については、この回答を参照してください)

private bool _bStorageRationaleBefore;
private bool _bStorageRationaleAfter;        
private const int ANDROID_PERMISSION_REQUEST_CODE__SDCARD = 2;
//private const int ANDROID_PERMISSION_REQUEST_CODE__CAMERA = 1;
private const int ANDROID_PERMISSION_REQUEST_CODE__NONE = 0;

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
{
    base.OnRequestPermissionsResult(requestCode, permissions, grantResults);

    switch (requestCode)
    {
        case ANDROID_PERMISSION_REQUEST_CODE__SDCARD:               
            _bStorageRationaleAfter = ShouldShowRequestPermissionRationale(Android.Manifest.Permission.WriteExternalStorage);
            bool bStorage = grantResults[0] == Permission.Granted;
            bool bNeverAskForStorage =
                !bStorage && (
                    _bStorageRationaleBefore == true  && _bStorageRationaleAfter == false ||
                    _bStorageRationaleBefore == false && _bStorageRationaleAfter == false
                );      
            break;                
    }
}

private List<string> GetRequiredPermissions(out int requestCode)
{
    // Android v6 requires explicit permission granting from user at runtime for security reasons            
    requestCode = ANDROID_PERMISSION_REQUEST_CODE__NONE; // 0
    List<string> requiredPermissions = new List<string>();

    _bStorageRationaleBefore = ShouldShowRequestPermissionRationale(Android.Manifest.Permission.WriteExternalStorage);
    Permission writeExternalStoragePerm = ApplicationContext.CheckSelfPermission(Android.Manifest.Permission.WriteExternalStorage);
    //if(extStoragePerm == Permission.Denied)
    if (writeExternalStoragePerm != Permission.Granted)
    {
        requestCode |= ANDROID_PERMISSION_REQUEST_CODE__SDCARD;
        requiredPermissions.Add(Android.Manifest.Permission.WriteExternalStorage);
    }

    return requiredPermissions;
}

protected override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);

        // Android v6 requires explicit permission granting from user at runtime for security reasons
        int requestCode;
        List<string> requiredPermissions = GetRequiredPermissions(out requestCode);
        if (requiredPermissions != null && requiredPermissions.Count > 0)
        {
            if (requestCode >= ANDROID_PERMISSION_REQUEST_CODE__SDCARD)                    
            {
                _savedInstanceState = savedInstanceState;
                RequestPermissions(requiredPermissions.ToArray(), requestCode);
                return;
            }
        }
    }            

    OnCreate2(savedInstanceState);
}

0

あなたはアンドロイドの公式文書を読むことができます アプリの許可をリクエストする

または、Githubで人気のあるandroid権限ライブラリをたくさん見つけることができます


2
ライブラリを提案するのは良い答えではありません。少なくとも、問題を解決するためにライブラリを使用する方法を説明してください。
M.プロホロフ

0

質問に正確に答えるために、ユーザーが「二度と尋ねない」を押すとどうなりますか?

オーバーライドされたメソッド/関数

onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray)

grantResult配列は空であることが判明したので、そこで何かを行うことができますか?しかし、ベストプラクティスではありません。

「二度と尋ねない」を処理するには?

READ_EXTERNAL_STORAGE権限が必要なFragmentを使用しています。

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        when {
            isReadPermissionsGranted() -> {

                /**
                 * Permissions has been Granted
                 */

                getDirectories()
            }

            isPermissionDeniedBefore() -> {

                /**
                 * User has denied before, explain why we need the permission and ask again
                 */

                updateUIForDeniedPermissions()
                checkIfPermissionIsGrantedNow()

            }
            else -> {

                /**
                 * Need to ask For Permissions, First Time
                 */

                checkIfPermissionIsGrantedNow()

                /**
                 * If user selects, "Dont Ask Again" it will never ask again! so just update the UI for Denied Permissions
                 */

                updateUIForDeniedPermissions()

            }
        }
    }

他の機能は簡単です。

// Is Read Write Permissions Granted
fun isReadWritePermissionGranted(context: Context): Boolean {
    return (ContextCompat.checkSelfPermission(
        context as Activity,
        Manifest.permission.READ_EXTERNAL_STORAGE
    ) == PackageManager.PERMISSION_GRANTED) and
            (ContextCompat.checkSelfPermission(
                context,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
            ) == PackageManager.PERMISSION_GRANTED)
}

fun isReadPermissionDenied(context: Context) : Boolean {
    return ActivityCompat.shouldShowRequestPermissionRationale(
        context as Activity,
        PermissionsUtils.READ_EXTERNAL_STORAGE_PERMISSIONS)
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.