在请求ACCESS_COARSE_LOCATION权限后,按下允许不打开位置 - 牛轧糖

时间:2016-12-18 14:53:13

标签: android beacon android-7.1-nougat

最后我遇到了问题,由于缺少ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION,我无法扫描信标。

我尝试使用找到的here代码修复它,但它实际上对我有所帮助。

此视图出现时enter image description here 我点击允许。之后我不会再出现此java.lang.SecurityException: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to get scan results错误,但我仍然无法看到我的信标,当我打开设置视图时,该位置会被关闭,如下图所示。

enter image description here

当我用手指打开位置时,一切正常,所以我可以看到我的信标和应用程序正常工作。这里有一个问题就是这些错误或者在打开访问设备位置后我错过了从代码后面打开位置的东西?

为了开发我使用Nexus 5x和android 7.1.1。

EDITED: 代码复制自上面链接的教程,带有按钮的片段启动信标扫描器:

 public void onBleClicked(View view)
    {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
            if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

                final AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle("This app needs location access");
                builder.setMessage("Please grant location access so this app can detect beacons.");
                builder.setPositiveButton(android.R.string.ok, null);
                builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
                    @Override
                    public void onDismiss(DialogInterface dialog) {

                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                                requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
                            }
                    }
                });
                builder.show();
            }
    BleManager bleManager = new BleManager(this);
    bleManager.tryToTurnOnBle();
}

声明权限的清单片段:

<!-- app only for phones -->
<uses-feature android:name="android.hardware.telephony"/>

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

蓝牙权限显然在库中。

我现在发现的事实是,我的here存在类似的问题。 但是这个将用户重定向到位置选项屏幕的解决方案对我来说似乎并不干净。

2 个答案:

答案 0 :(得分:2)

位置可以通过两种方式确定:

1.使用NETWORK_PROVIDER

2.使用GPS_PROVIDER

NETWORK_PROVIDER:它确定使用手机信号塔,wifi接入点的用户的位置。它通常用于确定房间或建筑物内的位置。 此处无法获取GPS坐标。

您可以指定

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

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

使用NETWORK_PROVIDER获取位置。

<强> GPS_PROVIDER: 它确定使用卫星的用户的位置。为此,获得GPS坐标并用于定位。智能手机中的GPS接收器接收来自卫星的信号。处理这些信号并确定精确的位置。它在户外工作得更好 - 直接天空/卫星视图和通信。

您需要指定权限

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

以便使用GPS_PROVIDER中的位置。

精美地点 它提供了更好,更准确的位置。所以,我建议你使用它来获取你的信标位置。它允许仅使用GPS_PROVIDER和NETWORK_PROVIDER或GPS_PROVIDER来确定位置。

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

现在,来实施吧。 - 在AnroidManifest.xml文件中声明上述两个权限: - 在java部分中,执行以下操作: 如果尚未批准,请申请许可:

private void requestPermission(Activity activity) {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CALL_PHONE}, MainActivity.PERMISSION_REQUEST_CODE_LOCATION);
} 

调用上述方法时,会出现一个询问权限的对话框。选择允许或拒绝时,将触发以下回调。

在onRequestPermissionsResult

@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case PERMISSION_REQUEST_CODE_LOCATION:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
                    boolean isGpsProviderEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
                    boolean isNetworkProviderEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
                    //Location permission is given. Check if the providers are available and start location updates.
                    if (isGpsProviderEnabled && isNetworkProviderEnabled) {
                        startLocationUpdates();
                    } else {
                        Log.d(TAG, "GPS and Network providers are disabled");
                    }
                } else if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_DENIED) {
                    boolean should = ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION);
                    if (should) {
                        ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MainActivity.PERMISSION_REQUEST_CODE_LOCATION);
                    } else {
                        promptSettings();
                    }
                }
        }
    }

在promptSettings()方法中,让用户从“设置”屏幕启用位置。

private void promptSettings() {
AlertDialog.Builder builder;

        builder = new AlertDialog.Builder(MainActivity.this);
        builder.setTitle(getResources().getString(R.string.unable_to_find_location));
        builder.setMessage(getResources().getString(R.string.message_denied_location_permission));
        builder.setCancelable(false);
        builder.setPositiveButton(getResources().getString(R.string.go_to_settings), (dialog, which) -> {
            dialog.dismiss();
            builder = null;
            if (!checkPermission(MainActivity.this)) {
                goToSettings();
            }
        });
        builder.show();
    }

在检查权限方法中:

public boolean checkPermission(Context context) {
    int result = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION);
    return result == PackageManager.PERMISSION_GRANTED;
}

goToSettings()允许用户进入设置屏幕:

private void goToSettings() {
        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = Uri.fromParts("package", getPackageName(), null);
        intent.setData(uri);
        startActivityForResult(intent, 1);
    }

注意:您需要在清单中提供以下权限才能扫描信标。我希望你这样做,如果没有,请你去做。

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

答案 1 :(得分:0)

从Android Marshmallow(6.0)开始,必须在应用程序的设置中打开位置,以便扫描包括信标在内的蓝牙LE设备。除了应用获得动态权限的要求之外,此要求。您可以查看下面的代码来查询正在启用的位置服务,并提示用户在需要时将其打开。

var path = require('path');
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', (req, res) => {
  res.sendFile(path.join(__dirname, 'si.html'));
});
io.on('connection', s => {
  for (var t = 0; t < 3; t++)
    setTimeout(() => s.emit('message', 'message from server'), 1000*t);
});
http.listen(3002, () => console.error('listening on http://localhost:3002/'));