前言
最近遇到一个吊诡的问题,开发的APP在 华为荣耀V20 的测试中发现无法扫描到蓝牙设备。而手机系统蓝牙可以扫描得到。打断点调试发现其扫描回调未执行…多次尝试未果。
开始以为是该机型特有的问题,随后偶然看到其为Android10
,这也是目前可供测试的唯一一部手机,考虑到安卓日益细分、严格的权限控制。我打开了 Android 10
隐私变更 ,终于解脱了。
原因
涉及到蓝牙功能如下,可以发现常用的扫描都需要…
解决方法
修改目标版本
解决不了问题,就解决提出问题的人。
既然是版本升级带来的权限细分,那么我们直接修改build.gradle
,将targetSdkVersion
改为27,问题解决。
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.example.felicitysolar_debug"
minSdkVersion 21
targetSdkVersion 29
versionCode 2
versionName "3.6"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
lintOptions {
checkReleaseBuilds false
abortOnError false
}
}
当然,这明显是剑走偏锋!
申请精确定位权限
正统做法来了:
首先需在AndroidManifest.xml
中加上如下权限:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
除此之外还需动态申请权限,这里参考了华为的例程:
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
Log.i(TAG, "sdk < 28 Q");
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
String[] strings =
{
Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION};
ActivityCompat.requestPermissions(this, strings, 1);
}
} else {
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(this,
"android.permission.ACCESS_BACKGROUND_LOCATION") != PackageManager.PERMISSION_GRANTED) {
String[] strings = {
android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION,
"android.permission.ACCESS_BACKGROUND_LOCATION"};
ActivityCompat.requestPermissions(this, strings, 2);
}
}
由于找不到强制开启GPS定位的方法,这里做个软提醒:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P){
LocationManager alm = (LocationManager)BLEActivity.this.getSystemService(Context.LOCATION_SERVICE);
if (!alm.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER)){
Toast.makeText(this, "请开启GPS!", Toast.LENGTH_SHORT).show();
}
}
一套组合拳下去,问题解决。