代码如下:
1.MainActivity部分
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private BluetoothAdapter mBluetoothAdapter;
private RecyclerView mRecyclerView;
private ScanResultAdapter mScanResultAdapter;
private BluetoothLeScanner mBluetoothLeScanner;
private Button mStartScaleButton,mStopScaleButton;
private static final int REQUEST_CODE_ACCESS_COARSE_LOCATION = 1; //动态申请权限
private static final int SCAN_START = 1000; //开始搜索
private static final int SCAN_TIME = 10 * 1000; //扫描时间
private static final String TAG = "BLE";
private List<ScanResult> mList = new ArrayList<>();
private List<String> mListAddress = new ArrayList<>();
private Handler mHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message msg) {
switch (msg.what){
case SCAN_START:
scanBluetooth(false);
}
return false;
}
});
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
SetOnClickListener();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {//如果 API level 是大于等于 23(Android 6.0) 时
//判断是否具有权限
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
//判断是否需要向用户解释为什么需要申请该权限
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_COARSE_LOCATION)) {
Toast.makeText(MainActivity.this, "自Android 6.0开始需要打开位置权限才可以搜索到Ble设备", Toast.LENGTH_LONG).show();
}
//请求权限
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
REQUEST_CODE_ACCESS_COARSE_LOCATION);
}
}
}
private void initView(){
/*找到控件*/
mStartScaleButton = findViewById(R.id.bt_1);
mStopScaleButton = findViewById(R.id.bt_2);
mRecyclerView = findViewById(R.id.rv_1);
mRecyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL));
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mScanResultAdapter = new ScanResultAdapter(this,mList);
mRecyclerView.setAdapter(mScanResultAdapter);
mScanResultAdapter.setOnItemClickListener(new ScanResultAdapter.OnItemClickListener() {
@Override
public void OnClick(int position) {
scanBluetooth(false);
ScanResult scanResult = mList.get(position);
}
});
/*获取本地蓝牙适配器*/
BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, "设备不支持BLE", Toast.LENGTH_SHORT).show();
finish();
}
/*打开蓝牙*/
if(mBluetoothAdapter == null ||!mBluetoothAdapter.isEnabled()){
Intent TrunOnBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(TrunOnBtIntent,0);
}
}
/*控件点击事件*/
private void SetOnClickListener(){
mStartScaleButton.setOnClickListener(this);
mStopScaleButton.setOnClickListener(this);
}
/*对应控件执行相关操作*/
@Override
public void onClick(View v){
switch (v.getId()){
case R.id.bt_1:
scanBluetooth(true);
Toast.makeText(MainActivity.this,"扫描",Toast.LENGTH_LONG).show();
break;
case R.id.bt_2:
scanBluetooth(false);
break;
}
}
/*开始搜索设备及停止搜索设备函数*/
private void scanBluetooth(boolean isSan){
if(isSan==true){
mBluetoothLeScanner.startScan(mScanCallback);
mHandler.sendEmptyMessageDelayed(SCAN_START,SCAN_TIME);//定时搜索蓝牙设备
}else {
mBluetoothLeScanner.stopScan(mScanCallback);
if(mHandler.hasMessages(SCAN_START)){
mHandler.removeMessages(SCAN_START);
}
}
}
/*搜索的回调函数*/
private ScanCallback mScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
Log.i(TAG,"result:" + result + "callbackType:" + callbackType);
/*通过扫描到的设备地址与新扫描的地址作比较,避免重复*/
if(!mListAddress.contains(result.getDevice().getAddress())){
mList.add(result);
mListAddress.add(result.getDevice().getAddress());
}
super.onScanResult(callbackType, result);
}
@Override
/*扫描失败的处理*/
public void onScanFailed(int errorCode){
Log.e(TAG,"onScanFailed:" + errorCode);
}
};
}
2.ScanResultAdapter部分
public class ScanResultAdapter extends RecyclerView.Adapter<ScanResultAdapter.ViewHolder> {
private Context mContext;
private List<ScanResult> mList;
private LayoutInflater inflater;
private OnItemClickListener onItemClickListener;
public ScanResultAdapter(Context mContext,List<ScanResult>mList){
this.mContext = mContext;
this.mList = mList;
inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener){
this.onItemClickListener = onItemClickListener;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ViewHolder(inflater.from(mContext).inflate(R.layout.layout_scanadapter_item,parent,false));
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
ScanResult scanResult = mList.get(position);
holder.tv_name.setText("设备名:"+scanResult.getDevice().getName());
holder.tv_address.setText("设备地址:"+scanResult.getDevice().getAddress());
holder.tv_rssi.setText("信号:"+scanResult.getRssi());
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(null != onItemClickListener){
onItemClickListener.OnClick(position);
}
}
});
}
@Override
public int getItemCount() {
return mList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
private TextView tv_name;
private TextView tv_address;
private TextView tv_rssi;
public ViewHolder(@NonNull View itemView) {
super(itemView);
tv_name = itemView.findViewById(R.id.tv_name);
tv_address = itemView.findViewById(R.id.tv_address);
tv_rssi = itemView.findViewById(R.id.tv_rssi);
}
}
public interface OnItemClickListener{
void OnClick(int position);
}
}
另:测试手机为小米mix2s,SDK版本为29