当前位置:   article > 正文

Android实现蓝牙(BlueTooth)设备检测连接_bluetoothdevice getbondeddevices android

bluetoothdevice getbondeddevices android

项目要求实现蓝牙设备搜索连接,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界面布局代码如下:界面布局代码如下: 

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:layout_width="match_parent"
  3. android:layout_height="match_parent"
  4. android:orientation="vertical"
  5. >
  6. <!--头部-->
  7. <RelativeLayout
  8. android:id="@+id/rl_title"
  9. android:layout_width="match_parent"
  10. android:layout_height="55dp"
  11. android:background="@color/color_2570fd"
  12. >
  13. <TextView
  14. android:layout_width="wrap_content"
  15. android:layout_height="wrap_content"
  16. android:text="@string/app_name"
  17. android:textColor="@color/white"
  18. android:textSize="22sp"
  19. android:layout_centerVertical="true"
  20. android:layout_marginLeft="10dp"
  21. />
  22. </RelativeLayout>
  23. <LinearLayout
  24. android:id="@+id/ll_switch"
  25. android:layout_width="match_parent"
  26. android:layout_height="wrap_content"
  27. android:orientation="horizontal"
  28. android:padding="5dp"
  29. android:layout_below="@id/rl_title"
  30. >
  31. <CheckBox
  32. android:id="@+id/ck_bluetooth"
  33. android:layout_width="wrap_content"
  34. android:layout_height="wrap_content"
  35. android:button="@null"
  36. android:checked="false"
  37. android:drawableLeft="@drawable/ck_status_selector"
  38. android:text="蓝牙"
  39. android:textColor="#ff000000"
  40. android:textSize="17sp" />
  41. <TextView
  42. android:id="@+id/tv_discovery"
  43. android:layout_width="0dp"
  44. android:layout_height="match_parent"
  45. android:layout_weight="1"
  46. android:gravity="right|center"
  47. android:textColor="#ff000000"
  48. android:textSize="17sp" />
  49. </LinearLayout>
  50. <LinearLayout
  51. android:id="@+id/ll_text"
  52. android:layout_width="match_parent"
  53. android:layout_height="40dp"
  54. android:orientation="horizontal"
  55. android:layout_below="@id/ll_switch"
  56. >
  57. <TextView
  58. android:layout_width="0dp"
  59. android:layout_height="match_parent"
  60. android:layout_weight="4"
  61. android:gravity="center"
  62. android:text="名称"
  63. android:textColor="#ff000000"
  64. android:textSize="17sp" />
  65. <TextView
  66. android:layout_width="0dp"
  67. android:layout_height="match_parent"
  68. android:layout_weight="5"
  69. android:gravity="center"
  70. android:text="地址"
  71. android:textColor="#ff000000"
  72. android:textSize="17sp" />
  73. <TextView
  74. android:layout_width="0dp"
  75. android:layout_height="match_parent"
  76. android:layout_weight="2"
  77. android:gravity="center"
  78. android:text="状态"
  79. android:textColor="#ff000000"
  80. android:textSize="17sp" />
  81. </LinearLayout>
  82. <ListView
  83. android:id="@+id/lv_bluetooth"
  84. android:layout_width="match_parent"
  85. android:layout_height="match_parent"
  86. android:layout_below="@id/ll_text"
  87. android:layout_above="@+id/ll_bottom"
  88. android:listSelector="@null"
  89. />
  90. <LinearLayout
  91. android:id="@+id/ll_bottom"
  92. android:layout_width="match_parent"
  93. android:layout_height="50dp"
  94. android:layout_alignParentBottom="true"
  95. android:orientation="horizontal">
  96. <Button
  97. android:id="@+id/bt_search"
  98. android:layout_width="0dp"
  99. android:layout_height="match_parent"
  100. android:layout_weight="1"
  101. android:gravity="center"
  102. android:text="搜索"
  103. android:textColor="#ff000000"
  104. android:textSize="14sp" />
  105. <Button
  106. android:id="@+id/bt_pair"
  107. android:layout_width="0dp"
  108. android:layout_height="match_parent"
  109. android:layout_weight="1"
  110. android:gravity="center"
  111. android:text="配对"
  112. android:textColor="#ff000000"
  113. android:textSize="14sp" />
  114. <Button
  115. android:id="@+id/bt_connect"
  116. android:layout_width="0dp"
  117. android:layout_height="match_parent"
  118. android:layout_weight="1"
  119. android:gravity="center"
  120. android:text="连接"
  121. android:textColor="#ff000000"
  122. android:textSize="14sp" />
  123. <Button
  124. android:id="@+id/bt_cancel"
  125. android:layout_width="0dp"
  126. android:layout_height="match_parent"
  127. android:layout_weight="1"
  128. android:gravity="center"
  129. android:text="取消配对"
  130. android:textColor="#ff000000"
  131. android:textSize="14sp" />
  132. </LinearLayout>
  133. </RelativeLayout>

BluetoothActivity.java逻辑代码如下: 

  1. package com.example.bluetoothtest;
  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.io.OutputStream;
  5. import java.lang.reflect.Method;
  6. import java.util.ArrayList;
  7. import java.util.UUID;
  8. import android.Manifest;
  9. import android.bluetooth.BluetoothAdapter;
  10. import android.bluetooth.BluetoothDevice;
  11. import android.bluetooth.BluetoothSocket;
  12. import android.content.BroadcastReceiver;
  13. import android.content.Context;
  14. import android.content.Intent;
  15. import android.content.IntentFilter;
  16. import android.content.pm.PackageManager;
  17. import android.os.Build;
  18. import android.os.Bundle;
  19. import android.util.Log;
  20. import android.view.View;
  21. import android.view.View.OnClickListener;
  22. import android.widget.AbsListView;
  23. import android.widget.AdapterView;
  24. import android.widget.AdapterView.OnItemClickListener;
  25. import android.widget.Button;
  26. import android.widget.CheckBox;
  27. import android.widget.CompoundButton;
  28. import android.widget.ListView;
  29. import android.widget.CompoundButton.OnCheckedChangeListener;
  30. import android.widget.TextView;
  31. import android.widget.Toast;
  32. import androidx.annotation.NonNull;
  33. import androidx.appcompat.app.AppCompatActivity;
  34. import androidx.core.app.ActivityCompat;
  35. import androidx.core.content.ContextCompat;
  36. import com.example.bluetoothtest.adapter.BlueListAdapter;
  37. import com.example.bluetoothtest.bean.BlueDevice;
  38. import com.example.bluetoothtest.thread.ReadThread;
  39. import com.example.bluetoothtest.thread.WriteThread;
  40. import com.example.bluetoothtest.util.CommonUtil;
  41. public class BluetoothActivity extends AppCompatActivity implements
  42. OnClickListener, OnItemClickListener, OnCheckedChangeListener {
  43. private static final String TAG = "BluetoothActivity ";
  1. private CheckBox ck_bluetooth;
  2. private TextView tv_discovery;
  3. private ListView lv_bluetooth;
  4. private Button bt_search;
  5. private Button bt_pair;
  6. private Button bt_connect;
  7. private Button bt_cancel;
  8. private BluetoothAdapter mBluetooth;
  9. private ArrayList<BlueDevice> mDeviceList = new ArrayList<BlueDevice>();
  10. private BlueListAdapter adapter;
  11. private BluetoothDevice bluetoothDevice;
  12. private BluetoothSocket mBlueSocket;
  13. private InputStream inputStream;//输入流
  14. private OutputStream outputStream;//输出流
  15. private WriteThread writeThread;
  16. private ReadThread readThread;
  17. private boolean isConnect = false;
  18. @Override
  19. protected void onCreate(Bundle savedInstanceState) {
  20. super.onCreate(savedInstanceState);
  21. setContentView(R.layout.activity_bluetooth);
  22. bluetoothPermissions();
  23. ck_bluetooth = findViewById(R.id.ck_bluetooth);
  24. tv_discovery = findViewById(R.id.tv_discovery);
  25. lv_bluetooth = findViewById(R.id.lv_bluetooth);
  26. bt_starmap = findViewById(R.id.bt_starmap);
  27. bt_location = findViewById(R.id.bt_location);
  28. bt_search = findViewById(R.id.bt_search);
  29. bt_pair = findViewById(R.id.bt_pair);
  30. bt_connect = findViewById(R.id.bt_connect);
  31. bt_cancel = findViewById(R.id.bt_cancel);
  32. bt_starmap.setOnClickListener(this);
  33. bt_location.setOnClickListener(this);
  34. bt_search.setOnClickListener(this);
  35. bt_pair.setOnClickListener(this);
  36. bt_connect.setOnClickListener(this);
  37. bt_cancel.setOnClickListener(this);
  38. if (CommonUtil.getBlueToothStatus(this) == true) {
  39. ck_bluetooth.setChecked(true);
  40. }
  41. ck_bluetooth.setOnCheckedChangeListener(this);
  42. mBluetooth = BluetoothAdapter.getDefaultAdapter();
  43. if (mBluetooth == null) {
  44. Toast.makeText(this, "本机未找到蓝牙功能", Toast.LENGTH_SHORT).show();
  45. finish();
  46. }
  47. beginDiscovery();
  48. }
  49. // 定义获取基于地理位置的动态权限
  50. private void bluetoothPermissions() {
  51. if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION)
  52. != PackageManager.PERMISSION_GRANTED
  53. || ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
  54. != PackageManager.PERMISSION_GRANTED
  55. ) {
  56. ActivityCompat.requestPermissions(this, new String[]{
  57. android.Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 1);
  58. }
  59. }
  60. /**
  61. * 重写onRequestPermissionsResult方法
  62. * 获取动态权限请求的结果,再开启蓝牙
  63. */
  64. @Override
  65. public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  66. if (requestCode == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
  67. if (CommonUtil.getBlueToothStatus(this) == true) {
  68. ck_bluetooth.setChecked(true);
  69. }
  70. ck_bluetooth.setOnCheckedChangeListener(this);
  71. mBluetooth = BluetoothAdapter.getDefaultAdapter();
  72. if (mBluetooth == null) {
  73. Toast.makeText(this, "本机未找到蓝牙功能", Toast.LENGTH_SHORT).show();
  74. finish();
  75. }
  76. beginDiscovery();
  77. } else {
  78. Toast.makeText(this, "用户拒绝了权限", Toast.LENGTH_SHORT).show();
  79. }
  80. super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  81. }
  82. @Override
  83. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
  84. if (buttonView.getId() == R.id.ck_bluetooth) {
  85. if (isChecked == true) {
  86. beginDiscovery();
  87. Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
  88. startActivityForResult(intent, 1);
  89. } else {
  90. cancelDiscovery();
  91. CommonUtil.setBlueToothStatus(this, false);
  92. mDeviceList.clear();
  93. adapter.notifyDataSetChanged();
  94. }
  95. }
  96. }
  97. @Override
  98. protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
  99. super.onActivityResult(requestCode, resultCode, intent);
  100. if (requestCode == 1) {
  101. if (resultCode == RESULT_OK) {
  102. Toast.makeText(this, "允许本地蓝牙被附近的其它蓝牙设备发现", Toast.LENGTH_SHORT).show();
  103. } else if (resultCode == RESULT_CANCELED) {
  104. Toast.makeText(this, "不允许蓝牙被附近的其它蓝牙设备发现", Toast.LENGTH_SHORT).show();
  105. }
  106. }
  107. }
  108. private void beginDiscovery() {
  109. if (mBluetooth.isDiscovering() != true) {
  110. mDeviceList.clear();
  111. adapter = new BlueListAdapter(BluetoothActivity.this, mDeviceList);
  112. lv_bluetooth.setAdapter(adapter);
  113. lv_bluetooth.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
  114. tv_discovery.setText("正在搜索蓝牙设备");
  115. mBluetooth.startDiscovery();
  116. }
  117. }
  118. private void cancelDiscovery() {
  119. // tv_discovery.setText("取消搜索蓝牙设备");
  120. if (mBluetooth.isDiscovering() == true) {
  121. mBluetooth.cancelDiscovery();
  122. }
  123. }
  124. @Override
  125. protected void onStart() {
  126. super.onStart();
  127. blueReceiver = new BluetoothReceiver();
  128. //需要过滤多个动作,则调用IntentFilter对象的addAction添加新动作
  129. IntentFilter foundFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
  130. foundFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
  131. foundFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
  132. registerReceiver(blueReceiver, foundFilter);
  133. }
  134. private BluetoothReceiver blueReceiver;
  135. private class BluetoothReceiver extends BroadcastReceiver {
  136. @Override
  137. public void onReceive(Context context, Intent intent) {
  138. String action = intent.getAction();
  139. // Log.d(TAG, "onReceive action=" + action);
  140. // 获得已经搜索到的蓝牙设备
  141. if (action.equals(BluetoothDevice.ACTION_FOUND)) {
  142. BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
  143. BlueDevice item = new BlueDevice(device.getName(), device.getAddress(), device.getBondState() - 10);
  144. for (int i = 0; i < mDeviceList.size(); i++) {
  145. if (item.address.equals(mDeviceList.get(i).address)) {
  146. mDeviceList.remove(i);//去掉重复项
  147. }
  148. }
  149. mDeviceList.add(item);
  150. adapter = new BlueListAdapter(BluetoothActivity.this, mDeviceList);
  151. lv_bluetooth.setAdapter(adapter);
  152. lv_bluetooth.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
  153. lv_bluetooth.setOnItemClickListener(BluetoothActivity.this);
  154. } else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {
  155. tv_discovery.setText("蓝牙设备搜索完成");
  156. } else if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
  157. BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
  158. if (device.getBondState() == BluetoothDevice.BOND_BONDING) {
  159. tv_discovery.setText("正在配对" + device.getName());
  160. } else if (device.getBondState() == BluetoothDevice.BOND_BONDED) {
  161. tv_discovery.setText("完成配对" + device.getName());
  162. refreshAddress(device.getAddress(), BlueListAdapter.BINDED);
  163. } else if (device.getBondState() == BluetoothDevice.BOND_NONE) {
  164. tv_discovery.setText("取消配对" + device.getName());
  165. }
  166. }
  167. }
  168. }
  169. @Override
  170. public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
  171. cancelDiscovery();
  172. BlueDevice item = mDeviceList.get(position);
  173. bluetoothDevice = mBluetooth.getRemoteDevice(item.address);
  174. adapter.setSelectedItem(position);
  175. adapter.notifyDataSetChanged();
  176. // Toast.makeText(BluetoothActivity.this, "选择" + bluetoothDevice.getAddress(), Toast.LENGTH_SHORT).show();
  177. }
  178. public void createBond(BluetoothDevice device) {
  179. Method createBondMethod = null;
  180. try {
  181. createBondMethod = BluetoothDevice.class.getMethod("createBond");
  182. Boolean result = (Boolean) createBondMethod.invoke(device);
  183. } catch (Exception e) {
  184. e.printStackTrace();
  185. }
  186. }
  187. public void cancelBond(BluetoothDevice device) {
  188. Method createBondMethod = null;
  189. try {
  190. createBondMethod = BluetoothDevice.class.getMethod("removeBond");
  191. Boolean returnValue = (Boolean) createBondMethod.invoke(device);
  192. tv_discovery.setText("取消配对" + device.getAddress());
  193. refreshAddress(device.getAddress(), BlueListAdapter.UNBIND);
  194. isConnect = false;
  195. if (readThread != null) {
  196. readThread.interrupt();
  197. readThread = null;
  198. }
  199. } catch (Exception e) {
  200. e.printStackTrace();
  201. }
  202. }
  203. public void connetBle(final BluetoothDevice device) {
  204. Log.d(TAG, "---开始连接蓝牙=" + device.getName());
  205. try {
  206. UUID SERIAL_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); // bluetooth serial port service
  207. final BluetoothSocket socket = device.createRfcommSocketToServiceRecord(SERIAL_UUID); //加密传输,Android系统强制配对,弹窗显示配对码
  208. //这里建立蓝牙连接 socket.connect()
  209. new Thread() {
  210. @Override
  211. public void run() {
  212. try {
  213. socket.connect();
  214. inputStream = socket.getInputStream();
  215. outputStream = socket.getOutputStream();
  216. if (readThread != null) {
  217. readThread.interrupt();
  218. readThread = null;
  219. }
  220. readThread = new ReadThread(inputStream);
  221. readThread.start();
  222. writeThread = new WriteThread(outputStream);
  223. writeThread.start();
  224. } catch (IOException e) {
  225. Log.d(TAG, "---connetBle e=" + e.toString());
  226. }
  227. }
  228. }.start();
  229. runOnUiThread(new Runnable() {
  230. @Override
  231. public void run() {
  232. Toast.makeText(BluetoothActivity.this, "连接成功", Toast.LENGTH_SHORT).show();
  233. onBlueConnect(device.getAddress(), socket);
  234. }
  235. });
  236. } catch (Exception e) {
  237. e.printStackTrace();
  238. }
  239. }
  240. //客户端主动连接
  241. public void onBlueConnect(String address, BluetoothSocket socket) {
  242. mBlueSocket = socket;
  243. tv_discovery.setText("连接成功");
  244. isConnect = true;
  245. refreshAddress(address, BlueListAdapter.CONNECTED);
  246. }
  247. //刷新蓝牙状态
  248. private void refreshAddress(String address, int state) {
  249. for (int i = 0; i < mDeviceList.size(); i++) {
  250. BlueDevice item = mDeviceList.get(i);
  251. if (item.address.equals(address) == true) {
  252. item.state = state;
  253. mDeviceList.set(i, item);
  254. }
  255. }
  256. adapter.notifyDataSetChanged();
  257. }
  258. @Override
  259. public void onClick(View v) {
  260. int id = v.getId();
  261. switch (id) {
  262. case R.id.bt_search:
  263. beginDiscovery();
  264. break;
  265. case R.id.bt_pair:
  266. createBond(bluetoothDevice);
  267. break;
  268. case R.id.bt_connect:
  269. connetBle(bluetoothDevice);
  270. break;
  271. case R.id.bt_cancel:
  272. cancelBond(bluetoothDevice);
  273. break;
  274. default:
  275. break;
  276. }
  277. }
  278. @Override
  279. protected void onDestroy() {
  280. super.onDestroy();
  281. cancelDiscovery();
  282. unregisterReceiver(blueReceiver);
  283. if (mBlueSocket != null) {
  284. try {
  285. mBlueSocket.close();
  286. } catch (IOException e) {
  287. e.printStackTrace();
  288. }
  289. }
  290. }
  291. }

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

  1. <!-- 蓝牙 -->
  2. <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
  3. <uses-permission android:name="android.permission.BLUETOOTH"/>
  4. <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED"/>
  5. <!--基于地理位置-->
  6. <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  7. <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

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

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/866537
推荐阅读
相关标签
  

闽ICP备14008679号