【问题标题】:Android Location runtime permissionsAndroid 位置运行时权限
【发布时间】:2017-10-17 07:34:50
【问题描述】:

我知道这类问题经常出现在堆栈溢出时。我看过很多有类似问题的帖子,阅读了官方文档,但最后我还是无法理解运行时权限在 android 中是如何工作的。

首先我得到以下错误:

Call requires permissions which may be rejected by user

当我生成 Android Studio 建议的代码时,我得到了:

    if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        // TODO: Consider calling
        //    ActivityCompat#requestPermissions
        // here to request the missing permissions, and then overriding
        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
        //                                          int[] grantResults)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.
        return;
    }

我的第一个问题是:如果我只想使用精细位置,我是否还需要检查粗略位置权限?

接下来我该怎么做?我应该在生成的代码的括号中包含什么?我如何以及在哪里请求权限?

这是我的代码中必须包含权限的部分(mLastLocation 行):

    private void displayLocation() {

    mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);

    if (mLastLocation != null) {
        double latitude = mLastLocation.getLatitude();
        double longitude = mLastLocation.getLongitude();

        lblLocation.setText(latitude + ", " + longitude);

    } else {

        lblLocation.setText("(Couldn't get the location. Make sure location is enabled on the device)");
    }
}

AndroidManifest 中定义的权限:

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

非常感谢!

【问题讨论】:

    标签: android android-permissions


    【解决方案1】:

    好位置:

    精细位置提供更好和准确的位置。它允许同时使用 GPS_PROVIDER 和 NETWORK_PROVIDER

    粗略位置:

    粗略位置提供的位置不太准确。它允许同时使用 NETWORK_PROVIDER 来确定位置。

    上下文:

    上下文允许访问特定于应用程序的资源和类,以及向上调用应用程序级操作,例如启动活动、广播和接收意图等。

    您可以使用以下类启用权限

    UtilityLocation.Java

    public class UtilityLocation {
        public static final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 123;
    
        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
        public static boolean checkPermission(final Context context)
        {
            int currentAPIVersion = Build.VERSION.SDK_INT;
            if(currentAPIVersion>= Build.VERSION_CODES.M)
            {
                if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                    if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, Manifest.permission.ACCESS_FINE_LOCATION)) {
                        AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
                        alertBuilder.setCancelable(true);
                        alertBuilder.setTitle("Permission necessary");
                        alertBuilder.setMessage("Camera permission is necessary");
                        alertBuilder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                            @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
                            public void onClick(DialogInterface dialog, int which) {
                                ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
                            }
                        });
                        AlertDialog alert = alertBuilder.create();
                        alert.show();
    
                    } else {
                        ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
                    }
                    return false;
                } else {
                    return true;
                }
            } else {
                return true;
            }
        }
    }
    

    MainActivity.Java

    检查权限是否启用

    Private Context mContext;
    mContext=MainActivty.this;
    
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    // only for gingerbread and newer versions
                    boolean resultLocation = UtilityLocation.checkPermission(mContext);
                    if (resultLocation) {
           //Allow Permission and Call your Location Activity.
                 }
                } else {
          //Call your Location Activity
              }
            }
    

    【讨论】:

    • MainActivity 中的 mContext 是什么?
    • 传递你的活动上下文。
    • 以及为什么我总是看到:无法解析符号:Manifest.permission.ACCESS_FINE_LOCATION?
    • 尝试像下面这样通过你的权限 android.Manifest.permission.ACCESS_FINE_LOCATION
    • 如果您在 Android M 中允许或启用了您的权限,if(resultLocation) 应该为 true 并调用您的 Activity 以获取位置,否则不调用您的 Activity,它应该使启用为 true或允许权限。对于低于 Android M 的较低设备,结果位置应该是错误的调用您的位置活动。
    【解决方案2】:

    如果我只想使用精细位置,是否还需要检查粗略位置权限?

    没有。请理解 IDE 快速修复是没有太多聪明才智的模板。

    我应该在生成的代码的括号中包含什么?我如何以及在哪里请求权限?

    嗯,生成的代码注释中对此进行了解释。在该区块中,致电ActivityCompat.requestPermissions() 请求您的许可。在用户授予或拒绝权限后,您将在onRequestPermissionsResult() 中被调用。

    然后,您将在两个地方调用您的 displayLocation() 方法:

    • 为您生成代码的if 的else 块

    • 在onRequestPermissionsResult()中,如果用户授予权限

    This sample app 演示了请求权限和处理 Play Services 集成作为查找设备位置的一部分。

    此外,关于您的 displayLocation() 方法,不要假设 getLastLocation() 将始终返回一个位置。即使可能启用了提供程序,设备目前也可能不会跟踪其位置。

    【讨论】:

    • 非常感谢您的回答!
    猜你喜欢
    • 2018-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-03
    • 2014-02-16
    • 1970-01-01
    相关资源
    最近更新 更多