web-dev-qa-db-ja.com

Androidランタイム許可-実装方法

Android Developer Documentation は、実行時に許可を要求するこの例を示します。

// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
            Manifest.permission.READ_CONTACTS)
    != PackageManager.PERMISSION_GRANTED) {

    // Should we show an explanation?
    if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
            Manifest.permission.READ_CONTACTS)) {

        // Show an expanation to the user *asynchronously* -- don't block
        // this thread waiting for the user's response! After the user
        // sees the explanation, try again to request the permission.

    } else {

        // No explanation needed, we can request the permission.

        ActivityCompat.requestPermissions(thisActivity,
                new String[]{Manifest.permission.READ_CONTACTS},
                MY_PERMISSIONS_REQUEST_READ_CONTACTS);

        // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
        // app-defined int constant. The callback method gets the
        // result of the request.
    }
}

この例の「MY_PERMISSIONS_REQUEST_READ_CONTACTS」とは何ですか?アプリ定義のint定数であると書かれていますが、Constants.Javaを作成してpublic static intを宣言する必要があるということですか?値はどうあるべきですか?

他の例では、ここで1、または0または0xFFEEDDCCを使用している人がいますが、それが何であるかの説明が見つかりません。誰かが私にここに行く必要があるものとその理由を説明できますか? (私の場合、アプリに細かい位置情報へのアクセス許可があることを確認する必要があります)

ActivityCompatのドキュメントには、「onRequestPermissionsResultに報告された結果と一致するアプリケーション固有の要求コード」と書かれていますか?これは私を助けません。

18
Andrew Torr

この例の「MY_PERMISSIONS_REQUEST_READ_CONTACTS」とは何ですか?

特定のrequestPermissions()呼び出しを対応するonRequestPermissionsResult()コールバックに結び付けるのは、intです。

内部では、requestPermissions()startActivityForResult()を使用します。このintは、startActivityForResult()と同じ役割を果たします。

つまり、Constants.Javaを作成してpublic static intを宣言する必要があるということですか?

アクティビティで_private static final int_にするだけです。しかし、どこでも好きな場所で宣言できます。

値はどうあるべきですか?

0x8000000未満にする必要があることを思い出すようですが、それ以外の場合は何でも構いません。アクティビティの各requestPermissions()呼び出しに使用する値は、個別のintを取得する必要がありますが、実際の数値は重要ではありません。

アクティビティにrequestPermissions()呼び出しが1つしかない場合、int値は実際には重要ではありません。ただし、多くのアプリでは、アクティビティにいくつかのrequestPermissions()呼び出しがあります。その場合、開発者はonRequestPermissionsResult()で、これがどのリクエストであるかを知る必要があるかもしれません。

21
CommonsWare

「アクセス許可要求の応答を処理する」の下のドキュメントを少し下に見ると、その目的がわかります。

onRequestPermissionsResultと呼ばれるコールバックメソッドがパラメーターと同じコードを送り返すため、どの許可が要求/許可されたかがわかります。

@Override
public void onRequestPermissionsResult(int requestCode,
        String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, yay! Do the
                // contacts-related task you need to do.

            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request
    }
}

定数はあなただけが使用するので、public static final intとして好きな値を与えることができます。要求される各許可には、独自の定数が必要です。

2
George Mulligan

私はすべての答えを試しましたが、必要な正確な答えを満たしていないので、ここに私が書いた例があり、ユーザーが二度と聞かないチェックボックスをクリックしても完全に動作します。

  1. 以下に示すように、readContacts()のようなランタイム許可を要求したい場合に呼び出されるメソッドを作成するか、openCamera()を持つこともできます。

    _private void readContacts() {
        if (!askContactsPermission()) {
            return;
        } else {
            queryContacts();
        } }
    _

ここでaskContactsPermission()を作成する必要がありますが、askCameraPermission()などの名前を付けることもできます。

_    private boolean askContactsPermission() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        return true;
    }
    if (checkSelfPermission(READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
        return true;
    }
    if (shouldShowRequestPermissionRationale(READ_CONTACTS)) {
        Snackbar.make(parentLayout, R.string.permission_rationale, Snackbar.LENGTH_INDEFINITE)
                .setAction(Android.R.string.ok, new View.OnClickListener() {
                    @Override
                    @TargetApi(Build.VERSION_CODES.M)
                    public void onClick(View v) {
                        requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
                    }
                }).show();
    } else if (contactPermissionNotGiven) {
        openPermissionSettingDialog();
    } else {
        requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
        contactPermissionNotGiven = true;

    }
    return false;
}
_

この関数を記述する前に、次のようにインスタンス変数が定義されていることを確認してください。

_    private View parentLayout;
    private boolean contactPermissionNotGiven;;


/**
 * Id to identity READ_CONTACTS permission request.
 */
private static final int REQUEST_READ_CONTACTS = 0;
_

次に示すonRequestPermissionsResultメソッドをオーバーライドする最後の手順:

_/**
 * Callback received when a permissions request has been completed.
 */
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                       @NonNull int[] grantResults) {
    if (requestCode == REQUEST_READ_CONTACTS) {
        if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            queryContacts();
        }
    }
}
_

ここで、RunTimeの許可を取得しました。アドオンはopenPermissionSettingDialog()で、ユーザーが再度尋ねないでくださいチェックボックスをクリックして許可を永久に無効にした場合に、単に設定画面を開きます。メソッドは次のとおりです。

_    private void openPermissionSettingDialog() {
    String message = getString(R.string.message_permission_disabled);
    AlertDialog alertDialog =
            new AlertDialog.Builder(MainActivity.this, AlertDialog.THEME_DEVICE_DEFAULT_LIGHT)
                    .setMessage(message)
                    .setPositiveButton(getString(Android.R.string.ok),
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    Intent intent = new Intent();
                                    intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                    Uri uri = Uri.fromParts("package", getPackageName(), null);
                                    intent.setData(uri);
                                    startActivity(intent);
                                    dialog.cancel();
                                }
                            }).show();
    alertDialog.setCanceledOnTouchOutside(true);
}
_

私たちが見逃したものは? 1. _strings.xml_で使用される文字列を定義する

_<string name="permission_rationale">"Contacts permissions are needed to display Contacts."</string>
    <string name="message_permission_disabled">You have disabled the permissions permanently,
        To enable the permissions please go to Settings -> Permissions and enable the required Permissions,
        pressing OK you will be navigated to Settings screen</string>
_
  1. parentLayoutメソッド内のonCreate変数の初期化

    parentLayout = findViewById(R.id.content);

  2. _AndroidManifest.xml_で必要な許可を定義する

_<uses-permission Android:name="Android.permission.READ_CONTACTS" />
_
  1. queryContactsメソッドは、必要性またはランタイム許可に基づいて、permissionが必要になる前にメソッドを呼び出すことができます。私の場合、次のようにローダーを使用して連絡先を取得するだけです。

    _private void queryContacts() {
    getLoaderManager().initLoader(0, null, this);}
    _

これは素晴らしい幸せなコーディングに役立ちます:)

1
HAXM
public class SplashActivity extends RuntimePermissionsActivity {


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_splash);

    SplashActivity.super.requestAppPermissions(new
                    String[]{Android.Manifest.permission.READ_PHONE_STATE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    Manifest.permission.READ_EXTERNAL_STORAGE}, R.string.app_name
            , 20);

}

@Override
public void onPermissionsGranted(int requestCode) {


    try {
        TelephonyManager tele = (TelephonyManager) getApplicationContext()
                .getSystemService(Context.TELEPHONY_SERVICE);

        String imei =tele.getDeviceId()
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public abstract class RuntimePermissionsActivity extends AppCompatActivity {
private SparseIntArray mErrorString;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mErrorString = new SparseIntArray();
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    int permissionCheck = PackageManager.PERMISSION_GRANTED;
    for (int permission : grantResults) {
        permissionCheck = permissionCheck + permission;
    }
    if ((grantResults.length > 0) && permissionCheck == PackageManager.PERMISSION_GRANTED) {
        onPermissionsGranted(requestCode);
    } else {

        finish();

    }
}

public void requestAppPermissions(final String[] requestedPermissions,
                                  final int stringId, final int requestCode) {
    mErrorString.put(requestCode, stringId);
    int permissionCheck = PackageManager.PERMISSION_GRANTED;
    boolean shouldShowRequestPermissionRationale = false;
    for (String permission : requestedPermissions) {
        permissionCheck = permissionCheck + ContextCompat.checkSelfPermission(this, permission);
        shouldShowRequestPermissionRationale = shouldShowRequestPermissionRationale || ActivityCompat.shouldShowRequestPermissionRationale(this, permission);
    }
    if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
        if (shouldShowRequestPermissionRationale) {
            ActivityCompat.requestPermissions(RuntimePermissionsActivity.this, requestedPermissions, requestCode);
            /*Snackbar.make(findViewById(Android.R.id.content), stringId,
                    Snackbar.LENGTH_INDEFINITE).setAction("GRANT",
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            ActivityCompat.requestPermissions(RuntimePermissionsActivity.this, requestedPermissions, requestCode);
                        }
                    }).show();*/
        } else {
            ActivityCompat.requestPermissions(this, requestedPermissions, requestCode);
        }
    } else {
        onPermissionsGranted(requestCode);
    }
}

public abstract void onPermissionsGranted(int requestCode);

}

0
Hardip