สิทธิ์ในการตรวจสอบ Android สำหรับ LocationManager


97

ฉันพยายามรับพิกัด GPS เพื่อแสดงเมื่อฉันคลิกปุ่มในรูปแบบกิจกรรมของฉัน ต่อไปนี้เป็นวิธีการที่เรียกเมื่อฉันคลิกปุ่ม:

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

ฉันได้รับข้อผิดพลาดที่ระบุว่า

การโทรต้องได้รับอนุญาตซึ่งอาจถูกปฏิเสธโดยผู้ใช้ รหัสควรตรวจสอบอย่างชัดเจนว่ามีการอนุญาตหรือไม่

ฉันได้ให้สิทธิ์เหล่านี้แล้วในAndroidManifestไฟล์. ข้อผิดพลาดได้รับการดูแลและแอปจะรวบรวมเมื่อฉันเพิ่มสิ่งต่อไปนี้ก่อนที่จะโทรlm.getLastKnownLocation:

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

อย่างไรก็ตามแอปขัดข้องเมื่อฉันกดปุ่มที่เรียก getLocation เมื่อมีการคลิก เกิดอะไรขึ้น? มีวิธีที่ดีกว่า / ง่ายกว่าในการคว้าพิกัด GPS ของอุปกรณ์หรือไม่?


คุณอาจแนบบันทึกข้อยกเว้น
มิลาน

1
ใช้ ContextCompat.checkSelfPermission (บริบทสิทธิ์) และตรวจสอบให้แน่ใจว่าคุณได้กล่าวถึงสิทธิ์ที่เหมาะสมในรายการ
Snehal Poyrekar

คำตอบ:


151

ด้วยระดับ API ของ Android (23) เราจำเป็นต้องตรวจสอบสิทธิ์ https://developer.android.com/training/permissions/requesting.html

ฉันมีปัญหาเดียวกันกับคุณ แต่สิ่งต่อไปนี้ใช้ได้ผลสำหรับฉันและฉันสามารถดึงข้อมูลตำแหน่งได้สำเร็จ:

(1) ตรวจสอบให้แน่ใจว่าคุณมีสิทธิ์ของคุณอยู่ในรายการ Manifest:

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

(2) ตรวจสอบให้แน่ใจว่าคุณขอสิทธิ์จากผู้ใช้:

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) ตรวจสอบให้แน่ใจว่าคุณใช้ ContextCompat เนื่องจากมีความเข้ากันได้กับระดับ API ที่เก่ากว่า

(4) ในบริการระบุตำแหน่งของคุณหรือคลาสที่เริ่มต้น LocationManager ของคุณและรับตำแหน่งที่รู้จักล่าสุดเราจำเป็นต้องตรวจสอบสิทธิ์:

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) วิธีนี้ใช้ได้ผลเฉพาะกับฉันหลังจากที่ฉันรวม @TargetApi (23) ไว้ที่ด้านบนของเมธอด initLocationService

(6) ฉันยังเพิ่มสิ่งนี้ในงานสร้างระดับประถมศึกษาของฉัน:

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

นี่คือ LocationService ของฉันสำหรับการอ้างอิง:

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

ฉันทดสอบกับอุปกรณ์ Android Lollipop แล้วเท่านั้น หวังว่านี่จะเหมาะกับคุณ


2
ฉันชอบโซลูชันของคุณ แต่คุณควรตรวจสอบว่า locationManager เป็นโมฆะก่อนที่จะใช้ไม่ใช่ในภายหลัง
เฟอร์

9
LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION บรรทัดนี้ใช้ไม่ได้กับเวอร์ชัน 23

4
LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION ก็ใช้งานไม่ได้เช่นกัน
Kairi San

1
@delive, LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION -> คุณต้องกำหนดรหัส int นี้ในกิจกรรมของคุณเอง (ซึ่งใช้คลาส ActivityCompat OnRequestPermissionsResultCallback) สำหรับรายละเอียดโปรดตรวจสอบลิงค์นี้
chub

11
COARSE ไม่ใช่ COURSE
Chris Cox

47

โซลูชันที่เรียบง่าย

ฉันต้องการรองรับแอพก่อน api 23 และแทนที่จะใช้checkSelfPermissionฉันใช้ 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
}

39

ส่วนสุดท้ายของข้อความแสดงข้อผิดพลาดที่คุณอ้างถึง: ...with ("checkPermission") or explicitly handle a potential "SecurityException"

วิธีที่เร็วมาก / try { ... } catch (SecurityException e) { [insert error handling code here] }ที่เรียบง่ายของการตรวจสอบว่าคุณมีสิทธิ์ที่จะล้อมรอบด้วยรหัสของคุณ หากคุณมีสิทธิ์ส่วน "ลอง" จะดำเนินการถ้าคุณไม่ทำส่วน "จับ" จะ


1
มีประโยชน์หากคุณไม่มีวัตถุกิจกรรมหรือบริบทคุณสามารถตรวจสอบสิทธิ์ได้
Nublodeveloper

7

ใช้ชั้นเรียนของฉันเพื่อตรวจสอบหรือขออนุญาต

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

ตัวอย่าง

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

ขอบคุณค่ะ แต่อยากถามว่า "int code" มีหน้าที่อะไร
Hendro Pramono

รหัสนี้ใช้เพื่ออนุญาตผลที่ได้รับหรือปฏิเสธผลกิจกรรม
milan pithadia

4

หากคุณกำลังดำเนินการกับการอนุญาตแบบไดนามิกและการอนุญาตใด ๆ เช่น ACCESS_FINE_LOCATION ACCESS_COARSE_LOCATION ทำให้เกิดข้อผิดพลาด"ไม่สามารถแก้ไขวิธีการ PERMISSION_NAME"ในกรณีนี้ให้เขียนโค้ดด้วยชื่อสิทธิ์จากนั้นสร้างโปรเจ็กต์ใหม่ซึ่งจะสร้างไฟล์รายการ (Manifest.permission) ขึ้นมาใหม่


0

หากคุณต้องการตรวจสอบสิทธิ์ (แทนที่จะขอสิทธิ์) ฉันเขียนส่วนขยายง่ายๆดังนี้:

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

ตอนนี้ถ้าฉันต้องการตรวจสอบการอนุญาตฉันสามารถส่งผ่านการอนุญาตได้ดังนี้:

checkPermission(Manifest.permission.READ_CONTACTS)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.