注意的问题
1:添加权限
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
2:添加运行时权限(SDK23以上一定要加,我就是没加怎么都搞不出来,弄了半天,嘤嘤嘤)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION ,
Manifest.permission.CAMERA,}, 1);
}
**
:**
首先添加手机中已经配对好的蓝牙设备到 mBluetoothAdapter(也可以不用创建BluetoothAdapter对象即可)。
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
方式1,startLeScan()方法
startLeScan()方法有一个回调参数BluetoothAdapter.LeScanCallback 类,先创建这个类的对象,在扫描找到周围的蓝牙设备时,会返回到 onLeScan 函数,可以在 onLeScan 函数中处理逻辑
BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
lv_bluetooth.setAdapter(mArrayAdapter);
Log.d(TAG, "onLeScan:563463 ");
}
};
然后再用 startLeScan()方法扫描
mBluetoothAdapter.startLeScan(mLeScanCallback);
startLeScan()方法的特点:在onLeScan() 中不能做耗时操作,特别是周围的BLE设备多的时候,容易导致底层堵塞
这个方法用到广播。
所以先定义一个类SingBroadcastReceiver,让他继承自BroadcastReceiver ,并重写onReceive()方法,在该方法中写扫描到设备时的逻辑。
class SingBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action) ){
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Add the name and address to an array adapter to show in a Toast
String derp = device.getName() + " - " + device.getAddress();
Toast.makeText(context, derp, Toast.LENGTH_LONG).show();
}
}
}
然后创建SingBroadcastReceiver对象,注册广播,再执行startDiscovery()方法
SingBroadcastReceiver mReceiver=new SingBroadcastReceiver ();
mBluetoothAdapter.startDiscovery();
IntentFilter ifilter1= new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, ifilter1);
对于经典蓝牙设备,扫描是通过调用startDiscovery接口,返回的结果是通过BroadcastReceiver接收的,可以获取设备MAC地址,名称以及RSSI。startDiscovery是个异步调用,会立即返回。如果不调用cancelDiscovery主动停止扫描的话,最多扫描12s。广播主要监听以下几个Action:BluetoothDevice.ACTION_FOUNDBluetoothAdapter.ACTION_DISCOVERY_STARTEDBluetoothAdapter.ACTION_DISCOVERY_FINISHED另外要注意startDiscovery返回的设备不包括已配对设备,如要获取已配对设备,需要额外调用getBondedDevices。
我比较喜欢用startDiscovery(),所以是用这个startDiscovery()写的。
public class MainActivity extends AppCompatActivity {
private ListView lv_bluetooth;//用于显示蓝牙设备
private SingBroadcastReceiver mReceiver;//这个我自定义的一个广播接收器
private ArrayAdapter<String> mArrayAdapter;//一个简单的适配器
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//实例化
lv_bluetooth=findViewById(R.id.lv_bluetooth);
Button button_find=findViewById(R.id.find);
Button button_cancel=findViewById(R.id.cancel);
mArrayAdapter=new ArrayAdapter<String >(
MainActivity.this,android.R.layout.simple_list_item_1
);
//运行时权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION ,
Manifest.permission.CAMERA,}, 1);
}
final BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
//注册广播
mReceiver = new SingBroadcastReceiver();
IntentFilter ifilter1= new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, ifilter1);
//扫描
button_find.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mBluetoothAdapter.startDiscovery();
lv_bluetooth.setAdapter(mArrayAdapter);
}
});
//停止扫描
button_cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mBluetoothAdapter.cancelDiscovery();
}
});
}
//广播接收器
class SingBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action) ){
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
//下面的代码的效果是不让已经扫描到的设备重复显示
Boolean isRepetition=false;
for(int i=0;i<mArrayAdapter.getCount();i++)
{
if((device.getName()+"-"+device.getAddress()).equals(mArrayAdapter.getItem(i).toString()))
{
isRepetition=true;
}
}
if(!isRepetition){
mArrayAdapter.add(device.getName()+"-"+device.getAddress());
}
}
}
}
}