【问题标题】:Android check permission for LocationManagerAndroid 检查 LocationManager 的权限
【发布时间】:2015-12-06 03:43:24
【问题描述】:

当我点击我的活动布局中的一个按钮时,我试图让 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 坐标?

【问题讨论】:

  • 可能你可以附上异常日志。
  • 使用 ContextCompat.checkSelfPermission(context,permission) 并确保您在清单中提到了适当的权限

标签: android locationmanager


【解决方案1】:

如果你只是想检查权限(而不是请求权限),我写了一个简单的扩展,如下所示:

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)

【讨论】:

    【解决方案2】:

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

    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”的作用是什么?
    • 此代码用于允许或拒绝活动结果的结果
    【解决方案3】:

    对于 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) 这种方法只有在我将 @TargetApi(23) 包含在我的 initLocationService 方法的顶部后才对我有效。

    (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 设备进行了测试。 希望这对你有用。

    【讨论】:

    • 我喜欢你的解决方案,但你应该在使用它之前检查 locationManager 是否为空,而不是以后。
    • LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION 此行不工作版本 23
    • LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION 对我也不起作用。
    • @delive, LocationService.MY_PERMISSION_ACCESS_COURSE_LOCATION -> 你必须在你自己的活动(实现了ActivityCompat.OnRequestPermissionsResultCallback)类中定义这个int代码,详情请查看link。
    • 粗略不是课程
    【解决方案4】:

    简单的解决方案

    我想支持 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
    }
    

    【讨论】:

      【解决方案5】:

      如果您正在处理动态权限和任何权限,例如 ACCESS_FINE_LOCATION、ACCESS_COARSE_LOCATION 给出错误 “无法解析方法 PERMISSION_NAME” 在这种情况下,请使用权限名称编写代码,然后重建您的项目,这将重新生成清单(Manifest.permission)文件。

      【讨论】:

        【解决方案6】:

        您引用的错误消息的最后一部分指出: ...with ("checkPermission") or explicitly handle a potential "SecurityException"

        检查您是否有权限的一种更快/更简单的方法是用try { ... } catch (SecurityException e) { [insert error handling code here] } 包围您的代码。如果你有权限,'try' 部分将执行,如果你没有,'catch' 部分将执行。

        【讨论】:

        • 如果您没有可以检查权限的 Activity 或 Context 对象,这很有用。
        猜你喜欢
        • 1970-01-01
        • 2016-07-22
        • 2017-09-26
        • 2017-07-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-02
        • 1970-01-01
        相关资源
        最近更新 更多