Android memeriksa izin untuk LocationManager

97

Saya mencoba menampilkan koordinat GPS saat saya mengklik tombol di tata letak aktivitas saya. Berikut ini adalah metode yang dipanggil ketika saya mengklik tombol:

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

Saya mendapatkan pesan kesalahan yang mengatakan

Panggilan membutuhkan izin yang mungkin ditolak oleh pengguna. Kode harus secara eksplisit memeriksa untuk melihat apakah izin tersedia.

Saya telah memberikan izin ini di saya AndroidManifest. Kesalahan diatasi dan aplikasi dikompilasi ketika saya menambahkan yang berikut ini sebelum memanggil lm.getLastKnownLocation:

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

Namun, aplikasi macet saat saya menekan tombol yang memanggil getLocation saat diklik. Apa yang sedang terjadi? Apakah ada cara yang lebih baik / lebih sederhana untuk mengambil koordinat GPS perangkat?

pengguna
sumber
Mungkin Anda bisa melampirkan log pengecualian.
Milan
1
Gunakan ContextCompat.checkSelfPermission (konteks, izin) dan pastikan Anda telah menyebutkan izin yang sesuai di manifes
Snehal Poyrekar

Jawaban:

150

Dengan Android API level (23), kami diminta untuk memeriksa izin. https://developer.android.com/training/permissions/requesting.html

Saya mengalami masalah yang sama, tetapi hal berikut berhasil untuk saya dan saya berhasil mengambil data Lokasi:

(1) Pastikan Anda memiliki izin yang tercantum di Manifes:

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

(2) Pastikan Anda meminta izin dari pengguna:

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) Pastikan Anda menggunakan ContextCompat karena ini memiliki kompatibilitas dengan level API yang lebih lama.

(4) Di layanan lokasi Anda, atau kelas yang menginisialisasi LocationManager Anda dan mendapatkan lokasi terakhir yang diketahui, kami perlu memeriksa izinnya:

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) Pendekatan ini hanya berfungsi untuk saya setelah saya menyertakan @TargetApi (23) di bagian atas metode initLocationService saya.

(6) Saya juga menambahkan ini ke build gradle saya:

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

Ini adalah LocationService saya untuk referensi:

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

Saya menguji dengan perangkat Android Lollipop sejauh ini saja. Semoga ini berhasil untuk Anda.

keshav.bahadoor
sumber
2
Saya suka solusi Anda, tetapi Anda harus memeriksa apakah locationManager null sebelum menggunakannya, bukan nanti.
Fer
9
LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION baris ini tidak berfungsi versi 23
4
LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION juga tidak berfungsi untuk saya.
Kairi San
1
@delive, LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION -> Anda harus mendefinisikan kode int ini dalam aktivitas Anda sendiri (yang mengimplementasikan kelas ActivityCompat.OnRequestPermissionsResultCallback), untuk detailnya silakan periksa tautan ini .
David Cheung
11
KERAS bukan KURSUS
Chris Cox
46

SOLUSI SEDERHANA

Saya ingin mendukung aplikasi sebelum api 23 dan alih-alih menggunakan, checkSelfPermissionsaya menggunakan coba / tangkap

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
sumber
39

Bagian terakhir dari pesan kesalahan yang Anda kutip menyatakan: ...with ("checkPermission") or explicitly handle a potential "SecurityException"

Cara yang lebih cepat / sederhana untuk memeriksa apakah Anda memiliki izin adalah dengan mengelilingi kode Anda try { ... } catch (SecurityException e) { [insert error handling code here] }. Jika Anda memiliki izin, bagian 'coba' akan dijalankan, jika tidak, bagian 'tangkap' akan.

VikingGlen
sumber
1
Berguna jika Anda tidak memiliki objek Aktivitas atau Konteks yang dapat Anda periksa izinnya.
Nublodeveloper
6

Gunakan kelas custome saya untuk memeriksa atau meminta izin

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

Contoh

if(!Permissons.Check_STORAGE(MainActivity.this))
{
   //if not permisson granted so request permisson with request code
   Permissons.Request_STORAGE(MainActivity.this,22);
}
milan pithadia
sumber
terima kasih, tapi saya ingin bertanya, apa fungsi dari "kode int"?
Hendro Pramono
Kode ini digunakan untuk mengizinkan hasil yang diberikan atau ditolak pada hasil Aktivitas
milan pithadia
4

jika Anda bekerja pada izin dinamis dan izin seperti ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION memberikan kesalahan "tidak dapat menyelesaikan metode PERMISSION_NAME" dalam hal ini tulis kode Anda dengan nama izin dan kemudian membangun kembali proyek Anda ini akan membuat kembali file manifes (Manifest.permission).

anoopbryan2
sumber
0

Jika Anda hanya ingin memeriksa izin (daripada meminta izin), saya menulis ekstensi sederhana seperti ini:

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

Sekarang, jika saya ingin memeriksa izin, saya cukup memberikan izin seperti ini:

checkPermission(Manifest.permission.READ_CONTACTS)
azwethinkweiz.dll
sumber