image/svg+xml $ $ ing$ ing$ ces$ ces$ Res Res ea ea Res->ea ou ou Res->ou r r ea->r ch ch ea->ch r->ces$ r->ch ch->$ ch->ing$ T T T->ea ou->r

Les différents types de permissions

Demande de permission

Un composant nécessitant une permission la demande dans le manifeste de l'application : <uses-permission android:name="nom.de.la.permission" /> :

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="fr.upem.coursand">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.FLASHLIGHT" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.SEND_SMS" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.READ_CALL_LOG" />
    <uses-permission android:name="android.permission.READ_SMS" />
    <uses-permission android:name="android.permission.READ_CALENDAR" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        
        <!-- ... -->
        
    </application>

</manifest>

Exemple de code pour une activité nécessitant une permission dangereuse :

package fr.upem.coursand.permission;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.pm.PackageManager;
import android.os.Bundle;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import java.util.HashMap;
import java.util.Map;

/** Template for an activity that needs to acquire a dangerous permission */
public class RequiringPermissionActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
    }

    /** Store here the permission requests with the associated onSuccess and onFailure runnables */
    private Map<Integer, Runnable[]> permissionRequests = new HashMap<>();
    private int nextPermissionRequestCode = 1;

    /** Run code that requires a prior permission grant 
     *  @param permissionName name of the permission to claim
     *  @param rationale message to display to explain to the user why this permission must be used 
     * 	@param onFailure code to execute if the permission is refused
     *  @param onSuccess code to execute if the permission is granted 
     */
    protected void runWithPermission(String permissionName, String rationale, Runnable onFailure, Runnable onSuccess)
    {
		// Is the permission already granted?
        if (ContextCompat.checkSelfPermission(this, permissionName) != PackageManager.PERMISSION_GRANTED)
        {
			// The permission is not granted yet
            // Should we show an explanation?
            if (rationale != null && ActivityCompat.shouldShowRequestPermissionRationale(this, permissionName))
            {
                // show an explanation with a dialog
                AlertDialog alertDialog = new AlertDialog.Builder(this).create();
                alertDialog.setTitle("Permission information");
                alertDialog.setMessage(rationale);
                alertDialog.setIcon(android.R.drawable.ic_dialog_info);
                // if ok is pressed rerun the method (but not showing now the rationale)
                alertDialog.setButton("OK", ((dialogInterface, i) -> runWithPermission(permissionName, null, onFailure, onSuccess)));
                alertDialog.show();
            } else
            {
                int code = nextPermissionRequestCode++; // use an unique id for the permission request
                permissionRequests.put(code, new Runnable[]{onFailure, onSuccess});
                // request asynchronously the permission
                ActivityCompat.requestPermissions(this, new String[]{permissionName}, code);
            }
        } else
            onSuccess.run(); // the permission has already been given already given
    }

	/** This method is called when the user has answered to the permission request */
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
    {
        Runnable[] runnables = permissionRequests.get(requestCode);
        if (runnables != null)
        {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
                runnables[1].run(); // run onSuccess since the permission has been granted
            else
                runnables[0].run(); // permission not granted
        }
    }
}

Création de permissions nouvelles (utile pour un ContentProvider)

Voici un exemple pour donner l'accès en lecture/écriture à un ContentProvider :

 <permission android:name="fr.upemlv.gpslog.GPS_TRACE_READ"
        android:label="@string/perm_label_GPSTraceRead"
        android:description="@string/perm_desc_GPSTraceRead"
        android:permissionGroup="android.permission-group.PESONAL_INFO"
        android:protectionLevel="dangerous" />

 <permission android:name="fr.upemlv.gpslog.GPS_TRACE_WRITE"
        android:label="@string/perm_label_GPSTraceWrite"
        android:description="@string/perm_desc_GPSTraceWrite"
        android:permissionGroup="android.permission-group.PESONAL_INFO"
        android:protectionLevel="dangerous" />

Remarque : pour être accessible d'une autre application, le ContentProvider
doit également posséder la propriété android:exported="true"

Protection d'un composant par une permission

<provider ...>
	<path-permission android:path="string"
                 android:pathPrefix="string"
                 android:pathPattern="string"
                 android:permission="string"
                 android:readPermission="string"
                 android:writePermission="string" />
</provider>

Permissions temporaires pour l'accès aux données

Transmission d'Intent avec permission temporaire d'accès :

Uri uri = Uri.parse("content://fr.upemlv.gpslogger.provider/log/" + id);
Intent intent = new Intent();
intent.setAction(MAP_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setData(uri);
startActivity(intent) ;

Accord/révocation de permissions (méthodes de Context) :

public void grantUriPermission(String toPackage, Uri uri, int modeFlags)
public void revokeUriPermission(Uri uri, int modeFlags) 

Révocation de permissions

Coopération malveillante inter-applicative