我正在尝试让一个简单的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);
}
});
}
}
答案 0 :(得分:0)
似乎与适配器本身引起问题有关,看着logcat,我在startscanning调用中得到status = 133,重置物理适配器可以清除问题,并开始出现扫描结果
答案 1 :(得分:0)
答案 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()