Android-Berechtigung für LocationManager prüfen

97

Ich versuche, die GPS-Koordinaten anzuzeigen, wenn ich in meinem Aktivitätslayout auf eine Schaltfläche klicke. Die folgende Methode wird aufgerufen, wenn ich auf die Schaltfläche klicke:

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());
}

Ich erhalte eine Fehlermeldung

Anruf erfordert Erlaubnis, die vom Benutzer abgelehnt werden kann. Der Code sollte explizit prüfen, ob eine Berechtigung verfügbar ist.

Ich habe diese Berechtigungen bereits in meinem erteilt AndroidManifest. Der Fehler wird behoben und die App wird kompiliert, wenn ich vor dem Aufruf Folgendes hinzufüge lm.getLastKnownLocation:

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

Die App stürzt jedoch ab, wenn ich die Schaltfläche drücke, die beim Klicken getLocation aufruft. Was ist los? Gibt es eine bessere / einfachere Möglichkeit, die GPS-Koordinaten des Geräts zu erfassen?

Benutzer
quelle
Wahrscheinlich könnten Sie ein Ausnahmeprotokoll anhängen.
Mailand
1
Verwenden Sie ContextCompat.checkSelfPermission (Kontext, Berechtigung) und stellen Sie sicher, dass Sie die entsprechenden Berechtigungen im Manifest erwähnt haben
Snehal Poyrekar

Antworten:

149

Mit der Android-API-Stufe (23) müssen wir nach Berechtigungen suchen. https://developer.android.com/training/permissions/requesting.html

Ich hatte das gleiche Problem, aber Folgendes hat bei mir funktioniert und ich kann Standortdaten erfolgreich abrufen:

(1) Stellen Sie sicher, dass Ihre Berechtigungen im Manifest aufgeführt sind:

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

(2) Stellen Sie sicher, dass Sie vom Benutzer Berechtigungen anfordern:

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) Stellen Sie sicher, dass Sie ContextCompat verwenden, da dies mit älteren API-Ebenen kompatibel ist.

(4) In Ihrem Standortdienst oder Ihrer Klasse, die Ihren LocationManager initialisiert und den letzten bekannten Standort abruft, müssen wir die Berechtigungen überprüfen:

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) Dieser Ansatz hat bei mir erst funktioniert, nachdem ich @TargetApi (23) oben in meine initLocationService-Methode eingefügt habe.

(6) Ich habe dies auch zu meinem Gradle-Build hinzugefügt:

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

Hier ist mein LocationService als Referenz:

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 
    }
}

Ich habe bisher nur mit einem Android Lollipop-Gerät getestet. Hoffe das funktioniert bei dir.

keshav.bahadoor
quelle
2
Ich mag Ihre Lösung, aber Sie sollten überprüfen, ob locationManager null ist, bevor Sie es verwenden, nicht später.
Fer
9
LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION Diese Zeile funktioniert nicht Version 23
4
Der LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION funktioniert auch bei mir nicht.
Kairi San
1
@delive, LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION -> Sie müssen diesen int-Code in Ihrer eigenen Aktivitätsklasse (die ActivityCompat.OnRequestPermissionsResultCallback implementiert hat) definieren. Weitere Informationen finden Sie unter diesem Link .
David Cheung
11
COARSE not COURSE
Chris Cox
46

EINFACHE LÖSUNG

Ich wollte Apps vor API 23 unterstützen und anstatt sie zu verwenden, habe checkSelfPermissionich einen Try / Catch verwendet

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

Der letzte Teil der von Ihnen zitierten Fehlermeldung lautet: ...with ("checkPermission") or explicitly handle a potential "SecurityException"

Eine viel schnellere / einfachere Möglichkeit, zu überprüfen, ob Sie über Berechtigungen verfügen, besteht darin, Ihren Code mit zu umgeben try { ... } catch (SecurityException e) { [insert error handling code here] }. Wenn Sie über Berechtigungen verfügen, wird der Teil "try" ausgeführt. Wenn Sie dies nicht tun, wird der Teil "catch" ausgeführt.

VikingGlen
quelle
1
Nützlich, wenn Sie kein Aktivitäts- oder Kontextobjekt haben, auf das Sie die Berechtigungen überprüfen können.
Nublodeveloper
5

Verwenden Sie meine Kundenklasse, um die Erlaubnis zu überprüfen oder anzufordern

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;
        }
    }

Beispiel

if(!Permissons.Check_STORAGE(MainActivity.this))
{
   //if not permisson granted so request permisson with request code
   Permissons.Request_STORAGE(MainActivity.this,22);
}
Mailand Pithadia
quelle
danke, aber ich möchte fragen, was ist die Funktion von "int code"?
Hendro Pramono
Dieser Code wird verwendet, um das gewährte Ergebnis zuzulassen oder das Aktivitätsergebnis
abzulehnen
4

Wenn Sie an dynamischen Berechtigungen und Berechtigungen wie ACCESS_FINE_LOCATION arbeiten, kann ACCESS_COARSE_LOCATION mit dem Fehler "Methode PERMISSION_NAME kann nicht aufgelöst werden" in diesem Fall den Code mit dem Berechtigungsnamen schreiben und dann Ihr Projekt neu erstellen. Dadurch wird die Manifestdatei (Manifest.permission) neu generiert.

anoopbryan2
quelle
0

Wenn Sie einfach nach Berechtigungen suchen möchten (anstatt nach Berechtigungen zu fragen), habe ich eine einfache Erweiterung wie folgt geschrieben:

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
        }
    }

Wenn ich nun nach einer Erlaubnis suchen möchte, kann ich einfach eine Erlaubnis wie folgt übergeben:

checkPermission(Manifest.permission.READ_CONTACTS)
azwethinkweiz
quelle