LocationManager için Android kontrol izni


97

Etkinlik düzenimdeki bir düğmeyi tıkladığımda GPS koordinatlarının görüntülenmesini sağlamaya çalışıyorum. Düğmeye tıkladığımda çağrılan yöntem şudur:

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

Diyen bir hata alıyorum

Çağrı, kullanıcı tarafından reddedilebilecek izin gerektirir. Kod, iznin olup olmadığını açıkça kontrol etmelidir.

Bu izinleri önceden vermiştim AndroidManifest. Aramadan önce aşağıdakileri eklediğimde hata halledilir ve uygulama derlenir lm.getLastKnownLocation:

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

Ancak, tıklandığında getLocation'ı çağıran düğmeye bastığımda uygulama çöküyor. Ne oluyor? Cihazın GPS koordinatlarını almanın daha iyi / daha basit bir yolu var mı?


Muhtemelen bir istisna günlüğü ekleyebilirsiniz.
Milan

1
ContextCompat.checkSelfPermission (bağlam, izin) kullanın ve bildirimde uygun izinlerden bahsettiğinizden emin olun
Snehal Poyrekar

Yanıtlar:


151

Android API seviyesi (23) ile izinleri kontrol etmemiz gerekiyor. https://developer.android.com/training/permissions/requesting.html

Aynı problemi yaşadım, ancak aşağıdakiler benim için çalıştı ve Konum verilerini başarıyla alabiliyorum:

(1) İzinlerinizi Manifest'te listelediğinizden emin olun:

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

(2) Kullanıcıdan izin talep ettiğinizden emin olun:

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) Daha eski API seviyeleriyle uyumlu olduğundan ContextCompat kullandığınızdan emin olun.

(4) Konum hizmetinizde veya LocationManager'ınızı başlatan ve bilinen son konumu alan sınıfta, izinleri kontrol etmemiz gerekir:

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) Bu yaklaşım, initLocationService yöntemimin en üstüne @TargetApi (23) ekledikten sonra sadece benim için çalıştı.

(6) Bunu gradle yapıma da ekledim:

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

İşte referans için Konum Hizmetim:

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

Şimdiye kadar yalnızca bir Android Lollipop cihazıyla test ettim. Umarım bu sizin için çalışır.


2
Çözümünüzü beğendim, ancak daha sonra değil, kullanmadan önce locationManager'ın boş olup olmadığını kontrol etmelisiniz.
Fer

9
LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION bu satır sürüm 23 çalışmıyor

4
LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION benim için de çalışmıyor.
Kairi San

1
@delive, LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION -> bu int kodunu kendi aktivitenizde (ActivityCompat.OnRequestPermissionsResultCallback uygulayan) sınıfında tanımlamalısınız, ayrıntılar için lütfen bu bağlantıyı kontrol edin .
kefal

11
COARSE not COURSE
Chris Cox

47

BASİT ÇÖZÜM

Api 23 öncesi uygulamaları desteklemek istedim ve bunun yerine checkSelfPermissionbir dene / yakala kullandım

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

Alıntı yaptığınız hata mesajının son kısmında şunlar belirtilmektedir: ...with ("checkPermission") or explicitly handle a potential "SecurityException"

İzinlere sahip olup olmadığınızı kontrol etmenin çok daha hızlı / basit bir yolu, kodunuzu çevrelemektir try { ... } catch (SecurityException e) { [insert error handling code here] }. İzinlere sahipseniz, 'dene' bölümü çalıştırılır, yoksa 'yakala' bölümü çalıştırılır.


1
Bir Activity veya Context nesneniz yoksa kullanışlıdır, izinlerini kontrol edebilirsiniz.
Nublodeveloper

7

İzni kontrol etmek veya istemek için custome sınıfımı kullan

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

Misal

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

teşekkürler, ama sormak istiyorum, "int kod" un işlevi nedir?
Hendro Pramono

bu kod, Etkinlik sonucunda verilen veya reddedilen sonuca izin vermek için kullanın
milan pithadia

4

Dinamik izinler ve ACCESS_FINE_LOCATION gibi herhangi bir izin üzerinde çalışıyorsanız, ACCESS_COARSE_LOCATION hatası vererek "PERMISSION_NAME yöntemini çözemez" bu durumda size kodunuzu izin adıyla yazın ve ardından projenizi yeniden oluşturun, bu manifest (Manifest.permission) dosyasını yeniden oluşturacaktır.


0

Yalnızca izinleri kontrol etmek istiyorsanız (izin istemek yerine), şöyle basit bir uzantı yazdım:

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

Şimdi, bir izin olup olmadığını kontrol etmek istersem, aşağıdaki gibi bir izin verebilirim:

checkPermission(Manifest.permission.READ_CONTACTS)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.