• 30 hours
  • Medium

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 1/13/20

Configurez les dépendances et permissions dans le Manifest

Log in or subscribe for free to enjoy all this course has to offer!

Lorsque l'on développe une application Android, on peut vouloir exploiter des fonctionnalités qui ne sont pas toujours présentes sur tous les appareils (Ex : usage du gyroscope) ou qui peuvent rentrer dans la vie privée de l'utilisateur (Ex : accès à ses contacts). Dans ces cas là, on devra annoncer, dans le Manifest des permissions ou des dépendances.

Permissions

Parmi les interactions que l'on peut avoir avec le système, certaines peuvent nécessiter de demander explicitement l'autorisation à l'utilisateur. Android définit 2 niveaux de criticité des permissions :

  • Normal : cela correspond à une demande d'accès à des ressources externes à l'application mais sans grand danger pour la sécurité de la plateforme ou la vie privée de l'utilisateur (ex : l'accès au vibreur). La plateforme pourra prendre l'initiative de donner ces permissions aux applications sans notifier l'utilisateur.

  • Dangereux : cela correspond à une demande d'accès à des ressources externes à l'application pour lesquelles l'utilisateur pourrait vouloir contrôler l'accès (Ex : contacts ou rythme cardiaque). L'utilisateur sera nécessairement questionné.

Avant Android 6, les permissions étaient présentées avant l'installation de l'application et l'utilisateur devait accepter ou refuser les permissions en bloc.

À partir d'Android 6, il devient nécessaire d'en faire la demande à l'utilisateur durant l'exécution, au moment de l'accès. L'utilisateur pourra ainsi accepter l'accès aux contacts pour une application de messagerie instantanée, mais refuser la diffusion de son rythme cardiaque par cette même application.

La conséquence de cette évolution est que faire une action nécessitant une permission devient un peu complexe. Il y a maintenant deux étapes obligatoires :

  1. Annoncer la permission dans le manifest :

    <manifest ...>
    <uses-permission android:name="android.permission...."></uses-permission>
    <application ... ></application>
    </manifest>
  2. Avant d'utiliser la permission, vérifier que l'on a la permission. Si on ne l'a pas, alors demander une fois à l'utilisateur s'il ne voudrait pas nous la donner. S'il répond oui, alors continuer le traitement. Mais cela doit être fait de manière asynchrone, pour ne pas bloquer le device. On peut suivre le schéma général suivant :

    final static int MY_PERMISSION_REQUEST_CODE=1; // valeur arbitraire
    final static String MY_PERMISSION_NAME=Manifest.permission./*...*/;
    public void makeActionWithPermission(){
    // A-t-on la permission de le faire ?
    if (ActivityCompat.checkSelfPermission(MainActivity.this, MY_PERMISSION_NAME) != PackageManager.PERMISSION_GRANTED) {
    // Si "non", alors il faut demander la ou les permissions
    ActivityCompat.requestPermissions(MainActivity.this,
    new String[]{MY_PERMISSION_NAME},
    MY_PERMISSION_REQUEST_CODE);
    // Finir ici le traitement : ne pas bloquer.
    // On attend la réponse via onRequestPermissionsResult
    } else {
    Toast.makeText(MainActivity.this,"On a la permission : on fait.", Toast.LENGTH_LONG).show();
    }
    }
    @Override
    public void onRequestPermissionsResult(int requestCode,
    String permissions[], int[] grantResults) {
    switch (requestCode) {
    case MY_PERMISSION_REQUEST_CODE: {
    if (grantResults.length > 0 &&
    grantResults[0] == PackageManager.PERMISSION_GRANTED) {
    Toast.makeText(MainActivity.this,"Réponse de l'utilisateur : oui", Toast.LENGTH_LONG).show();
    // On relance la méthode de réalisation de l'action. Cette fois, on a l'autorisation.
    makeActionWithPermission();
    } else {
    Toast.makeText(MainActivity.this,"Réponse de l'utilisateur : non", Toast.LENGTH_LONG).show();
    // On abandonne notre super fonctionnalité.
    }
    return;
    }
    }
    }

La complexité de ce code est notamment liée au fait que plusieurs actions de votre application peuvent nécessiter des permissions. Toutes ces demandes aboutiront à l'appel de la fonction de callbackonRequestPermissionsResult. Cette fonction devra donc être capable de savoir qui a fait une demande pour savoir analyser la réponse de l'utilisateur (notamment si des permissions différentes sont demandées). Pour ce faire, lors de l'appel à requestPermissions, on doit fournir en troisième paramètre un identifiant (Ici : MY_PERMISSION_REQUEST_CODE) permettant d'identifier l'action en cours et de la continuer si les permissions sont accordées.

C'est donc le rôle du switch présent dans onRequestPermissionsResult  de tester l'action qui était en cours pour savoir quelle suite donner à la demande d'autorisation.

Notez que, si la permission n'est pas accordée (ligne 7), alors c'est potentiellement parce que l'on a déjà fait la demande à l'utilisateur. Il est donc conseillé de commencer par vérifier si c'était le cas (via un appel à shouldShowRequestPermissionRationale). Et si oui, alors soit ne rien faire (abandonner la fonctionnalité), soit tenter de le convaincre de vous donner l'autorisation. Si non, alors tout simplement, demander l'autorisation. 

if (ActivityCompat.shouldShowRequestPermissionRationale(
this,
MY_PERMISSION)) {
// L'utilisateur a refusé par le passé.
// Soit j'abandonne, soit je tente de justifier la demande.
} else {
// On ne l'a jamais demandé à l'utilisateur. Dans le doute, on
// demande simplement, sans justifier outre mesure.
}

Dépendances <uses-feature >

Si notre application utilise un périphérique qui n'est pas toujours présent sur tous les appareils (Ex : podomètre), alors on peut annoncer cette dépendance dans le Manifest. On pourra également préciser si son absence rend l'application inutilisable. Cela permettra aux utilisateurs de ne pas voir, dans le store, les applications qui ne sont pas compatibles avec leur appareil.

Pour annoncer une dépendance, on insère la balise <uses-feature>  dans le manifest, avant le bloc<application>. En paramètre, on précise nécessairement le nom de la dépendance, tandis que le champs optionnel required  permet de dire si l'absence de cette dépendance doit interdire l'installation ou pas. 

Exemple :

<manifest ...>
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true" ></uses-feature>
<application ... ></application>
</manifest>

Dans certains cas, une permission peut avoir une dépendance sur le matériel nécessaire. Par exemple, demander une géolocalisation fine devrait nécessiter la présence d'un GPS. Cette implication était faite dans les versions d'Android inférieures à 5. À partir de la version 5 (API 21), il est devenu nécessaire de demander la présence du matériel nécessaire à nos applications. Ainsi, pour faire une géolocalisation gros-grain, on devra annoncer :

<manifest ... >
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-feature android:name="android.hardware.location.network" />
</manifest>

Tandis que pour permettre une localisation grain fin, on devra annoncer :

<manifest ... >
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-feature android:name="android.hardware.location.gps" />
</manifest>

Enfin, si l'application peut faire les deux, mais qu'il est indispensable que cela soit faisable, alors on pourra annoncer (la permission fine inclue la permission gros grain) :

<manifest ... >
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-feature android:name="android.hardware.location.network" android:required="true"/>
<uses-feature android:name="android.hardware.location.gps" android:required="false"/>
</manifest>

Example of certificate of achievement
Example of certificate of achievement