Pytanie Uprawnienia do sprawdzania Androida dla Menedżera lokalizacji


Próbuję uzyskać współrzędne GPS do wyświetlenia po kliknięciu przycisku w moim układzie czynności. Poniżej znajduje się metoda, która zostanie wywołana po kliknięciu przycisku:

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

Dostaję błąd, który mówi

Połączenie wymaga pozwolenia, które może zostać odrzucone przez użytkownika. Kod powinien jawnie sprawdzić, czy uprawnienia są dostępne.

Te uprawnienia zostały już przeze mnie przyznane AndroidManifest. Błąd został rozwiązany i aplikacja kompiluje się, gdy dodaję następujące elementy przed wywołaniem lm.getLastKnownLocation:

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

Jednak aplikacja ulega awarii po naciśnięciu przycisku wywołującego getLocation po kliknięciu. Co się dzieje? Czy istnieje lepszy / prostszy sposób na pobranie współrzędnych GPS urządzenia?


76
2017-09-10 02:09


pochodzenie


Prawdopodobnie możesz dołączyć dziennik wyjątków. - Milan
Użyj ContextCompat.checkSelfPermission (kontekst, uprawnienie) i upewnij się, że wspomniałeś odpowiednie uprawnienia w manifeście - Snehal Poyrekar


Odpowiedzi:


W przypadku poziomu interfejsu Android API (23) musimy sprawdzić uprawnienia. https://developer.android.com/training/permissions/requesting.html

Miałem ten sam problem, ale dla mnie zadziałały poniższe elementy i mogę z powodzeniem pobierać dane o lokalizacji:

(1) Upewnij się, że masz uprawnienia wymienione w Manifest:

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

(2) Upewnij się, że żądasz uprawnień od użytkownika:

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) Upewnij się, że korzystasz z ContextCompat, ponieważ ma on kompatybilność ze starszymi poziomami API.

(4) W usłudze lokalizacji lub klasie inicjującej menedżera lokalizacji LocationManager i pobierającej ostatnią znaną lokalizację, musimy sprawdzić uprawnienia:

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) To podejście zadziałało tylko dla mnie po tym, jak włączyłem @TargetApi (23) na początku mojej metody initLocationService.

(6) Dodałem to również do mojej kompilacji:

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

Oto moja usługa LocationService w celach informacyjnych:

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

Testowałem tylko na urządzeniu z Androidem Lollipop. Mam nadzieję, że to działa dla ciebie.


121
2017-10-11 22:03



Podoba mi się twoje rozwiązanie, ale powinieneś sprawdzić, czy locationManager ma wartość NULL przed użyciem, a nie później. - Fer
LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION ta linia nie działa w wersji 23 - delive
Usługa LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION również nie działa. - Kairi San
@delive, LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION -> musisz zdefiniować ten kod int w swoim własnym działaniu (który zaimplementował ActivityCompat.OnRequestPermissionsResultCallback) class, po szczegóły sprawdź to połączyć. - David Cheung
COARSE not not course - Chris Cox


PROSTE ROZWIĄZANIE

Chciałem obsługiwać aplikacje pre-api 23 i zamiast tego używać checkSelfPermission Użyłem 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
}

40
2018-03-02 19:52



Niesamowite rozwiązanie !! - V. Kalyuzhnyu


Ostatnia część komunikatu o błędzie, który podałeś, stwierdza: ...with ("checkPermission") or explicitly handle a potential "SecurityException"

Znacznie szybszym / prostszym sposobem sprawdzenia, czy masz uprawnienia, jest otaczanie kodu try { ... } catch (SecurityException e) { [insert error handling code here] }. Jeśli masz uprawnienia, część "try" zostanie wykonana, jeśli nie, część "catch" będzie.


36
2017-12-01 16:54



Przydatne, jeśli nie masz obiektu aktywności lub kontekstu, możesz sprawdzić uprawnienia. - Nublodeveloper


jeśli pracujesz nad uprawnieniami dynamicznymi i wszelkimi uprawnieniami, takimi jak ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION, podając błąd "nie można rozwiązać metody PERMISSION_NAME" w tym przypadku napisz kod z nazwą uprawnienia, a następnie przebuduj swój projekt, który zregeneruje plik manifestu (Manifest.permission).


4
2018-03-17 03:05





Użyj mojej klasy custome, aby sprawdzić lub poprosić o permissona

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

Przykład

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

0
2018-06-08 12:24