项目要求实现蓝牙设备搜索连接,Android为蓝牙技术提供了4个工具类,分别是蓝牙适配器BluetoothAdapter、蓝牙设备BluetoothDevice、蓝牙服务端套接字BluetoothServerSocket和蓝牙客户端套接字BluetoothSocket。

蓝牙适配器BluetoothAdapter

BluetoothAdapter的作用其实跟其它的**Manger差不多,可以把它当作蓝牙管理器。下面是BluetoothAdapter的常用方法说明。

getDefaultAdapter:静态方法,获取默认的蓝牙适配器对象;
enable:打开蓝牙功能;
disable:关闭蓝牙功能;
isEnable:判断蓝牙功能是否打开;
startDiscovery:开始搜索周围的蓝牙设备;
cancelDiscovery:取消搜索操作;
isDiscovering:判断当前是否正在搜索设备;
getBondedDevices:获取已绑定的设备列表;
setName:设置本机的蓝牙名称;
getName:获取本机的蓝牙名称;
getAddress:获取本机的蓝牙地址;
getRemoteDevice:根据蓝牙地址获取远程的蓝牙设备;
getState:获取本地蓝牙适配器的状态;
listenUsingRfcommWithServiceRecord:根据名称和UUID创建并返回BluetoothServiceSocket;
listenUsingRfcommOn:根据渠道编号创建并返回BluetoothServiceSocket。

蓝牙设备BluetoothDevice

BluetoothDevice用于指代某个蓝牙设备,通常表示对方设备。BluetoothAdapter管理的是本机蓝牙设备。下面是BluetoothDevice的常用方法说明。

  • getName:获得该设备的名称;
  • getAddress:获得该设备的地址;
  • getBondState:获得该设备的绑定状态;
  • createBond:创建匹配对象;
  • createRfcommSocketToServiceRecord:根据UUID创建并返回一个BluetoothSocket。

蓝牙服务器套接字BluetoothServiceSocket

BluetoothServiceSocket是服务端的Socket,用来接收客户端的Socket连接请求。下面是常用的方法说明。

accept:监听外部的蓝牙连接请求;
close:关闭服务端的蓝牙监听。

蓝牙客户端套接字BluetoothSocket

BluetoothSocket是客户端的Socket,用于与对方设备进行数据通信。下面是常用的方法说明。

  • connect:建立蓝牙的socket连接;
  • close:关闭蓝牙的socket连接;
  • getInputStream:获取socket连接的输入流对象;
  • getOutputStream:获取socket连接的输出流对象;
  • getRemoteDevice:获取远程设备信息。

layout\activity_bluetooth.xml界面布局代码如下:界面布局代码如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><!--头部--><RelativeLayoutandroid:id="@+id/rl_title"android:layout_width="match_parent"android:layout_height="55dp"android:background="@color/color_2570fd"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/app_name"android:textColor="@color/white"android:textSize="22sp"android:layout_centerVertical="true"android:layout_marginLeft="10dp"/></RelativeLayout><LinearLayoutandroid:id="@+id/ll_switch"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:padding="5dp"android:layout_below="@id/rl_title"><CheckBoxandroid:id="@+id/ck_bluetooth"android:layout_width="wrap_content"android:layout_height="wrap_content"android:button="@null"android:checked="false"android:drawableLeft="@drawable/ck_status_selector"android:text="蓝牙"android:textColor="#ff000000"android:textSize="17sp" /><TextViewandroid:id="@+id/tv_discovery"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="right|center"android:textColor="#ff000000"android:textSize="17sp" /></LinearLayout><LinearLayoutandroid:id="@+id/ll_text"android:layout_width="match_parent"android:layout_height="40dp"android:orientation="horizontal"android:layout_below="@id/ll_switch"><TextViewandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="4"android:gravity="center"android:text="名称"android:textColor="#ff000000"android:textSize="17sp" /><TextViewandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="5"android:gravity="center"android:text="地址"android:textColor="#ff000000"android:textSize="17sp" /><TextViewandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="2"android:gravity="center"android:text="状态"android:textColor="#ff000000"android:textSize="17sp" /></LinearLayout><ListViewandroid:id="@+id/lv_bluetooth"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_below="@id/ll_text"android:layout_above="@+id/ll_bottom"android:listSelector="@null"/><LinearLayoutandroid:id="@+id/ll_bottom"android:layout_width="match_parent"android:layout_height="50dp"android:layout_alignParentBottom="true"android:orientation="horizontal"><Buttonandroid:id="@+id/bt_search"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center"android:text="搜索"android:textColor="#ff000000"android:textSize="14sp" /><Buttonandroid:id="@+id/bt_pair"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center"android:text="配对"android:textColor="#ff000000"android:textSize="14sp" /><Buttonandroid:id="@+id/bt_connect"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center"android:text="连接"android:textColor="#ff000000"android:textSize="14sp" /><Buttonandroid:id="@+id/bt_cancel"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center"android:text="取消配对"android:textColor="#ff000000"android:textSize="14sp" /></LinearLayout></RelativeLayout>

BluetoothActivity.java逻辑代码如下:

package com.example.bluetoothtest;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.UUID;import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ListView;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.TextView;
import android.widget.Toast;import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;import com.example.bluetoothtest.adapter.BlueListAdapter;
import com.example.bluetoothtest.bean.BlueDevice;
import com.example.bluetoothtest.thread.ReadThread;
import com.example.bluetoothtest.thread.WriteThread;
import com.example.bluetoothtest.util.CommonUtil;public class BluetoothActivity extends AppCompatActivity implementsOnClickListener, OnItemClickListener, OnCheckedChangeListener {private static final String TAG = "BluetoothActivity ";    private CheckBox ck_bluetooth;private TextView tv_discovery;private ListView lv_bluetooth;private Button bt_search;private Button bt_pair;private Button bt_connect;private Button bt_cancel;private BluetoothAdapter mBluetooth;private ArrayList<BlueDevice> mDeviceList = new ArrayList<BlueDevice>();private BlueListAdapter adapter;private BluetoothDevice bluetoothDevice;private BluetoothSocket mBlueSocket;private InputStream inputStream;//输入流private OutputStream outputStream;//输出流private WriteThread writeThread;private ReadThread readThread;private boolean isConnect = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_bluetooth);bluetoothPermissions();ck_bluetooth = findViewById(R.id.ck_bluetooth);tv_discovery = findViewById(R.id.tv_discovery);lv_bluetooth = findViewById(R.id.lv_bluetooth);bt_starmap = findViewById(R.id.bt_starmap);bt_location = findViewById(R.id.bt_location);bt_search = findViewById(R.id.bt_search);bt_pair = findViewById(R.id.bt_pair);bt_connect = findViewById(R.id.bt_connect);bt_cancel = findViewById(R.id.bt_cancel);bt_starmap.setOnClickListener(this);bt_location.setOnClickListener(this);bt_search.setOnClickListener(this);bt_pair.setOnClickListener(this);bt_connect.setOnClickListener(this);bt_cancel.setOnClickListener(this);if (CommonUtil.getBlueToothStatus(this) == true) {ck_bluetooth.setChecked(true);}ck_bluetooth.setOnCheckedChangeListener(this);mBluetooth = BluetoothAdapter.getDefaultAdapter();if (mBluetooth == null) {Toast.makeText(this, "本机未找到蓝牙功能", Toast.LENGTH_SHORT).show();finish();}beginDiscovery();}// 定义获取基于地理位置的动态权限private void bluetoothPermissions() {if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION)!= PackageManager.PERMISSION_GRANTED|| ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)!= PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 1);}}/*** 重写onRequestPermissionsResult方法* 获取动态权限请求的结果,再开启蓝牙*/@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {if (requestCode == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {if (CommonUtil.getBlueToothStatus(this) == true) {ck_bluetooth.setChecked(true);}ck_bluetooth.setOnCheckedChangeListener(this);mBluetooth = BluetoothAdapter.getDefaultAdapter();if (mBluetooth == null) {Toast.makeText(this, "本机未找到蓝牙功能", Toast.LENGTH_SHORT).show();finish();}beginDiscovery();} else {Toast.makeText(this, "用户拒绝了权限", Toast.LENGTH_SHORT).show();}super.onRequestPermissionsResult(requestCode, permissions, grantResults);}@Overridepublic void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {if (buttonView.getId() == R.id.ck_bluetooth) {if (isChecked == true) {beginDiscovery();Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);startActivityForResult(intent, 1);} else {cancelDiscovery();CommonUtil.setBlueToothStatus(this, false);mDeviceList.clear();adapter.notifyDataSetChanged();}}}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent intent) {super.onActivityResult(requestCode, resultCode, intent);if (requestCode == 1) {if (resultCode == RESULT_OK) {Toast.makeText(this, "允许本地蓝牙被附近的其它蓝牙设备发现", Toast.LENGTH_SHORT).show();} else if (resultCode == RESULT_CANCELED) {Toast.makeText(this, "不允许蓝牙被附近的其它蓝牙设备发现", Toast.LENGTH_SHORT).show();}}}private void beginDiscovery() {if (mBluetooth.isDiscovering() != true) {mDeviceList.clear();adapter = new BlueListAdapter(BluetoothActivity.this, mDeviceList);lv_bluetooth.setAdapter(adapter);lv_bluetooth.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);tv_discovery.setText("正在搜索蓝牙设备");mBluetooth.startDiscovery();}}private void cancelDiscovery() {
//        tv_discovery.setText("取消搜索蓝牙设备");if (mBluetooth.isDiscovering() == true) {mBluetooth.cancelDiscovery();}}@Overrideprotected void onStart() {super.onStart();blueReceiver = new BluetoothReceiver();//需要过滤多个动作,则调用IntentFilter对象的addAction添加新动作IntentFilter foundFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);foundFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);foundFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);registerReceiver(blueReceiver, foundFilter);}private BluetoothReceiver blueReceiver;private class BluetoothReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();
//            Log.d(TAG, "onReceive action=" + action);// 获得已经搜索到的蓝牙设备if (action.equals(BluetoothDevice.ACTION_FOUND)) {BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);BlueDevice item = new BlueDevice(device.getName(), device.getAddress(), device.getBondState() - 10);for (int i = 0; i < mDeviceList.size(); i++) {if (item.address.equals(mDeviceList.get(i).address)) {mDeviceList.remove(i);//去掉重复项}}mDeviceList.add(item);adapter = new BlueListAdapter(BluetoothActivity.this, mDeviceList);lv_bluetooth.setAdapter(adapter);lv_bluetooth.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);lv_bluetooth.setOnItemClickListener(BluetoothActivity.this);} else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {tv_discovery.setText("蓝牙设备搜索完成");} else if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);if (device.getBondState() == BluetoothDevice.BOND_BONDING) {tv_discovery.setText("正在配对" + device.getName());} else if (device.getBondState() == BluetoothDevice.BOND_BONDED) {tv_discovery.setText("完成配对" + device.getName());refreshAddress(device.getAddress(), BlueListAdapter.BINDED);} else if (device.getBondState() == BluetoothDevice.BOND_NONE) {tv_discovery.setText("取消配对" + device.getName());}}}}@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {cancelDiscovery();BlueDevice item = mDeviceList.get(position);bluetoothDevice = mBluetooth.getRemoteDevice(item.address);adapter.setSelectedItem(position);adapter.notifyDataSetChanged();
//        Toast.makeText(BluetoothActivity.this, "选择" + bluetoothDevice.getAddress(), Toast.LENGTH_SHORT).show();}public void createBond(BluetoothDevice device) {Method createBondMethod = null;try {createBondMethod = BluetoothDevice.class.getMethod("createBond");Boolean result = (Boolean) createBondMethod.invoke(device);} catch (Exception e) {e.printStackTrace();}}public void cancelBond(BluetoothDevice device) {Method createBondMethod = null;try {createBondMethod = BluetoothDevice.class.getMethod("removeBond");Boolean returnValue = (Boolean) createBondMethod.invoke(device);tv_discovery.setText("取消配对" + device.getAddress());refreshAddress(device.getAddress(), BlueListAdapter.UNBIND);isConnect = false;if (readThread != null) {readThread.interrupt();readThread = null;}} catch (Exception e) {e.printStackTrace();}}public void connetBle(final BluetoothDevice device) {Log.d(TAG, "---开始连接蓝牙=" + device.getName());try {UUID SERIAL_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); // bluetooth serial port servicefinal BluetoothSocket socket = device.createRfcommSocketToServiceRecord(SERIAL_UUID); //加密传输,Android系统强制配对,弹窗显示配对码//这里建立蓝牙连接 socket.connect()new Thread() {@Overridepublic void run() {try {socket.connect();inputStream = socket.getInputStream();outputStream = socket.getOutputStream();if (readThread != null) {readThread.interrupt();readThread = null;}readThread = new ReadThread(inputStream);readThread.start();writeThread = new WriteThread(outputStream);writeThread.start();} catch (IOException e) {Log.d(TAG, "---connetBle e=" + e.toString());}}}.start();runOnUiThread(new Runnable() {@Overridepublic void run() {Toast.makeText(BluetoothActivity.this, "连接成功", Toast.LENGTH_SHORT).show();onBlueConnect(device.getAddress(), socket);}});} catch (Exception e) {e.printStackTrace();}}//客户端主动连接public void onBlueConnect(String address, BluetoothSocket socket) {mBlueSocket = socket;tv_discovery.setText("连接成功");isConnect = true;refreshAddress(address, BlueListAdapter.CONNECTED);}//刷新蓝牙状态private void refreshAddress(String address, int state) {for (int i = 0; i < mDeviceList.size(); i++) {BlueDevice item = mDeviceList.get(i);if (item.address.equals(address) == true) {item.state = state;mDeviceList.set(i, item);}}adapter.notifyDataSetChanged();}@Overridepublic void onClick(View v) {int id = v.getId();switch (id) {case R.id.bt_search:beginDiscovery();break;case R.id.bt_pair:createBond(bluetoothDevice);break;case R.id.bt_connect:connetBle(bluetoothDevice);break;case R.id.bt_cancel:cancelBond(bluetoothDevice);break;default:break;}}@Overrideprotected void onDestroy() {super.onDestroy();cancelDiscovery();unregisterReceiver(blueReceiver);if (mBlueSocket != null) {try {mBlueSocket.close();} catch (IOException e) {e.printStackTrace();}}}}

添加蓝牙所需的相应权限:

<!-- 蓝牙 -->
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED"/><!--基于地理位置-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

6.0以上系统记得动态获取ACCESS_COARSE_LOCATION权限,不然可能会出现蓝牙设备检测不到。

Demo程序运行效果界面截图如下:

socket.connect();蓝牙连接成功之后,根据自己的需要做后续处理,楼主这里是通过InputStream和OutputStream来做数据的读写操作,所以各自开了一个读写进程。关于蓝牙连接就这么多,希望对大家有帮助呀~

Android实现蓝牙(BlueTooth)设备检测连接相关推荐

  1. Android通过蓝牙获取设备的通讯录、通话记录等

    本功能实现方案流程如下: 1.在AndroidManifest文件中添加蓝牙相关权限: 2.通过静态或者动态注册广播的形式,监听蓝牙设备的状态(本文以动态监听的方式实现): 3.根据已实现广播的回调状 ...

  2. android 多个蓝牙连接电脑,Android BLE蓝牙多设备连接

    多设备连接的问题很典型,一方面实际应用中存在同时和多个设备通信的场景,另一方面蓝牙连接较耗时,如果能尽可能保持连接,则可省去不少时间,用户体验更好. 然而多设备连接也有一些问题要注意,有以下几点: 一 ...

  3. android 传统蓝牙Bluetooth联通性

    Android平台包含了对蓝牙网络协议栈的支持,它允许一个蓝牙设备跟其他的蓝牙设备进行无线的数据交换.应用程序通过Android蓝牙API提供访问蓝牙的功能.这些API会把应用程序无线连接到其他的蓝牙 ...

  4. 此蓝牙设备或计算机无法处理该类型文件,蓝牙允许设备进行连接用不了_win10蓝牙允许设备连接灰色怎么解决...

    2020-11-12 15:20:52 浏览量:4578 在如今的智能设备中像手机.电脑等设备中都集成了蓝牙功能,我们经常会使用到这一功能,不过近日有用户在使用时,有一疑问,那就是手机可以连接多个蓝牙 ...

  5. win10蓝牙允许设备连接到此计算机,蓝牙允许设备进行连接用不了_win10蓝牙允许设备连接灰色怎么解决...

    手机可以连接多个蓝牙设备吗 手机连接多个蓝牙耳机的方法 在如今的智能设备中像手机.电脑等设备中都集成了蓝牙功能,我们经常会使用到这一功能,不过近日有用户在使用时,有一疑问,那就是手机可以连接多个蓝牙设 ...

  6. Windows Moible, Wince 使用.NET Compact Framework的进行蓝牙(Bluetooth)设备配对的开发

    在.NET Compact Framework下的Bluetooth开发 之 32feet.NET 里讲述了如何使用32feet.net库来进行Bluetooth的开发,天机 同学在使用过程发现设备配 ...

  7. Ubuntu蓝牙Bluetooth命令行连接发送文件完整流程

    1.确保bluez已安装好 $sudo apt install bluez 2.查看当前蓝牙阻塞状态 $sudo rfkill list 如果上面阻塞状态为yes,表示蓝牙关闭,则需要unblock打 ...

  8. Android 蓝牙 Bluetooth 自动回连 取消pin码校验弹出框

    蓝牙深层次的也不太懂,主要是使用了 BluetoothAdapter 和 BluetoothDevice 这两类,一个表示本地蓝牙设备,一个表示远程蓝牙设备 相关说明:https://blog.csd ...

  9. 微信小程序蓝牙连接硬件设备并进行通讯,小程序蓝牙因距离异常断开自动重连,js实现crc校验位

    一.小程序实现搜索蓝牙: 注意:comtl是我封装的工具函数,无关紧要,实际项目中可能用不到: const comtl = require('../../utils/commontool') cons ...

最新文章

  1. 从经典问题开始教你如何入门计算机视觉!贴心!
  2. 洛谷 P1029 最大公约数和最小公倍数问题
  3. LINQ学习(六):OrderBy/Group By子句
  4. 鸟哥的Linux私房菜(基础篇)- 第二十章、启动流程、模块管理与 Loader
  5. 运维基础(12)服务器12种基本故障+排查方法
  6. 腾讯成功入选LoRa联盟新一届董事会
  7. 分布式与人工智能课程(part14)--深度学习
  8. Unity3D Shader入门指南(二)
  9. live555推流rtsp_Hi3518 RTSP推流
  10. 根据/proc/meminfo对空闲内存进行占用
  11. 游戏编程精粹学习 - 使用定点颜色插值模拟实时光照
  12. 全新AI内参:量子位精心打磨,最新产业资讯、科研进展一文呈现
  13. 一台电脑安装多个Chrome
  14. django优化--ORM优缺点
  15. 小工具-悬浮窗LogViewer在android手机上查看数据日志
  16. 某易易盾滑块流程加参数分析
  17. Roslyn入门(1):一个简单修改C#代码的例子
  18. aspack(工具+手动)脱壳
  19. 【论文复现】CBAM(2018)
  20. 服务器登陆之后一直转无法显示桌面,如何解决远程登录Windows服务器无法显示桌面的问题?...

热门文章

  1. 【动手学深度学习】Task05笔记汇总
  2. Fluxion安装教程
  3. python3编程小车_控制小车
  4. Cocos2d-x 实现地图滚动,解释缝隙产生的原因以及解决方案
  5. android 屏幕旋转
  6. 简单的注册表代码记录
  7. Windows10系统批量获取所有用户名称、修改所有用户名称
  8. Android简单实现计时和倒计时
  9. Eclipse护眼背景色图文设置
  10. [蓝桥杯]Excel题