首先Android6.0以上的系统的很大的变化就是权限机制的变化,具体的可以看看鸿大佬的这篇文章:http://blog.csdn.net/lmj623565791/article/details/50709663
然后就是对蓝牙4.0 BLE的开发的一些小变化。
本篇文章主要讲关于蓝牙开发的,但是后面会用到运行时权限的知识,所以不了解的可以看看上面那篇文章。
在Android6.0以下,我们进行蓝牙开发只需要这两个权限。
<!--蓝牙4.0需要的权限-->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
但是在Android6.0以上,我们不声明其他权限,在调用扫描蓝牙设备的API时会抛出一个SecurityException异常,并且不会进行扫描。
这个异常就说需要ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION权限,那我们就在AndroidManifest.xml中声明任意一个权限。
<!--安卓6.0以上,想扫描蓝牙设备需要此权限,并且需要开启GPS-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
但是只在AndroidManifest.xml中声明并没有什么用,还是会抛出异常,因为这是个Security权限,需要在运行的时候询问用户授权,所以添加如下代码。
if (Build.VERSION.SDK_INT >= 23) {
//安卓6.0以上,需要手动授权危险权限
if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
//没有授权需要授权
Log.d(TAG, "这个权限还没有进行授权");
if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) mContext,
Manifest.permission.ACCESS_COARSE_LOCATION)) {
//如果第一次授权用户拒绝了,再次需要授权的时候就进到这里,进行解释,这里第一次不会进入
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setTitle("权限解释")
.setMessage("扫描蓝牙设备需要位置信息,并且需要开启GPS,所以你必须要授权这个权限。")
.setPositiveButton("好的", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions((Activity) mContext,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION);
dialog.dismiss();
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
Toast.makeText(mContext, "取消授权,无法进行扫描", Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
})
.show();
} else {
//进行询问授权
ActivityCompat.requestPermissions((Activity) mContext,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION);
}
return;
}
}
运行时授权的代码添加了,也授权了,但还是扫描不出来设备,那看下这两个权限,ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION,都是跟位置信息有关的,那尝试一下开启GPS,果然,开启GPS后,我们扫描到了蓝牙设备。6.0以上,扫描蓝牙设备,需要开启GPS,不知道为什么。
提示用户开启GPS的代码。
if (Build.VERSION.SDK_INT >= 23) {
if (!Utils.checkGpsIsOpen(mContext)) { //如果没有开启
Log.d(TAG, "请求开启GPS");
new AlertDialog.Builder(mContext)
.setTitle("请开启GPS")
.setMessage("安卓6.0以上扫描蓝牙设备需要开启GPS")
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
dialog.dismiss();
}
})
.setPositiveButton("设置", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
//跳转GPS设置界面
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
((Activity) mContext).startActivityForResult(intent, OPEN_GPS_REQUEST_CODE);
}
})
.setCancelable(true)
.show();
return;
}
}
public class Utils {
/**
* 判断GPS是否开启,GPS或者AGPS开启一个就认为是开启的
*
* @param context
* @return true 表示开启
*/
public static final boolean checkGpsIsOpen(final Context context) {
boolean isOpen;
LocationManager locationManager = (LocationManager)
context.getSystemService(Context.LOCATION_SERVICE);
isOpen = locationManager.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER);
return isOpen;
}
}
总结
Android6.0以上的系统,
1.权限需要蓝牙权限和位置信息权限。
2.要开启蓝牙和GPS。