Android 10蓝牙LE扫描问题

时间:2020-02-22 17:56:09

标签: android bluetooth android-10.0 bluetoothlescanner

我正在尝试让一个简单的Bluetooth LE Scanning应用程序在Android 10下运行

扫描开始,但没有发现设备。

关于Android 10所需的正确权限的流量很大,我想我已经正确了,目前,我需要并向用户询问:

蓝牙 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);
        }
    });
}

}

3 个答案:

答案 0 :(得分:0)

似乎与适配器本身引起问题有关,看着logcat,我在startscanning调用中得到status = 133,重置物理适配器可以清除问题,并开始出现扫描结果

答案 1 :(得分:0)

似乎蓝牙扫描已禁用。请在下面的屏幕截图中找到。仅启用位置功能无法与启用蓝牙扫描所需的位置一起使用。

Bluetooth Scanning

答案 2 :(得分:0)

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

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

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

还有

<块引用>

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

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

bluetoothMangaer.adapter.startScan(scanCallback)

如果你不希望用户启用他的位置,你可以做一个

bluetoothMangaer.adapter.startDiscovery()