2015-09-10 13 views
71

Ich versuche, die GPS-Koordinaten anzuzeigen, wenn ich auf eine Schaltfläche in meinem Aktivitätslayout klicken. Im Folgenden ist die Methode, die aufgerufen wird, wenn ich auf die Schaltfläche klicken:Android Check-Berechtigung für LocationManager

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, die besagt,

Anruf Genehmigung erfordert, die vom Benutzer zurückgewiesen werden kann. Code sollte explizit überprüfen, ob die Berechtigung verfügbar ist.

Ich habe diese Berechtigungen bereits in meinem AndroidManifest gewährt. Der Fehler ist gesorgt und die App erstellt, wenn ich folgendes hinzufügen, bevor lm.getLastKnownLocation Aufruf:

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

Doch die App stürzt ab, wenn ich die Taste drücken, die getLocation aufruft, wenn es angeklickt wird. Was ist los? Gibt es eine bessere/einfachere Möglichkeit, die GPS-Koordinaten des Geräts zu erfassen?

+0

Wahrscheinlich könnten Sie ein Ausnahmeprotokoll anhängen. – Milan

+1

Verwenden Sie ContextCompat.checkSelfPermission (Kontext, Berechtigung) und stellen Sie sicher, dass Sie entsprechende Berechtigungen in Manifest erwähnt haben –

Antwort

113

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

Ich hatte Ihr gleiches Problem, aber die für mich folgende gearbeitet und ich bin erfolgreich Standortdaten abrufen kann:

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

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

(2) Stellen Sie sicher, Sie Berechtigungen vom Benutzer 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, Sie ContextCompat wie diese verwenden hat Kompatibilität mit älteren API-Ebenen.

(4) In Ihrem Standort Dienst oder Klasse, die Ihre Locationmanager initialisiert und erhält die letzte bekannte Position, 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 nur für mich, nachdem ich gearbeitet included @TargetApi (23) am Anfang meiner Methode initLocationService.

(6) ich dies auch für meine gradle Build hinzugefügt:

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

Hier ist meine LocationService 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 mit einem Android Lollipop Gerät nur so weit getestet. Hoffe, das funktioniert für Sie.

+2

Ich mag Ihre Lösung, aber Sie sollten überprüfen, ob LocationManager Null ist, bevor Sie es verwenden, nicht später. – Fer

+0

Ich bekomme "java.lang.NullPointerException: Versuch, aus Feld zu lesen" double android.location.Location.mLatitude 'auf eine Null-Objektreferenz ", wenn ich nicht nach Null zu der Zeit überprüfen –

+0

Ich meine, Sie sollten" if (locationManager! = null) "direkt nach" if (isNetworkEnabled) "und direkt nach" if (isGPSEnabled) {"obwohl es nicht wirklich notwendig ist: Es kann nicht Null in dieser Zeile sein, weil Sie es zuvor in Zeile" this .isGPSEnabled = locationManager.isProviderEnabled (LocationManager.GPS_PROVIDER); " und sein Wert wird in Ihrem Code nicht auf Null geändert. – Fer

36

Der letzte Teil der Fehlermeldung zitiert Sie lautet: ...with ("checkPermission") or explicitly handle a potential "SecurityException"

Eine viel schneller/einfacher Art und Weise der Überprüfung, ob Sie Berechtigungen haben, ist Ihr Code mit try { ... } catch (SecurityException e) { [insert error handling code here] } zu umgeben. Wenn Sie Berechtigungen haben, wird der 'try' Teil ausgeführt, wenn nicht, wird der 'catch' Teil.

+1

Nützlich, wenn Sie kein Aktivitäts- oder Kontextobjekt haben, für das Sie Berechtigungen prüfen können. – Nublodeveloper

35

EINFACHE LÖSUNG

Ich wollte apps pre api 23 unterstützen und stattdessen checkSelfPermission der Verwendung benutzte ich einen 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 
} 
4

, wenn Sie auf dynamische Berechtigungen und jede Berechtigung wie ACCESS_FINE_LOCATION arbeiten, ACCESS_COARSE_LOCATION Fehler geben "kann Methode PERMISSION_NAME nicht auflösen" in diesem Fall schreiben Sie Code mit dem Namen der Berechtigung und dann erstellen Sie Ihr Projekt neu wird dies die Manifest (Manifest.permission) Datei neu generieren.

Verwandte Themen