Documentation pour les développeurs Android donne cet exemple de demande d'autorisations au moment de l'exécution:
// 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.
}
}
Qu'est-ce que "MY_PERMISSIONS_REQUEST_READ_CONTACTS" dans cet exemple? Il dit que c'est une constante int définie par l'application, mais cela signifie-t-il que je devrais créer un Constants.Java et déclarer un int statique public? Quelle devrait être la valeur?
Dans d'autres exemples, je vois des gens utiliser 1 ici, ou 0 ou 0xFFEEDDCC, mais je ne trouve pas d'explication de ce que c'est. Quelqu'un peut-il m'expliquer ce qui doit être fait ici et pourquoi? (Dans mon cas, je dois m'assurer que l'application est autorisée à accéder à un emplacement précis)
La documentation ActivityCompat indique "Code de demande spécifique à l'application à associer à un résultat signalé à onRequestPermissionsResult"? Cela ne m'aide pas.
Qu'est-ce que "MY_PERMISSIONS_REQUEST_READ_CONTACTS" dans cet exemple?
Il s'agit d'une int
, pour lier un appel requestPermissions()
particulier au rappel onRequestPermissionsResult()
correspondant.
Sous les couvertures, requestPermissions()
utilise startActivityForResult()
; cette int
remplit le même rôle que dans startActivityForResult()
.
cela signifie-t-il que je devrais créer un Constants.Java et déclarer un int statique public?
Je voudrais juste en faire un private static final int
dans l'activité. Mais, vous pouvez le déclarer où vous voulez.
Quelle devrait être la valeur?
Il me semble me rappeler qu’il doit être inférieur à 0x8000000, mais sinon, cela peut être ce que vous voulez. La valeur que vous utilisez pour chaque appel requestPermissions()
dans une activité doit avoir une valeur int
distincte, mais les nombres réels importent peu.
Si votre activité n'a qu'un seul appel requestPermissions()
, la valeur int
n'a pas d'importance. Mais de nombreuses applications auront plusieurs appels requestPermissions()
dans une activité. Dans ce cas, le développeur peut avoir besoin de savoir, dans onRequestPermissionsResult()
, à quelle requête correspond le résultat.
Regardez un peu plus loin dans la documentation sous "Gérer la réponse à la demande de permission" et vous verrez son objectif.
Une méthode de rappel appelée onRequestPermissionsResult
est renvoyée avec le même code qu'un paramètre afin que vous sachiez quelle autorisation était demandée/accordée:
@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
}
}
Étant donné que la constante est utilisée par vous seul, vous pouvez lui attribuer la valeur de votre choix sous la forme public static final int
. Chaque autorisation demandée nécessite sa propre constante.
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);
}
J'ai parcouru toutes les réponses, mais je n'ai pas trouvé la réponse exacte, voici donc un exemple que j'ai écrit et qui fonctionne parfaitement, même si l'utilisateur clique sur Ne plus demander case à cocher.
Créez une méthode qui sera appelée lorsque vous souhaitez demander une autorisation d'exécution telle que readContacts()
ou vous pouvez également avoir openCamera()
comme indiqué ci-dessous:
private void readContacts() {
if (!askContactsPermission()) {
return;
} else {
queryContacts();
} }
Maintenant, nous devons créer askContactsPermission()
, vous pouvez également le nommer comme suit: askCameraPermission()
ou quelle que soit l'autorisation que vous allez demander.
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;
}
Avant d'écrire cette fonction, assurez-vous d'avoir défini la variable d'instance ci-dessous, comme indiqué:
private View parentLayout;
private boolean contactPermissionNotGiven;;
/**
* Id to identity READ_CONTACTS permission request.
*/
private static final int REQUEST_READ_CONTACTS = 0;
Dernière étape pour remplacer la méthode onRequestPermissionsResult
comme indiqué ci-dessous:
/**
* 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();
}
}
}
Nous en avons terminé avec les autorisations RunTime. L'addon est la openPermissionSettingDialog()
qui ouvre simplement l'écran Paramètre si l'utilisateur a désactivé l'autorisation en permanence en cliquant sur Ne plus demander case à cocher. ci-dessous est la méthode:
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);
}
Qu'est-ce que nous avons manqué? 1. Définir les chaînes utilisées dans 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>
Initialisation de la variable parentLayout
dans la méthode onCreate
parentLayout = findViewById (R.id.content);
Définir l'autorisation requise dans AndroidManifest.xml
<uses-permission Android:name="Android.permission.READ_CONTACTS" />
La méthode queryContacts
, en fonction de vos besoins ou de l'autorisation d'exécution, vous pouvez appeler votre méthode avant laquelle la permission
était nécessaire. dans mon cas, j'utilise simplement le chargeur pour récupérer le contact, comme indiqué ci-dessous:
private void queryContacts() {
getLoaderManager().initLoader(0, null, this);}
Cela fonctionne très bien le codage :)