0

我正在尝试让一个简单的蓝牙 LE 扫描应用程序在 Android 10 下运行

扫描开始但未发现设备。

关于 Android 10 所需的正确权限有很多流量,我认为我的权限是正确的,目前,我要求并要求用户:

BLUETOOTH BLUETOOTH_ADMIN ACCESS_FINE_LOCATION FOREGROUND_SERVICE ACCESS_BACKGROUND_LOCATION

该应用程序很简单,只有一个表单、一个开始扫描按钮、一个停止扫描按钮和一个显示结果的文本视图。

有人可以指出我错过了什么吗?

非常感谢

public class MainActivity extends AppCompatActivity {

BluetoothAdapter btAdapter;
BluetoothLeScanner btScanner;

Button startScanningButton;
Button stopScanningButton;
TextView peripheralTextView;


private static final int REQUEST_ENABLE_BT = 1;
private static final int PERMISSION_REQUEST_FINE_LOCATION = 1;
private static final int PERMISSION_REQUEST_BACKGROUND_LOCATION = 2;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    BottomNavigationView navView = findViewById(R.id.nav_view);
    // Passing each menu ID as a set of Ids because each
    // menu should be considered as top level destinations.
    AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
            R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications)
            .build();
    NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
    NavigationUI.setupWithNavController(navView, navController);


    peripheralTextView = (TextView) findViewById(R.id.PeripheralTextView);
    peripheralTextView.setMovementMethod(new ScrollingMovementMethod());

    startScanningButton = (Button) findViewById(R.id.StartScanButton);
    startScanningButton.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            startScanning();
        }
    });

    stopScanningButton = (Button) findViewById(R.id.StopScanButton);
    stopScanningButton.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            stopScanning();
        }
    });
    stopScanningButton.setVisibility(View.INVISIBLE);


    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (this.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            if (this.checkSelfPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
                    != PackageManager.PERMISSION_GRANTED) {
                if (this.shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_BACKGROUND_LOCATION)) {
                    final AlertDialog.Builder builder = new AlertDialog.Builder(this);
                    builder.setTitle("This app needs background location access");
                    builder.setMessage("Please grant location access so this app can detect beacons in the background.");
                    builder.setPositiveButton(android.R.string.ok, null);
                    builder.setOnDismissListener(new DialogInterface.OnDismissListener() {

                        @TargetApi(23)
                        @Override
                        public void onDismiss(DialogInterface dialog) {
                            requestPermissions(new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION},
                                    PERMISSION_REQUEST_BACKGROUND_LOCATION);
                        }

                    });
                    builder.show();
                }
                else {
                    final AlertDialog.Builder builder = new AlertDialog.Builder(this);
                    builder.setTitle("Functionality limited");
                    builder.setMessage("Since background location access has not been granted, this app will not be able to discover beacons in the background.  Please go to Settings -> Applications -> Permissions and grant background location access to this app.");
                    builder.setPositiveButton(android.R.string.ok, null);
                    builder.setOnDismissListener(new DialogInterface.OnDismissListener() {

                        @Override
                        public void onDismiss(DialogInterface dialog) {
                        }

                    });
                    builder.show();
                }

            }
        } else {
            if (!this.shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) {
                requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
                                Manifest.permission.ACCESS_BACKGROUND_LOCATION},
                        PERMISSION_REQUEST_FINE_LOCATION);
            }
            else {
                final AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle("Functionality limited");
                builder.setMessage("Since location access has not been granted, this app will not be able to discover beacons.  Please go to Settings -> Applications -> Permissions and grant location access to this app.");
                builder.setPositiveButton(android.R.string.ok, null);
                builder.setOnDismissListener(new DialogInterface.OnDismissListener() {

                    @Override
                    public void onDismiss(DialogInterface dialog) {
                    }

                });
                builder.show();
            }

        }
    }


    final BluetoothManager btManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);

    btAdapter = btManager.getAdapter();

    if (btAdapter == null || !btAdapter.isEnabled()) {
        Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableIntent,REQUEST_ENABLE_BT);
    }


    btScanner = btAdapter.getBluetoothLeScanner();

}


// Device scan callback.
private ScanCallback leScanCallback = new ScanCallback() {
    @Override
    public void onScanResult(int callbackType, ScanResult result) {
        peripheralTextView.append("Device Name: " + result.getDevice().getName() + " rssi: " + result.getRssi() + "\n");
    }
};

@Override
public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    switch (requestCode) {
        case PERMISSION_REQUEST_FINE_LOCATION: {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                System.out.println("fine location permission granted");
            } else {
                final AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle("Functionality limited");
                builder.setMessage("Since location access has not been granted, this app will not be able to discover devices when in the background.");
                builder.setPositiveButton(android.R.string.ok, null);
                builder.setOnDismissListener(new DialogInterface.OnDismissListener() {

                    @Override
                    public void onDismiss(DialogInterface dialog) {
                    }

                });
                builder.show();
            }
            return;
        }
    }
}

public void startScanning() {
    peripheralTextView.setText("");
    peripheralTextView.append("Start Scanning");
    startScanningButton.setVisibility(View.INVISIBLE);
    stopScanningButton.setVisibility(View.VISIBLE);
    AsyncTask.execute(new Runnable() {
        @Override
        public void run() {
            btScanner.startScan(leScanCallback);
        }
    });
}

public void stopScanning() {
    peripheralTextView.append("Stopped Scanning");
    startScanningButton.setVisibility(View.VISIBLE);
    stopScanningButton.setVisibility(View.INVISIBLE);
    AsyncTask.execute(new Runnable() {
        @Override
        public void run() {
            btScanner.stopScan(leScanCallback);
        }
    });
}

}

4

3 回答 3

1

似乎蓝牙扫描已禁用。请在下面找到截图。只有位置启用将无法与您需要启用蓝牙扫描的位置一起使用。

蓝牙扫描

于 2020-06-02T13:04:21.380 回答
0

我知道我有点晚了,但我希望这对某人有所帮助。

这些权限是正确的。您没有启用位置服务,这是您的问题。

看看这个。正如你所看到的,有很多关于谷歌为什么要这样做的讨论。在问题的最后,有一个 Youtube 视频链接(见这里),Chet解释说,即使是谷歌也不知道那是什么,所以他们在 A12 中添加了新的权限。

Android 10 权限:
在 Android 10 上,您通常必须获得 ACCESS_BACKGROUND_LOCATION 才能在您的应用不可见时进行信标检测。但是,如果您将 android:foregroundServiceType="location" 添加到清单中的前台服务声明中,则可以仅在授予前台位置权限和前台服务的情况下进行扫描。有关详细信息,请参见此处

因此,启用位置服务将足以让您获得结果

bluetoothMangaer.adapter.startScan(scanCallback)

如果您不希望用户启用他的位置,您可以执行

bluetoothMangaer.adapter.startDiscovery()
于 2021-07-28T11:52:40.763 回答
0

似乎与适配器本身导致问题有关,查看 logcat 我在 startscanning 调用中得到状态 = 133,重置物理适配器清除了问题并开始出现扫描结果

于 2020-02-23T10:43:26.290 回答