Android BLE 权限

Android BLE permissions

[Google 已翻译]

该应用程序适用于 BLE 设备。我在 Android 10 上调试了它,一切正常。我决定检查 8.0,发现搜索不起作用。从日志来看,很可能是权限问题,但我找不到错误。

P.S。 code部分不是我的,如果有详细的解释我将不胜感激。

清单:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION" />

代码:

    public void startScan() {

    if (!bluetoothAdapter.isEnabled()) {
        checkBluetoothState();
        return;
    }
    /*
    PERMISSIONS_CHECK
     */
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            scanState = ScanState.NONE;
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle(R.string.location_permission_title);
            builder.setMessage(R.string.location_permission_message);
            builder.setPositiveButton(android.R.string.ok,
                    (dialog, which) -> requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 0));
            builder.show();
            return;
        }
        LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
        locationEnabled = false;
        try {
            locationEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        } catch(Exception ignored) {}
        try {
            locationEnabled |= locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        } catch(Exception ignored) {}
        if(!locationEnabled)
            scanState = ScanState.DISCOVERY;
        // Starting with Android 6.0 a bluetooth scan requires ACCESS_COARSE_LOCATION permission, but that's not all!
        // LESCAN also needs enabled 'location services', whereas DISCOVERY works without.
        // Most users think of GPS as 'location service', but it includes more, as we see here.
        // Instead of asking the user to enable something they consider unrelated,
        // we fall back to the older API that scans for bluetooth classic _and_ LE
        // sometimes the older API returns less results or slower
    }

    if (!locationEnabled) {
        return;
    }

    if(scanState != ScanState.NONE)
        return;
    scanState = ScanState.LESCAN;

    listItems.clear();
    foundListAdapter.notifyDataSetChanged();
    tvNoDeviceFound.setVisibility(View.INVISIBLE);

    if(scanState == ScanState.LESCAN) {
        leScanStopHandler.postDelayed(this::stopScan, LESCAN_PERIOD);

        new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void[] params) {
                bluetoothAdapter.startLeScan(null,leScanCallback);
                Log.d(TAG, "starLetScan: scanning");
                return null;

            }
        }.execute();// start async to prevent blocking UI, because startLeScan sometimes take some seconds
    } else {
        bluetoothAdapter.startDiscovery();
    }
    if(scanState == ScanState.LESCAN) {
        pbSearch.setVisibility(View.VISIBLE);
        btnSearch.setVisibility(View.GONE);
    }
}

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            // ignore requestCode as there is only one in this fragment
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
               startScan();
               locationEnabled = true;
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !shouldShowRequestPermissionRationale(permissions[0])) {
    
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle(R.string.location_permission_title);
                builder.setMessage(R.string.location_permission_message_clarification);
                builder.setPositiveButton(R.string.location_permission_go_to_settings, (dialogInterface, i) -> {
                    Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                            Uri.fromParts("package", getPackageName(), null));
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(intent);
                });
                builder.show();
            } else {
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle(getText(R.string.location_denied_title));
                builder.setMessage(getText(R.string.location_denied_message));
                builder.setPositiveButton(android.R.string.ok, null);
                builder.show();
            }
        }

phone 上的 gps 已激活?阅读官方文档可能会对您有所帮助 (Android developer guide)。

在我的一个应用程序中,我使用了 BluetoothLeScannerCompat (BluetoothLeScannerCompat),它在 android 10 android 8.0

中都工作正常

我给你看一个实用程序class,我用它来显示所有必要的权限(可能会帮助你解决)

public class PermissionUtils {
    public static void askForPermissions(Activity activity) {
        List<String> permissionsToAsk = new ArrayList<>();
        int requestResult = 0;

        if (ContextCompat.checkSelfPermission(activity.getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) !=
                PackageManager.PERMISSION_GRANTED) {
            // Ask for permission
            permissionsToAsk.add(Manifest.permission.ACCESS_FINE_LOCATION);
        }

        if (ContextCompat.checkSelfPermission(activity.getApplicationContext(), Manifest.permission.ACCESS_BACKGROUND_LOCATION) !=
                PackageManager.PERMISSION_GRANTED) {
            // Ask for permission
            permissionsToAsk.add(Manifest.permission.ACCESS_BACKGROUND_LOCATION);
        }

        if (ContextCompat.checkSelfPermission(activity.getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) !=
                PackageManager.PERMISSION_GRANTED) {
            // Ask for permission
            permissionsToAsk.add(Manifest.permission.ACCESS_COARSE_LOCATION);
        }

        if (ContextCompat.checkSelfPermission(activity.getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
                PackageManager.PERMISSION_GRANTED) {
            // Ask for permission
            permissionsToAsk.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
        }

        if (permissionsToAsk.size() > 0) {
            ActivityCompat.requestPermissions(activity, permissionsToAsk.toArray(new String[permissionsToAsk.size()]), requestResult);
        }
    }
}

并尝试在清单中添加所有这些:


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