LocationManager에 대한 Android 확인 권한


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에게

답변:


150

Android API 레벨 (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) 이전 API 레벨과 호환되므로 ContextCompat를 사용해야합니다.

(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)이 접근 방식은 initLocationService 메서드의 맨 위에 @TargetApi (23)를 포함시킨 후에 만 ​​저에게 효과적이었습니다.

(6) 나는 또한 이것을 내 gradle 빌드에 추가했습니다.

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가 null인지 확인해야합니다.
Fer

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을 구현 한) 클래스에서 정의해야합니다 . 자세한 내용은이 링크 를 확인 하십시오 .
데이비드 청

11
하지 COURSE COARSE
크리스 콕스

46

간단한 솔루션

나는 앱 프리 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] }. 권한이 있으면 'try'부분이 실행되고, 그렇지 않으면 'catch'부분이 실행됩니다.


1
권한을 확인할 수있는 활동 또는 컨텍스트 개체가없는 경우 유용합니다.
Nublodeveloper

6

내 손님 클래스를 사용하여 허가 확인 또는 요청

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.