web-dev-qa-db-ger.com

Android-Laufzeitberechtigungen - wie implementiert werden soll

Android Developer-Dokumentation zeigt dieses Beispiel für das Anfordern von Berechtigungen zur Laufzeit:

// 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.
    }
}

Was ist "MY_PERMISSIONS_REQUEST_READ_CONTACTS" in diesem Beispiel? Es sagt, dass es eine App-definierte int-Konstante ist, aber bedeutet das, ich sollte eine Constants.Java erstellen und ein öffentliches statisches int deklarieren? Was soll der Wert sein?

In anderen Beispielen sehe ich, dass Leute hier 1 verwenden, oder 0 oder 0xFFEEDDCC, aber ich kann keine Erklärung finden, was es ist. Kann mir jemand erklären, was hier zu gehen ist und warum? (In meinem Fall muss ich sicherstellen, dass die App berechtigt ist, auf den genauen Standort zuzugreifen.)

In der Dokumentation zu ActivityCompat heißt es: "Anwendungsspezifischer Anforderungscode, der mit einem an onRequestPermissionsResult gemeldeten Ergebnis übereinstimmt"? Das hilft mir nicht.

16
Andrew Torr

Was ist "MY_PERMISSIONS_REQUEST_READ_CONTACTS" in diesem Beispiel?

Es ist eine int, um einen bestimmten requestPermissions()-Aufruf an den entsprechenden onRequestPermissionsResult()-Callback zu binden.

Unter den Abdeckungen verwendet requestPermissions()startActivityForResult(); Dieses int hat dieselbe Funktion wie in startActivityForResult().

heißt das, ich sollte eine Konstanten.Java erstellen und ein öffentliches statisches int deklarieren?

Ich würde es einfach zu einem private static final int in der Aktivität machen. Aber Sie können es deklarieren, wo immer Sie möchten.

Was soll der Wert sein?

Ich denke daran, dass es unter 0x8000000 liegen muss, aber ansonsten kann es sein, was Sie wollen. Der Wert, den Sie für jeden requestPermissions()-Aufruf in einer Aktivität verwenden, sollte ein eindeutiges int erhalten, die tatsächlichen Zahlen spielen jedoch keine Rolle.

Wenn Ihre Aktivität nur einen requestPermissions()-Aufruf hat, spielt der int-Wert keine Rolle. Viele Apps haben jedoch mehrere requestPermissions()-Aufrufe in einer Aktivität. In diesem Fall muss der Entwickler in onRequestPermissionsResult() möglicherweise wissen, für welche Anforderung dies das Ergebnis ist.

18
CommonsWare

Schauen Sie in der Dokumentation unter "Behandeln der Antwortanforderung für Berechtigungen" nach, und sehen Sie den Zweck.

Eine Callback-Methode mit dem Namen onRequestPermissionsResult wird denselben Code zurückgesendet wie ein Parameter, damit Sie wissen, welche Berechtigung angefordert/erteilt wurde:

@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
    }
}

Da die Konstante nur von Ihnen verwendet wird, können Sie als public static final int einen beliebigen Wert angeben. Jede angeforderte Berechtigung benötigt eine eigene Konstante.

2
George Mulligan
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

Ich habe alle Antworten durchgesehen, aber meine exakte Antwort nicht erfüllt, so ist hier ein Beispiel, das ich geschrieben habe und perfekt funktioniert, sogar der Benutzer klickt auf das Kontrollkästchen Nicht mehr fragen .

  1. Erstellen Sie eine Methode, die aufgerufen wird, wenn Sie nach einer Laufzeitberechtigung wie readContacts() fragen möchten, oder Sie können openCamera() wie unten gezeigt verwenden:

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

Jetzt müssen wir askContactsPermission() machen, Sie können es auch als askCameraPermission() oder wie auch immer für eine Erlaubnis nennen, um die Sie bitten werden.

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

Bevor Sie diese Funktion schreiben, stellen Sie sicher, dass Sie die folgende Instanzvariable wie folgt definiert haben:

    private View parentLayout;
    private boolean contactPermissionNotGiven;;


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

Nun den letzten Schritt, um die onRequestPermissionsResult-Methode wie folgt zu überschreiben:

/**
 * 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();
        }
    }
}

Hier sind wir mit den RunTime-Berechtigungen fertig, das Addon ist das openPermissionSettingDialog(), das einfach den Einstellungsbildschirm öffnet, wenn der Benutzer die Berechtigung dauerhaft deaktiviert hat, indem er auf Nicht mehr fragen Kontrollkästchen klickt. Unten ist die Methode:

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

Was haben wir vermisst? 1. Definieren der verwendeten Zeichenfolgen in 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. Die Variable parentLayout innerhalb der onCreate-Methode wird initialisiert

    parentLayout = findViewById (R.id.content);

  2. Definieren der erforderlichen Berechtigung in AndroidManifest.xml

<uses-permission Android:name="Android.permission.READ_CONTACTS" />

  1. Mit der queryContacts-Methode können Sie je nach Bedarf oder Laufzeitberechtigung Ihre Methode aufrufen, vor der permission benötigt wurde. In meinem Fall verwende ich einfach den Lader, um den Kontakt wie folgt abzurufen:

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

Das funktioniert super glücklich Codierung :) 

0
HAXM