检查用户位置的权限

Posted

技术标签:

【中文标题】检查用户位置的权限【英文标题】:Check permission for user location 【发布时间】:2018-06-20 17:43:55 【问题描述】:

我一直在按照 android 开发者教程获取用户的最后一个已知位置:https://developer.android.com/training/location/retrieve-current.html。我按照步骤操作并收到以下错误:Call requires permissions which may be reject by the user: code should explicitly check to see if the permission is available (with checkPermission) or explicitly handle a potential SecurityException

经过一番研究后,我决定创建一个 checkPermissions 方法来检查权限,但是我仍然遇到上述相同的错误。

清单中的权限

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

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

getLocation 方法

public class ImageGalleryFragment extends Fragment 
    // Instance variables
    private static final int REQUEST_READ_EXTERNAL_STORAGE = 2987;
    private static final int REQUEST_WRITE_EXTERNAL_STORAGE = 7829;
    private static final int REQUEST_COARSE_LOCATION = 200;
    private FusedLocationProviderClient mFusedLocationClient;

    ...

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);

        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this.getActivity());

        checkPermissions(this.getContext());

        mFusedLocationClient.getLastLocation()
            .addOnSuccessListener(this.getActivity(), new OnSuccessListener<Location>() 
                @Override
                public void onSuccess(Location location) 
                    // Got last known location. In some rare situations this can be null.
                    if (location != null) 
                        // Logic to handle location object
                    
                
    

    ...

checkPermissions 方法

public class ImageGalleryFragment extends Fragment 

    ...

    private void checkPermissions(final Context context) 
    int currentAPIVersion = Build.VERSION.SDK_INT;

    if (currentAPIVersion >= android.os.Build.VERSION_CODES.M) 
        // Access coarse location permission check
        if (ContextCompat.checkSelfPermission(this.getActivity(),
                Manifest.permission.ACCESS_COARSE_LOCATION) !=
                PackageManager.PERMISSION_GRANTED) 
            // Check if explanation required
            if (ActivityCompat.shouldShowRequestPermissionRationale(this.getActivity(),
                    Manifest.permission.ACCESS_COARSE_LOCATION)) 
                // Provide explanation
                AlertDialog.Builder alertBuilder = new android.support.v7.app.AlertDialog.Builder(context);
                alertBuilder.setCancelable(true);
                alertBuilder.setTitle("Permission necessary");
                alertBuilder.setMessage("Access coarse location permission is necessary to save location to images");
                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_COARSE_LOCATION, REQUEST_COARSE_LOCATION);
                    
                );
                AlertDialog alert = alertBuilder.create();
                alert.show();
            
            else 
                // No explanation required, request permission
                ActivityCompat.requestPermissions(this.getActivity(),
                        new String[]Manifest.permission.ACCESS_COARSE_LOCATION,
                        REQUEST_COARSE_LOCATION);
            
        


        if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) 
            if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)) 
                AlertDialog.Builder alertBuilder = new android.support.v7.app.AlertDialog.Builder(context);
                alertBuilder.setCancelable(true);
                alertBuilder.setTitle("Permission necessary");
                alertBuilder.setMessage("Reading external storage 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.READ_EXTERNAL_STORAGE, REQUEST_READ_EXTERNAL_STORAGE);
                    
                );
                AlertDialog alert = alertBuilder.create();
                alert.show();

             else 
                ActivityCompat.requestPermissions(getActivity(), new String[]Manifest.permission.READ_EXTERNAL_STORAGE, REQUEST_READ_EXTERNAL_STORAGE);
            

        
        if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) 
            if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) 
                android.support.v7.app.AlertDialog.Builder alertBuilder = new android.support.v7.app.AlertDialog.Builder(context);
                alertBuilder.setCancelable(true);
                alertBuilder.setTitle("Permission necessary");
                alertBuilder.setMessage("Writing external storage 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.WRITE_EXTERNAL_STORAGE, REQUEST_WRITE_EXTERNAL_STORAGE);
                    
                );
                android.support.v7.app.AlertDialog alert = alertBuilder.create();
                alert.show();

             else 
                ActivityCompat.requestPermissions(getActivity(), new String[]Manifest.permission.WRITE_EXTERNAL_STORAGE, REQUEST_WRITE_EXTERNAL_STORAGE);
            

        

    


    ...



【问题讨论】:

您是否在 AndroidManifest.xml 文件中添加了位置权限? @hardartcore 是的,刚刚编辑了我的问题以包含清单权限 对不起,我刚刚看到......你做错了。您正在检查权限状态,但实际上您并不真正关心是否可以使用该位置并直接调用“getLastLocation”。您在这里有几个选项,但您可以尝试编辑“checkPermissions”并使其返回布尔值(如果已授予权限),如果为真,则尝试获取最后一个位置。 啊,好吧,我将如何创建一个布尔 checkLocationPermission() 方法以在授予权限后返回 true? 'ContextCompat.checkSelfPermission' 已经在这样做了。如果您的应用程序可以使用该位置,它会返回。也许从该方法返回布尔值并不是一个很好的选择,这只是一个想法。您可以创建不同的场景如何正确处理这种情况:) 这完全取决于您 【参考方案1】:

您已经实现了检查权限代码,但您弄错了。这是做好的路线图。,

    当片段/活动开始时,向用户询问位置或在您需要访问用户位置的操作上。 当用户授予位置权限时,然后获取位置(仅在这种情况下,您将收到您所指出的错误) 当用户允许你的位置权限时,你可以在 @Override 中得到它的结果 公共无效 onRequestPermissionsResult(int requestCode, 字符串权限[], int[] grantResults) 切换(请求代码)

我坚信您在以下行中遇到错误

 mFusedLocationClient.getLastLocation()
            .addOnSuccessListener(this.getActivity(), new OnSuccessListener<Location>() 
                @Override
                public void onSuccess(Location location) 
                    // Got last known location. In some rare situations this can be null.
                    if (location != null) 
                        // Logic to handle location object
                    
                

所以你必须向用户表明你必须允许位置来保持应用程序的工作,如果该权限是必要的,你可以显示 RequestPermissionRationale 对话框,如果他取消它,你可以简单地退出活动。

我也看到您对如何请求运行时权限没有明确的概念。我看到你一次检查了所有的权限。

这不是正确的方法。对于不同的权限,您必须一一询问。例如,您可以询问位置,如果应用程序需要太多,如果用户不允许,您可以退出活动,或者如果用户允许,您可以继续请求读取/写入外部存储权限。

这就是请求权限的流程。这是link,看看他是如何获得许可的。在这里您可以看到本教程中的多个权限。

【讨论】:

以上是关于检查用户位置的权限的主要内容,如果未能解决你的问题,请参考以下文章

即使用户授予位置权限检查,三星 note 20 也总是会被拒绝

如何修复“代码应明确检查权限是不是可用”错误

位置权限检查和授权

Laravel 5 检查权限

如何在 Flutter 中请求和检查权限

强制关闭 Android 位置权限