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(context,permission)并确保您在清单中提到了适当的权限
Snehal Poyrekar 2015年

Answers:


149

对于Android API级别(23),我们需要检查权限。 https://developer.android.com/training/permissions/requesting.html

我遇到了同样的问题,但是以下问题对我有用,并且我能够成功检索位置数据:

(1)确保您具有清单中列出的权限:

<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)只有在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。
2015年

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->您必须在自己的活动(已实现ActivityCompat.OnRequestPermissionsResultCallback)类中定义此int代码,有关详细信息,请检查此链接
张大卫

11
粗糙而不是过程
克里斯·考克斯

46

简单的解决方案

我想在api 23之前支持应用程序,而不是使用checkSelfPermissiontry / 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 2015年

5

使用我的客户课程检查或请求许可

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

此代码用于允许授予或拒绝活动结果
米兰皮塔迪亚

4

如果您正在使用动态权限,并且任何权限(例如ACCESS_FINE_LOCATION,ACCESS_COARSE_LOCATION)在这种情况下给出错误“无法解析方法PERMISSION_NAME”,则使用权限名称编写代码,然后重新生成项目,这将重新生成manifest(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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.