Android vérifier l'autorisation pour LocationManager


97

J'essaie d'obtenir les coordonnées GPS à afficher lorsque je clique sur un bouton dans ma disposition d'activité. Voici la méthode qui est appelée lorsque je clique sur le bouton:

public void getLocation(View view) {
    TextView tv = (TextView) findViewById(R.id.gps_coord_view);
    LocationManager lm = (LocationManager) getSystemService(LOCATION_SERVICE);
    Location loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
    tv.setText("Latitude: " + loc.getLatitude() + "\nLongitude: " + loc.getLongitude());
}

J'obtiens une erreur qui dit

L'appel nécessite une autorisation qui peut être rejetée par l'utilisateur. Le code doit vérifier explicitement si l'autorisation est disponible.

J'ai déjà accordé ces autorisations dans mon AndroidManifest. L'erreur est prise en charge et l'application se compile lorsque j'ajoute ce qui suit avant d'appeler lm.getLastKnownLocation:

if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
        && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
    return;
}

Cependant, l'application se bloque lorsque j'appuie sur le bouton qui appelle getLocation lorsque l'utilisateur clique dessus. Que se passe-t-il? Existe-t-il un moyen meilleur / plus simple pour saisir les coordonnées GPS de l'appareil?


Vous pourriez probablement joindre un journal des exceptions.
Milan

1
Utilisez ContextCompat.checkSelfPermission (contexte, autorisation) et assurez-vous d'avoir mentionné les autorisations appropriées dans le manifeste
Snehal Poyrekar

Réponses:


149

Avec le niveau d'API Android (23), nous devons vérifier les autorisations. https://developer.android.com/training/permissions/requesting.html

J'ai eu le même problème, mais ce qui suit a fonctionné pour moi et je suis en mesure de récupérer les données de localisation avec succès:

(1) Assurez-vous que vos autorisations sont répertoriées dans le manifeste:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

(2) Assurez-vous de demander des autorisations à l'utilisateur:

if ( ContextCompat.checkSelfPermission( this, android.Manifest.permission.ACCESS_COARSE_LOCATION ) != PackageManager.PERMISSION_GRANTED ) {

            ActivityCompat.requestPermissions( this, new String[] {  android.Manifest.permission.ACCESS_COARSE_LOCATION  },
                                                LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION );
        }

(3) Assurez-vous d'utiliser ContextCompat car il est compatible avec les anciens niveaux d'API.

(4) Dans votre service de localisation, ou classe qui initialise votre LocationManager et obtient le dernier emplacement connu, nous devons vérifier les autorisations:

if ( Build.VERSION.SDK_INT >= 23 &&
             ContextCompat.checkSelfPermission( context, android.Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED &&
             ContextCompat.checkSelfPermission( context, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return  ;
        }

(5) Cette approche n'a fonctionné pour moi qu'après avoir inclus @TargetApi (23) en haut de ma méthode initLocationService.

(6) J'ai également ajouté ceci à ma version gradle:

compile 'com.android.support:support-v4:23.0.1'

Voici mon LocationService pour référence:

public class LocationService implements LocationListener  {

    //The minimum distance to change updates in meters
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 0; // 10 meters

    //The minimum time between updates in milliseconds
    private static final long MIN_TIME_BW_UPDATES = 0;//1000 * 60 * 1; // 1 minute

    private final static boolean forceNetwork = false;

    private static LocationService instance = null;

    private LocationManager locationManager;
    public Location location;
    public double longitude;
    public double latitude; 


    /**
     * Singleton implementation
     * @return
     */
    public static LocationService getLocationManager(Context context)     {
        if (instance == null) {
            instance = new LocationService(context);
        }
        return instance;
    }

    /**
     * Local constructor
     */
    private LocationService( Context context )     {

        initLocationService(context); 
        LogService.log("LocationService created");
    }



    /**
     * Sets up location service after permissions is granted
     */
    @TargetApi(23)
    private void initLocationService(Context context) {


        if ( Build.VERSION.SDK_INT >= 23 &&
             ContextCompat.checkSelfPermission( context, android.Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED &&
             ContextCompat.checkSelfPermission( context, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return  ;
        }

        try   {
            this.longitude = 0.0;
            this.latitude = 0.0;
            this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

            // Get GPS and network status
            this.isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
            this.isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

            if (forceNetwork) isGPSEnabled = false;

            if (!isNetworkEnabled && !isGPSEnabled)    {
                // cannot get location
                this.locationServiceAvailable = false;
            }
            //else
            {
                this.locationServiceAvailable = true;

                if (isNetworkEnabled) {
                    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                    if (locationManager != null)   {
                        location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                        updateCoordinates();
                    }
                }//end if

                if (isGPSEnabled)  {
                    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, this);

                    if (locationManager != null)  {
                        location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                        updateCoordinates();
                    }
                }
            }
        } catch (Exception ex)  {
            LogService.log( "Error creating location service: " + ex.getMessage() );

        }
    }       


    @Override
    public void onLocationChanged(Location location)     {
        // do stuff here with location object 
    }
}

J'ai testé avec un appareil Android Lollipop jusqu'à présent uniquement. J'espère que cela fonctionne pour toi.


2
J'aime votre solution, mais vous devriez vérifier si locationManager est nul avant de l'utiliser, pas plus tard.
Fer

9
LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION cette ligne ne fonctionne pas la version 23

4
le LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION ne fonctionne pas non plus pour moi.
Kairi San

1
@delive, LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION -> vous devez définir ce code int dans votre propre activité (qui a implémenté ActivityCompat.OnRequestPermissionsResultCallback), pour plus de détails, veuillez consulter ce lien .
David Cheung

11
COARSE not COURSE
Chris Cox

46

SOLUTION SIMPLE

Je voulais prendre en charge les applications antérieures à l'api 23 et au lieu d'utiliser, checkSelfPermissionj'ai utilisé un try / catch

try {
   location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
} catch (SecurityException e) {
   dialogGPS(this.getContext()); // lets the user know there is a problem with the gps
}

39

La dernière partie du message d'erreur que vous avez cité indique: ...with ("checkPermission") or explicitly handle a potential "SecurityException"

Un moyen beaucoup plus rapide / plus simple de vérifier si vous disposez des autorisations consiste à entourer votre code try { ... } catch (SecurityException e) { [insert error handling code here] }. Si vous avez des autorisations, la partie 'try' s'exécutera, sinon la partie 'catch' le fera.


1
Utile si vous ne disposez pas d'un objet Activité ou Contexte pour lequel vous pouvez vérifier les autorisations.
Nublodeveloper

5

Utilisez ma classe personnalisée pour vérifier ou demander une autorisation

public class Permissons {

        //Request Permisson
        public static void Request_STORAGE(Activity act,int code)
        {

            ActivityCompat.requestPermissions(act, new
                    String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE},code);
        }
        public static void Request_CAMERA(Activity act,int code)
        {
            ActivityCompat.requestPermissions(act, new
                    String[]{Manifest.permission.CAMERA},code);
        }
        public static void Request_FINE_LOCATION(Activity act,int code)
        {
            ActivityCompat.requestPermissions(act, new
                    String[]{Manifest.permission.ACCESS_FINE_LOCATION},code);
        }
        public static void Request_READ_SMS(Activity act,int code)
        {
            ActivityCompat.requestPermissions(act, new
                    String[]{Manifest.permission.READ_SMS},code);
        }
        public static void Request_READ_CONTACTS(Activity act,int code)
        {
            ActivityCompat.requestPermissions(act, new
                    String[]{Manifest.permission.READ_CONTACTS},code);
        }
        public static void Request_READ_CALENDAR(Activity act,int code)
        {
            ActivityCompat.requestPermissions(act, new
                    String[]{Manifest.permission.READ_CALENDAR},code);
        }
        public static void Request_RECORD_AUDIO(Activity act,int code)
        {
            ActivityCompat.requestPermissions(act, new
                    String[]{Manifest.permission.RECORD_AUDIO},code);
        }

        //Check Permisson
        public static boolean Check_STORAGE(Activity act)
        {
            int result = ContextCompat.checkSelfPermission(act,android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
            return result == PackageManager.PERMISSION_GRANTED;
        }
        public static boolean Check_CAMERA(Activity act)
        {
            int result = ContextCompat.checkSelfPermission(act, Manifest.permission.CAMERA);
            return result == PackageManager.PERMISSION_GRANTED;
        }
        public static boolean Check_FINE_LOCATION(Activity act)
        {
            int result = ContextCompat.checkSelfPermission(act, Manifest.permission.ACCESS_FINE_LOCATION);
            return result == PackageManager.PERMISSION_GRANTED;
        }
        public static boolean Check_READ_SMS(Activity act)
        {
            int result = ContextCompat.checkSelfPermission(act, Manifest.permission.READ_SMS);
            return result == PackageManager.PERMISSION_GRANTED;
        }
        public static boolean Check_READ_CONTACTS(Activity act)
        {
            int result = ContextCompat.checkSelfPermission(act, Manifest.permission.READ_CONTACTS);
            return result == PackageManager.PERMISSION_GRANTED;
        }
        public static boolean Check_READ_CALENDAR(Activity act)
        {
            int result = ContextCompat.checkSelfPermission(act, Manifest.permission.READ_CALENDAR);
            return result == PackageManager.PERMISSION_GRANTED;
        }
        public static boolean Check_RECORD_AUDIO(Activity act)
        {
            int result = ContextCompat.checkSelfPermission(act, Manifest.permission.RECORD_AUDIO);
            return result == PackageManager.PERMISSION_GRANTED;
        }
    }

Exemple

if(!Permissons.Check_STORAGE(MainActivity.this))
{
   //if not permisson granted so request permisson with request code
   Permissons.Request_STORAGE(MainActivity.this,22);
}

merci, mais je veux demander, quelle est la fonction de "code int"?
Hendro Pramono

ce code utilise pour autoriser le résultat accordé ou le déclin du résultat d'activité
milan pithadia

4

si vous travaillez sur des autorisations dynamiques et des autorisations telles que ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION donnant l'erreur " Impossible de résoudre la méthode PERMISSION_NAME" dans ce cas, écrivez votre code avec le nom de l'autorisation, puis reconstruisez votre projet, cela régénérera le fichier manifeste (Manifest.permission).


0

Si vous voulez simplement vérifier les autorisations (plutôt que demander des autorisations), j'ai écrit une simple extension comme celle-ci:

fun BaseActivity.checkPermission(permissionName: String): Boolean {
        return if (Build.VERSION.SDK_INT >= 23) {
            val granted =
                ContextCompat.checkSelfPermission(this, permissionName)
            granted == PackageManager.PERMISSION_GRANTED
        } else {
            val granted =
                PermissionChecker.checkSelfPermission(this, permissionName)
            granted == PermissionChecker.PERMISSION_GRANTED
        }
    }

Maintenant, si je veux vérifier une autorisation, je peux simplement transmettre une autorisation comme celle-ci:

checkPermission(Manifest.permission.READ_CONTACTS)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.