关于在Android6.0以上系统的BLE开发

首先Android6.0以上的系统的很大的变化就是权限机制的变化,具体的可以看看鸿大佬的这篇文章:http://blog.csdn.net/lmj623565791/article/details/50709663
然后就是对蓝牙4.0 BLE的开发的一些小变化。
本篇文章主要讲关于蓝牙开发的,但是后面会用到运行时权限的知识,所以不了解的可以看看上面那篇文章。

在Android6.0以下,我们进行蓝牙开发只需要这两个权限。

    
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

但是在Android6.0以上,我们不声明其他权限,在调用扫描蓝牙设备的API时会抛出一个SecurityException异常,并且不会进行扫描。
关于在Android6.0以上系统的BLE开发_第1张图片
这个异常就说需要ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION权限,那我们就在AndroidManifest.xml中声明任意一个权限。

    
    <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。

你可能感兴趣的:(Android)