两个Android端基于蓝牙通讯的demo

xiaoxiao2021-02-28  84

这几天很不顺利,经过一段时间的疯狂加班之后工作终于辞了,淡定下来回顾下最近所开发的软件,当做整合整合知识。闲话不多说进入正题。

随着硬件成本的不断降低,目前越来越多的终端外设也运行了Android系统,因此在和这些外设做短距离的小数据通讯时Android与Android的蓝牙通讯成为了主力军,本次采用的是socket蓝牙通讯,熟悉socket的同学肯定知道,socket通讯肯定就有服务器端和客户端,我们先来介绍服务器的代码:

老样子我们先介绍下界面布局,本服务器端有两个页面,分别是蓝牙配对页面和收发接口页面,如下图:

                                                               

上图第一个界面是蓝牙的配对界面,打开软件会列出已配对的设备,点击扫面按键会扫描附近的蓝牙设备(如果长时间不能够扫面到设备建议先使用系统进行配对),点击相应的需连接设备后进入第二个界面,等待客户端的连接,具体代码如下:

蓝牙扫描页面:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.viewat.bluetooth.MainActivity" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="搜索设备" android:onClick="onClick_search"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="60dp" android:text="蓝牙设备列表" android:layout_centerHorizontal="true"/> <ListView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="80dp" android:id="@+id/listView"> </ListView> </RelativeLayout> 蓝牙收发操作界面:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/white"> <ScrollView android:layout_width="match_parent" android:layout_height="300dp" android:paddingLeft="10dp" android:paddingRight="10dp"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/tv_message"/> </ScrollView> <EditText android:layout_width="match_parent" android:layout_height="50dp" android:layout_alignParentBottom="true" android:layout_marginBottom="80dp" android:id="@+id/editText"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginBottom="20dp" android:layout_marginLeft="30dp" android:text="发送" android:onClick="onClick_send"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginBottom="20dp" android:layout_alignParentRight="true" android:layout_marginRight="30dp" android:text="结束回话,断开链接" android:onClick="onClick_end"/> </RelativeLayout> 下面介绍实现的代码,首先是获取已配对的蓝牙设备罗列出来:

/** * 列出所有的蓝牙设备 */ private void init() { Log.i("tag", "mBtAdapter=="+ mBtAdapter); //根据适配器得到所有的设备信息 Set<BluetoothDevice> deviceSet = mBtAdapter.getBondedDevices(); if (deviceSet.size() > 0) { for (BluetoothDevice device : deviceSet) { mDatas.add(new DeviceBean(device.getName() + "\n" + device.getAddress(), true)); mAdapter.notifyDataSetChanged(); mListView.setSelection(mDatas.size() - 1); } } else { mDatas.add(new DeviceBean("没有配对的设备", true)); mAdapter.notifyDataSetChanged(); mListView.setSelection(mDatas.size() - 1); } }利用广播获取所有的蓝牙设备:

/** * 发现设备广播 */ private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { // 获得设备信息 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // 如果绑定的状态不一样 if (device.getBondState() != BluetoothDevice.BOND_BONDED) { mDatas.add(new DeviceBean(device.getName() + "\n" + device.getAddress(), false)); mAdapter.notifyDataSetChanged(); mListView.setSelection(mDatas.size() - 1); } // 如果搜索完成了 } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { setProgressBarIndeterminateVisibility(false); if (mListView.getCount() == 0) { mDatas.add(new DeviceBean("没有发现蓝牙设备", false)); mAdapter.notifyDataSetChanged(); mListView.setSelection(mDatas.size() - 1); } showTxt("请重新搜索"); } } }; 接着监听点击事件,进入连接页面:

/** * 点击设备监听 */ private OnItemClickListener mDeviceClickListener = new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { DeviceBean bean = mDatas.get(position); String info = bean.message; String address = info.substring(info.length() - 17); BlueToothAddress = address; AlertDialog.Builder stopDialog = new AlertDialog.Builder(MainActivity.this); stopDialog.setTitle("连接");//标题 stopDialog.setMessage(bean.message); stopDialog.setPositiveButton("连接", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { mBtAdapter.cancelDiscovery(); // showTxt("停止扫描,进行连接..."); startActivity(new Intent(MainActivity.this,ChatActivity.class)); dialog.cancel(); } }); stopDialog.setNegativeButton("取消", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { BlueToothAddress = null; dialog.cancel(); } }); stopDialog.show(); } }; 紧接着会跳转到蓝牙的收发页面,首先获得一个蓝牙适配器 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 接着会打开监听的线程;

// 开启服务器 private class ServerThread extends Thread { public void run() { try { // 创建一个蓝牙服务器 参数分别:服务器名称、UUID mServerSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(PROTOCOL_SCHEME_RFCOMM, UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); Message msg = new Message(); msg.obj = "请稍候,正在等待客户端的连接..."; msg.what = STATUS_CONNECT; mHandler.sendMessage(msg); /* 接受客户端的连接请求 */ mSocket = mServerSocket.accept(); msg = new Message(); msg.obj = "客户端已经连接上!可以发送信息。"; msg.what = STATUS_CONNECT; mHandler.sendMessage(msg); // 启动接受数据 mReadThread = new ReadThread(); mReadThread.start(); } catch (Exception e) { e.printStackTrace(); } } }; 此时服务端的代码准备完成,下面我们介绍下客户端代码,同样的客户端也是有类似的两个页面,如下图:

                                                                              

当打开服务端的监听后,打开客户端的代码会进入蓝牙配对的界面,点击相应的服务端设备进入蓝牙操作界面,点击open后会进行和服务端连接,连接成功后会进行相应的提醒,此时既可以进行通讯了,具体的界面代码如下: 蓝牙扫面界面:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.viewat.bluetooth.MainActivity" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="搜索设备" android:onClick="onClick_search"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="60dp" android:text="蓝牙设备列表" android:layout_centerHorizontal="true"/> <ListView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="80dp" android:id="@+id/listView"> </ListView> </RelativeLayout> 蓝牙收发界面:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.viewat.bluetoothhostclient.MainActivity" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="客户端" android:layout_centerHorizontal="true"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:text="open" android:onClick="onClick_open"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="20dp" android:text="send" android:onClick="onClick_send"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_marginTop="20dp" android:text="close" android:onClick="onClick_close"/> <EditText android:layout_width="match_parent" android:layout_height="40dp" android:layout_marginTop="100dp" android:id="@+id/editText"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="160dp" android:paddingLeft="10dp" android:paddingRight="10dp" android:text="数据" android:id="@+id/tv_message"/> </RelativeLayout> 下面介绍客户端的实现,监听蓝牙列表的点击事件和服务端类似,连接服务端时同样先构建一个蓝牙适配器 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();紧接着以给定的MAC地址去创建一个 BluetoothDevice 类实例 mDevice = mBluetoothAdapter.getRemoteDevice(address);然后开启客户端的连接线程:

// 客户端线程 private class ClientThread extends Thread { public void run() { try { mSocket = mDevice.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); Message msg = new Message(); msg.obj = "请稍候,正在连接服务器:" + address; msg.what = STATUS_CONNECT; mHandler.sendMessage(msg); mSocket.connect(); msg = new Message(); msg.obj = "已经连接上服务端!可以发送信息。"; msg.what = STATUS_CONNECT; mHandler.sendMessage(msg); // 启动接受数据 mReadThread = new ReadThread(); mReadThread.start(); isOpen = true; } catch (Exception e) { Message msg = new Message(); msg.obj = "连接服务端异常!请断开连接重新试一试。"; msg.what = STATUS_CONNECT; mHandler.sendMessage(msg); } } }; 在连接线程之后会开启接收数据的线程,然后利用回调显示在界面上:

// 读取数据 private class ReadThread extends Thread { public void run() { byte[] buffer = new byte[1024]; int bytes; InputStream is = null; try { is = mSocket.getInputStream(); while (true) { if ((bytes = is.read(buffer)) > 0) { byte[] buf_data = new byte[bytes]; for (int i = 0; i < bytes; i++) { buf_data[i] = buffer[i]; } String s = new String(buf_data); Message msg = new Message(); Bundle bundle = msg.getData(); bundle.putString("info", s); bundle.putByteArray("buf", buf_data); mHandler.sendMessage(msg); } } } catch (Exception e1) { e1.printStackTrace(); } finally { try { is.close(); } catch (Exception e1) { e1.printStackTrace(); } } } } 致此整个蓝牙收发的客户端和服务端已经全部写完,这里废话下软件的操作流程:

服务端: 进入主界面后,找到对应的手机的蓝牙mac地址,点击后进入聊天界面。 遇到弹框就点同意。 客户端: 进入主界面后,找到对应的手机的蓝牙mac地址,点击后进入聊天界面。 遇到弹框就点同意。 点击open,然后弹框上点击同意,在服务端上显示"客户端已经连接上,可以发送信息",表示能进行通讯了

最后贴上我的源代码:源码下载(辛苦手打收两个积分,如果积分不够可在下面留下邮箱,我看到后第一时间发送源码)

纯手打,有帮助就回复下,有什么问题也可留言,我们共同讨论下。

转载请注明出处!谢谢!

转载请注明原文地址: https://www.6miu.com/read-72269.html

最新回复(0)