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" />
[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" />