我最近做了一个蓝牙扫描Demo需要将经典蓝牙与BLE低功耗蓝牙进行分开扫描并且显示,发现了一些问题在次总结一下,首先是Android 6.0以后扫描蓝牙需要与定位权限,否则扫描不到。自己写的Demo是前30秒扫描经典蓝牙,后30秒扫描BLe蓝牙,按下扫描键是变成停止,停止扫描工作,再次点击为扫描。
申请蓝牙权限,首先需要自己写一个方法,requestPermission()这个方法用来判断自己是否拥有权限以及没有是申请权限。
checkSelfPermission方法的返回值不等于PERMISSION_GRANTED时没有权限,PERMISSION_GRANTED是个静态常量是0,也就是checkSelfPermission返回值是1是没有权限。
private void requestPermission() {
if (Build.VERSION.SDK_INT >= 23) {
int checkAccessFinePermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
//检查是否拥有权限
if (checkAccessFinePermission != PackageManager.PERMISSION_GRANTED) {
//没有权限,申请权限回调onRequestPermissionsResult方法
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_PERMISSION_ACCESS_LOCATION);
Log.e(getPackageName(), "没有权限,请求权限");
return;
}
Log.e(getPackageName(), "已有定位权限");
startDiscovery();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case 1: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.e(getPackageName(), "开启权限permission granted!");
//做下面该做的事
startDiscovery();
} else {
Log.e(getPackageName(), "没有定位权限,请先开启!");
}
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
下面是经典蓝牙扫描,通过广播,回调onReceive方法扫描到蓝牙设备
注册广播
private void registerBroadcast() {
// Register for broadcasts when a device is discovered
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(myReceive, filter);
// Register for broadcasts when discovery has finished
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(myReceive, filter);
}
调用startDiscovery方法开始扫描经典蓝牙
public void startDiscovery() {
if (blueToothAdapter.isDiscovering())
blueToothAdapter.cancelDiscovery();
blueToothAdapter.startDiscovery();
Log.e("MAinActivity","执行了Discovery ");
}
经典蓝牙扫描广播的回调方法
private final int addclassic=5;
@Override
public void onReceive(Context context, Intent intent) {
Log.d("BluetoothRecrive","开始扫描classic");
if(BluetoothDevice.ACTION_FOUND.equals(intent.getAction()))
{
BluetoothDevice device=intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if(device.getAddress()!=null)
{ //通过Handler传值
blue bb=new blue(device.getName(),device.getAddress());//自定义类放入进行数据的发送
Message msg = new Message();
msg.what =addclassic;
Bundle b = new Bundle();
b.putSerializable("CLASSIC", bb);
msg.setData(b);
Handler handler=MainActivity.handlerOPeration.getHandler();//自己写的方法获取Activity的Handler对象
handler.sendMessage(msg);
}
}else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(intent.getAction())) {
Log.d("BlutoothReceive","开始搜索");
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(intent.getAction())) {
Log.d("BlutoothReceive","完成搜索");
}
}
顺便提供一下获取Handler对象的工具类吧,直接Set,Get方法就行了
public class HandlerOPeration extends Application {
private Handler mHandler;
@Override
public void onCreate()
{
super.onCreate();
}
//该方法用于保存要传递的handler
public void setHandler( Handler handler) {
this.mHandler = handler;
}
//该方法用于获取要传递的handler
public Handler getHandler() {
return mHandler;
}
}
下面是BLE低功耗蓝牙的扫描代码,回调ScanCallBack方法扫描蓝牙
Callback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
BluetoothDevice device = result.getDevice();
Log.d("Blescan", "开始扫描BLE");
if(device.getAddress()!=null){
//Handler进行数据传输
blue bb = new blue(device.getName(), device.getAddress());
Message msg = new Message();
msg.what = addble;
Bundle b = new Bundle();
b.putSerializable("BLE", bb);
msg.setData(b);
Handler handler = MainActivity.handlerOPeration.getHandler();
handler.sendMessage(msg);
}
}
@Override
public void onBatchScanResults(List results) {
super.onBatchScanResults(results);
}
@Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
Log.e("Blescan", "搜索失败");
}
};
开启BLE蓝牙扫描以及关闭
/**
* 开启蓝牙
*/
public void startBlue(){
if(mScanning){
mScanning = false;
//开始扫描并设置回调
scanner.startScan(Callback);
}
}
/**
* 停止蓝牙扫描
*/
public void stopBlue(){
if(!mScanning){
//结束蓝牙扫描
mScanning=true;
scanner.stopScan(Callback);
}
}
Handler通信逻辑
public Handler mhandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
ListOperation listOperation=new ListOperation();
handlerOPeration.setHandler(mhandler);
switch (msg.what) {
case addclassic://listview1的数据接收
blue user = (blue) msg.getData().getSerializable("CLASSIC");
if(listOperation.RemoveRepeat(list_classic,user)==true){//去除扫描到的重复的蓝牙设备,listOperation.RemoveRepeat这是自己写的方法
list_classic.add(user);
blueAdapter_classic.notifyDataSetChanged(); //发现新的设备更新UI
Log.d("listviewclassic", "姓名" + user.getName() + "地址 " + user.getAddress());
break;
}
break;
case addble:
blue ble = (blue) msg.getData().getSerializable("BLE");
if(listOperation.RemoveRepeat(list_ble,ble)==true){
list_ble.add(ble);
blueAdapter_ble.notifyDataSetChanged(); //发现新的设备更新UI
Log.d("listviewBLE", "姓名" + ble.getName() + "地址 " + ble.getAddress());
break;
}
break;
case scanble: //扫描BLE
blueToothAdapter.cancelDiscovery();
if(flag==true) {//只在扫描的状态下执行下面代码
//blueAdapter_classic.notifyDataSetChanged();
blescan.getInitialization(MainActivity.this);
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Log.e("MainActivity", "支持BLE");
} else {
Log.e("MainActivity", "bu支持BLE");
}
blescan.startBlue(); //开始扫描BLE
Toast.makeText(MainActivity.this, "开始扫描BLE蓝牙", Toast.LENGTH_SHORT).show();
break;
}else {
break;
}
case scanclassic: //扫描经典蓝牙
Toast.makeText(MainActivity.this,"开始扫描经典蓝牙",Toast.LENGTH_SHORT).show();
blueToothAdapter.enable();
requestPermission(); //请求定位权限
break;
case stop:
//blueAdapter_classic.notifyDataSetChanged();
//blueAdapter_ble.notifyDataSetChanged(); //发现新的设备更新UI
mhandler.removeMessages(scanble);//清空消息队列
mhandler.removeMessages(stop);
mhandler.removeMessages(scanclassic);
blueToothAdapter.cancelDiscovery(); //结束经典蓝牙扫描
//blueToothAdapter.disable();
blescan.stopBlue(); //结束BLE扫描
button.setText(MainActivity.this.getString(R.string.scan));
flag = false;
Log.d("BlutoothReceive", "停止");
break;
default:
break;
}
return false;
}
});
刚刚开始写博客,写的比较乱,多多谅解,不明白的可以多交流,
把源码也放进来吧
https://download.csdn.net/download/weixin_38916092/10642271