web-dev-qa-db-fra.com

Attendre l'autorisation de l'utilisateur

Je construis une application qui échantillonne le GPS au démarrage de… .. Comme vous le savez probablement, des autorisations sont demandées pendant l'exécution à partir d'Android M et supérieur.

Donc, dans mon cas, je commence par vérifier si des autorisations sont nécessaires, comme ceci:

private void permissionForAndroidM()
{
    if (Build.VERSION.SDK_INT > 22) {
        String[] allPermissionNeeded = {
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.ACCESS_COARSE_LOCATION,
                Manifest.permission.CAMERA,
                Manifest.permission.RECORD_AUDIO};

        List<String> permissionNeeded = new ArrayList<>();
        for (String permission : allPermissionNeeded)
            if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED)
                permissionNeeded.add(permission);
        if (permissionNeeded.size() > 0) {
            requestPermissions(permissionNeeded.toArray(new String[0]), 0);
        }
    }
}

mais Android continue à exécuter le code et à demander des données GPS (= plantage, car l'utilisateur n'a pas accepté la demande d'autorisation).

Je trouve de nombreuses solutions pour attendre les entrées de l'utilisateur (comme utiliser DialogInterface.OnClickListener, link , mais cela ne peut pas être mis en œuvre dans ce cas, car je ne crée pas le dialogue).

En bout de ligne, la question: comment puis-je attendre la réponse de l'utilisateur à partir de la boîte de dialogue d'autorisation Android? 

15
AsfK

Vous pouvez gérer la méthode de substitution de réponse de l'utilisateur

public void onRequestPermissionsResult(
    int requestCode,
    String[] permissions,
    int[] grantResults
)

de votre activité.

13
Valentin Yuryev

Android continue à exécuter le code et à demander des données GPS (= plantage, car l'utilisateur n'a pas accepté la demande d'autorisation).

Comme beaucoup de choses dans Android, requestPermissions() est asynchrone. L'utilisateur n'a même pas été invité à entrer les autorisations au moment du retour de cette méthode.

Comment puis-je attendre la réponse de l'utilisateur à partir de la boîte de dialogue d'autorisation Android?

Vous pas.

Si vous trouvez que vous avez déjà la permission, vous faites votre travail. Si vous constatez que vous devez demander une autorisation, vous retardez l'exécution de ce travail jusqu'à l'obtention de l'autorisation, dans onRequestPermissionsResult().

15
CommonsWare

Je l'ai travaillé de la manière suivante:

1- Création d'un assistant Boolean pour vérifier les autorisations accordées:

public class UtilPermissions {
    public static boolean hasPermissions(Context context, String... allPermissionNeeded)
    {
        if (Android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
                && context != null && allPermissionNeeded != null) 
            for (String permission : allPermissionNeeded) 
                if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED)
                     return false;
        return true;
    }
}

2- Créer un écran Splash en tant que:

public class Splash extends Activity {
    private static final int PERMISSION_ALL = 0;
    private Handler h;
    private Runnable r;
  /*  
    SharedPreferences mPrefs;
    final String settingScreenShownPref = "settingScreenShown";
    final String versionCheckedPref = "versionChecked";
  */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        h = new Handler();
        r = new Runnable() {
            @Override
            public void run() {
                Toast.makeText(Splash.this, "Runnable started", Toast.LENGTH_SHORT).show();

  /*          // (OPTIONAL) these lines to check if the `First run` ativity is required
                int versionCode = BuildConfig.VERSION_CODE;
                String versionName = BuildConfig.VERSION_NAME;

                mPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
                SharedPreferences.Editor editor = mPrefs.edit();

                Boolean settingScreenShown = mPrefs.getBoolean(settingScreenShownPref, false);
                int savedVersionCode = mPrefs.getInt(versionCheckedPref, 1);

                if (!settingScreenShown || savedVersionCode != versionCode) {
                    startActivity(new Intent(Splash.this, FirstRun.class));
                    editor.putBoolean(settingScreenShownPref, true);
                    editor.putInt(versionCheckedPref, versionCode);
                    editor.commit();
                }
                else
  */
                startActivity(new Intent(Splash.this, MainActivity.class));
                finish();    
            }
        };

        String[] PERMISSIONS = {
                READ_PHONE_STATE,
                MODIFY_AUDIO_SETTINGS,
                ACCESS_FINE_LOCATION,
                READ_SMS
        };

        if(!UtilPermissions.hasPermissions(this, PERMISSIONS)){
            ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
        }
        else
            h.postDelayed(r, 1500);
    }

  // Put the below OnRequestPermissionsResult code here
}

3- Créé la OnRequestPermissionsResult comme ci-dessous:

@Override
public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {

    int index = 0;
    Map<String, Integer> PermissionsMap = new HashMap<String, Integer>();
    for (String permission : permissions){
        PermissionsMap.put(permission, grantResults[index]);
        index++;
    }

    if((PermissionsMap.get(ACCESS_FINE_LOCATION) != 0)
            || PermissionsMap.get(READ_SMS) != 0){
        Toast.makeText(this, "Location and SMS permissions are a must", Toast.LENGTH_SHORT).show();
        finish();
    }
    else
    {
        h.postDelayed(r, 1500);
    }
}

4- Défini l'écran Splash comme Launcher dans le AndroidManifest.xml comme:

<activity
    Android:name=".MainActivity"
    Android:label="@string/app_name"
    Android:theme="@style/AppTheme.NoActionBar">
</activity>

<activity
    Android:name=".Splash"
    Android:configChanges="orientation|keyboardHidden|screenSize"
    Android:theme="@style/SplashTheme">

    <intent-filter>
        <action Android:name="Android.intent.action.MAIN" />
        <category Android:name="Android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

5- Dans le styles.xml défini la SplashTheme comme:

<style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
    <item name="Android:windowBackground">@drawable/Splash</item>
</style>

6- Le @drawable/Splash.xmls est:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android">

    <item
        Android:drawable="@color/lightgray"/>

    <item>
        <bitmap
            Android:gravity="center"
            Android:src="@mipmap/ic_launcher"/>
    </item>

</layer-list>

7- Dans le values/colors.xmls, la couleur lightgray avait été définie comme suit:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="lightgray">#D3D3D3</color>
</resources>
7
Hasan A Yousef

Après avoir demandé une autorisation, avec une boucle while, vous pouvez vérifier si l'autorisation est accordée de manière continue. Si cette autorisation est accordée, vous pouvez modifier la valeur et quitter la boucle while.

Boolean isAnswered = true;

    while(isAnswered){

        if (ActivityCompat.checkSelfPermission(getApplication(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getApplication(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            Log.d("isanswered", String.valueOf(isAnswered));
        }
        else{
            isAnswered = false;
            Log.d("isanswered", String.valueOf(isAnswered));
        }
    }
0
Caner Kaya