无线通信方案,有三种方案可以实施:
1、NFC 2、蓝牙 3、WIFI
下面是对这三个知识点做的一个总结,参照对比可以选择合适的方案。而本章着重讲的蓝牙之间通信。

首先介绍一下蓝牙的两个广播Receiver。
第一个:蓝牙状态的改变是通过广播接收到的。

 // 注册蓝牙状态接收广播IntentFilter intentFilter = new  ntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);registerReceiver(mReceiverBluetoothStatus,intentFilter);/*** 定义接收蓝牙状态广播receiver** @param savedInstanceState*/private BroadcastReceiver mReceiverBluetoothStatus = new BroadcastReceiver() {@Overridepublic void onReceive(Context context,Intent intent) {int status = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,-1);switch (status) {case BluetoothAdapter.STATE_OFF:Log.d(TAG,"蓝牙已关闭");break;case BluetoothAdapter.STATE_ON:Log.d(TAG,"蓝牙已打开");break;case BluetoothAdapter.STATE_TURNING_OFF:Log.d(TAG,"蓝牙关闭中...");break;case BluetoothAdapter.STATE_TURNING_ON:Log.d(TAG,"蓝牙打开中...");break;default:break;}}};

第二个:蓝牙搜索到设备、绑定设备(配对)也是通过广播接收的。(搜索到设备系统会自动发一个广播)

   // 注册蓝牙device接收广播IntentFilter intentFilterDevice = new IntentFilter();// 开始查找intentFilterDevice.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);// 结束查找intentFilterDevice.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);// 查找设备(查找到设备)intentFilterDevice.addAction(BluetoothDevice.ACTION_FOUND);// 设备扫描模式改变 (自己状态的改变action,当设置可见或者不见时都会发送此广播)intentFilterDevice.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);// 绑定状态intentFilterDevice.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);registerReceiver(mReceiverDeceiver,intentFilterDevice);
  /*** 定义接收蓝牙device广播Receiver*/private BroadcastReceiver mReceiverDeceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context,Intent intent) {String action = intent.getAction();if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {// 开始搜索        ——接收广播Log.d(TAG,"开始搜索");mList.clear();mAdapter.refresh(mList);} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {// 查找到设备完成   —— 接收广播Log.d(TAG,"查找到设备完成");} else if (BluetoothDevice.ACTION_FOUND.equals(action)) {// 搜索到设备       —— 接收广播Log.d(TAG,"搜索到设备");BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);mList.add(device);mAdapter.refresh(mList);} else if (BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(action)) {// 当自己设备设置蓝牙可见时或者不可见时 —— 接收广播int scanMode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE,0);// 可见时if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {Log.d(TAG,"设备可见监听");} else {Log.d(TAG,"设备不可见监听");}} else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {// 绑定状态改变回调BluetoothDevice remoteDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);if (remoteDevice == null) {Log.d(TAG,"没有绑定设备");return;}int status = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,0);if (status == BluetoothDevice.BOND_BONDED) {Log.d(TAG,"绑定设备完成: " + remoteDevice.getName());} else if (status == BluetoothDevice.BOND_BONDING) {Log.d(TAG,"绑定设备中: " + remoteDevice.getName());} else if (status == BluetoothDevice.BOND_NONE) {Log.d(TAG,"取消绑定: ");}}}};

以上基本上就是蓝牙接收状态和搜索到设备,绑定设备一系列改变的操作!基本上已经很全了。下面介绍一个蓝牙通信的流程。

左为客户端Socket连接的一个流程:首先获取一个客户端Socket(),然后连接上,就可以读取数据和发送数据了。

右为服务端Socket操作流程:

蓝牙通信原理介绍:
蓝牙通信和socket通信原理基本上是一致的,下面我给大家上一张图(图为Socket通信图)。分析一下。

蓝牙客户端Socket的与Sokcet流程是一样的,只不过参数不同而已。如下:
1、创建客户端蓝牙Sokcet
2、创建连接
3、读写数据
4、关闭

服务端socket:
1、创建服务端蓝牙Socket
2、绑定端口号(蓝牙忽略)
3、创建监听listen(蓝牙忽略, 蓝牙没有此监听,而是通过whlie(true)死循环来一直监听的)
4、通过accept(),如果有客户端连接,会创建一个新的Socket,体现出并发性,可以同时与多个socket通讯)
5、读写数据
6、关闭

下面看客户端代码:

/*** <p>Title: ConnectThread</p >* <p>Description: 客户端逻辑: 客户端的线程,处理客户端socket</p >* <p>Company: ihaveu</p >** @author MaWei* @date 2017/12/26*/
public class ConnectThread extends Thread{private static final UUID MY_UUID = UUID.fromString(Constant.CONNECTTION_UUID);/** 客户端socket*/private final BluetoothSocket mmSoket;/** 要连接的设备*/private final BluetoothDevice mmDevice;private BluetoothAdapter mBluetoothAdapter;/** 主线程通信的Handler*/private final Handler mHandler;/** 发送和接收数据的处理类*/private ConnectedThread mConnectedThread;public ConnectThread(BluetoothDevice device, BluetoothAdapter bluetoothAdapter, Handler mUIhandler) {mmDevice = device;mBluetoothAdapter = bluetoothAdapter;mHandler = mUIhandler;BluetoothSocket tmp = null;try {// 创建客户端Sockettmp = device.createRfcommSocketToServiceRecord(MY_UUID);} catch (IOException e) {e.printStackTrace();}mmSoket = tmp;}@Overridepublic void run() {super.run();// 关闭正在发现设备.(如果此时又在查找设备,又在发送数据,会有冲突,影响传输效率)mBluetoothAdapter.cancelDiscovery();try {// 连接服务器mmSoket.connect();} catch (IOException e) {// 连接异常就关闭try {mmSoket.close();} catch (IOException e1) {}return;}manageConnectedSocket(mmSoket);}private void manageConnectedSocket(BluetoothSocket mmSoket) {// 通知主线程连接上了服务端socket,更新UImHandler.sendEmptyMessage(Constant.MSG_CONNECTED_TO_SERVER);// 新建一个线程进行通讯,不然会发现线程堵塞mConnectedThread = new ConnectedThread(mmSoket,mHandler);mConnectedThread.start();}/*** 关闭当前客户端*/public void cancle() {try {mmSoket.close();} catch (IOException e) {e.printStackTrace();}}/*** 发送数据* @param data*/public void sendData(byte[] data) {if(mConnectedThread != null) {mConnectedThread.write(data);}}
}

服务端代码:

/*** <p>Title: AccepThread</p >* <p>Description: 服务端Socket通过accept()一直监听客户端连接的线程</p >* <p>Company: ihaveu</p >** @author MaWei* @date 2017/12/26*/
public class AccepThread extends Thread {/** 连接的名称*/private static final String NAME = "BluetoothClass";/** UUID*/private static final UUID MY_UUID = UUID.fromString(Constant.CONNECTTION_UUID);/** 服务端蓝牙Sokcet*/private final BluetoothServerSocket mmServerSocket;private final BluetoothAdapter mBluetoothAdapter;/** 线程中通信的更新UI的Handler*/private final Handler mHandler;/** 监听到有客户端连接,新建一个线程单独处理,不然在此线程中会堵塞*/private ConnectedThread mConnectedThread;public AccepThread(BluetoothAdapter adapter, Handler handler) throws IOException {mBluetoothAdapter = adapter;this.mHandler = handler;// 获取服务端蓝牙socketmmServerSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);}@Overridepublic void run() {super.run();// 连接的客户端soacketBluetoothSocket socket = null;// 服务端是不退出的,要一直监听连接进来的客户端,所以是死循环while (true){// 通知主线程更新UI,客户端开始监听mHandler.sendEmptyMessage(Constant.MSG_START_LISTENING);try {// 获取连接的客户端socketsocket =  mmServerSocket.accept();} catch (IOException e) {// 通知主线程更新UI, 获取异常mHandler.sendEmptyMessage(Constant.MSG_ERROR);e.printStackTrace();// 服务端退出一直监听线程break;}if(socket != null) {// 管理连接的客户端socketmanageConnectSocket(socket);// 这里应该是手动断开,案例应该是只保证连接一个客户端,所以连接完以后,关闭了服务端socket
//                try {//                    mmServerSocket.close();
//                    mHandler.sendEmptyMessage(Constant.MSG_FINISH_LISTENING);
//                } catch (IOException e) {//                    e.printStackTrace();
//                }}}}/*** 管理连接的客户端socket* @param socket*/private void manageConnectSocket(BluetoothSocket socket) {// 只支持同时处理一个连接// mConnectedThread不为空,踢掉之前的客户端if(mConnectedThread != null) {mConnectedThread.cancle();}// 主线程更新UI,连接到了一个客户端mHandler.sendEmptyMessage(Constant.MSG_GOT_A_CLINET);// 新建一个线程,处理客户端发来的数据mConnectedThread = new ConnectedThread(socket, mHandler);mConnectedThread.start();}/*** 断开服务端,结束监听*/public void cancle() {try {mmServerSocket.close();mHandler.sendEmptyMessage(Constant.MSG_FINISH_LISTENING);} catch (IOException e) {e.printStackTrace();}}/*** 发送数据* @param data*/public void sendData(byte[] data){if(mConnectedThread != null) {mConnectedThread.write(data);}}
}

下面看一个共同通讯处理类:

/*** <p>Title: ConnectedThread</p >* <p>Description: 客户端和服务端 处理 发送数据 和获取数据</p >* <p>Company: ihaveu</p >** @author MaWei* @date 2017/12/26*/
public class ConnectedThread extends Thread{/** 当前连接的客户端BluetoothSocket*/private final BluetoothSocket mmSokcet;/** 读取数据流*/private final InputStream mmInputStream;/** 发送数据流*/private final OutputStream mmOutputStream;/** 与主线程通信Handler*/private Handler mHandler;private String TAG = "ConnectedThread";public ConnectedThread(BluetoothSocket socket,Handler handler) {mmSokcet = socket;mHandler = handler;InputStream tmpIn = null;OutputStream tmpOut = null;try {tmpIn = socket.getInputStream();tmpOut = socket.getOutputStream();} catch (IOException e) {e.printStackTrace();}mmInputStream = tmpIn;mmOutputStream = tmpOut;}@Overridepublic void run() {super.run();byte[] buffer = new byte[1024];while (true) {try {// 读取数据int bytes = mmInputStream.read(buffer);if(bytes > 0) {String data = new String(buffer,0,bytes,"utf-8");// 把数据发送到主线程, 此处还可以用广播Message message = mHandler.obtainMessage(Constant.MSG_GOT_DATA,data);mHandler.sendMessage(message);}Log.d(TAG, "messge size :" + bytes);} catch (IOException e) {e.printStackTrace();}}}// 踢掉当前客户端public void cancle() {try {mmSokcet.close();} catch (IOException e) {e.printStackTrace();}}/*** 服务端发送数据* @param data*/public void write(byte[] data) {try {mmOutputStream.write(data);} catch (IOException e) {e.printStackTrace();}}
}

下面是自己写的一个聊天demo

/*** <p>Title: ChatController</p >* <p>Description: 聊天控制器</p >* <p>Company: ihaveu</p >** @author MaWei* @date 2017/12/26*/
public class ChatController {/** 客户端的线程*/private ConnectThread mConnectThread;/** 服务端的线程*/private AccepThread mAccepThread;private ChatProtocol mProtocol = new ChatProtocol();/*** 网络协议的处理函数*/private class ChatProtocol implements ProtocoHandler<String>{private static final String CHARSET_NAME = "utf-8";/*** 封包(发送数据)* 把发送的数据变成  数组 2进制流*/@Overridepublic byte[] encodePackge(String data) {if(data == null) {return new byte[0];}else {try {return data.getBytes(CHARSET_NAME);} catch (UnsupportedEncodingException e) {e.printStackTrace();return new byte[0];}}}/*** 解包(接收处理数据)* 把网络上数据变成自己想要的数据体*/@Overridepublic String decodePackage(byte[] netData) {if(netData == null) {return "";}else {try {return new String(netData, CHARSET_NAME);} catch (UnsupportedEncodingException e) {e.printStackTrace();return "";}}}}/*** 与服务器连接进行聊天*/public void startChatWith(BluetoothDevice device,BluetoothAdapter adapter,Handler handler){mConnectThread = new ConnectThread(device, adapter, handler);mConnectThread.start();}/*** 等待客户端来连接* handler : 用来跟主线程通信,更新UI用的*/public void waitingForFriends(BluetoothAdapter adapter, Handler handler) {try {mAccepThread = new AccepThread(adapter,handler);mAccepThread.start();} catch (IOException e) {e.printStackTrace();}}/*** 发出消息*/public void sendMessage(String msg){// 封包byte[] data = mProtocol.encodePackge(msg);if(mConnectThread != null) {mConnectThread.sendData(data);}else if(mAccepThread != null) {mAccepThread.sendData(data);}}/*** 网络数据解码*/public String decodeMessage(byte[] data){return mProtocol.decodePackage(data);}/*** 停止聊天*/public void stopChart(){if(mConnectThread != null) {mConnectThread.cancle();}if(mAccepThread != null) {mAccepThread.cancle();}}/*** 以下是单例写法*/private static class ChatControlHolder{private static ChatController mInstance = new ChatController();}public static ChatController getInstance(){return ChatControlHolder.mInstance;}
}

OK,完成,大家主要看上面的广播,和蓝牙sokcet流程,其他的根据自己业务要求写就OK

蓝牙通信,完整的通信流程!相关推荐

  1. 【Binder 机制】AIDL 分析 ( AIDL 通信完整流程梳理 )

    文章目录 AIDL 跨进程通信完整流程梳理 1.AIDL 文件编译 2.注册服务 3.IMyAidlInterface.Stub.asInterface 方法获取远程服务 4.IMyAidlInter ...

  2. DSP:6678开发板NDK网口通信完整实现(附源码)

    如果出现图片打不开,或是显示异常,请点击下方链接阅读原文!!! DSP:6678开发板NDK网口通信完整实现(附源码) - 子木的文章 - 知乎 https://zhuanlan.zhihu.com/ ...

  3. Android Studio 简要实现蓝牙(Bluetooth)通信(附加作业)

    文章目录 一.项目实现功能 二.项目核心代码 1.简要实现设备蓝牙通信 2.模拟Client 和Server端实现简单的通信. 三.实验项目截图 四.源代码 一.项目实现功能 1.两台设备可以通过蓝牙 ...

  4. TR-069 协议完整的通信过程

    TR-069协议完整的通信过程 以下为设备重启到挂上TR069网管的报文流程解析 (1) 设备启动:根据配置的ACS(自动配置服务器)地址,建立安全的HTTP连接以后,每次连接CPE都必须首先对ACS ...

  5. ros分布式多机通信完整教程

    ros多机通信完整试坑教程 文章目录 ros多机通信完整试坑教程 前言: 系统介绍: 1.设置IP和~/.bashrc文件: 列一波搜到的有用的教程: 接着上面的来 第二个bug--图像话题会丢包.延 ...

  6. Android--经典蓝牙(文件传输--socket通信)

    标准蓝牙 UUID 0000xxxx-0000-1000-8000-00805F9B34FB 其中 xxxx 代表自定义部分 例如:蓝牙串口服务1101 -- SerialPortServiceCla ...

  7. cdma matlab仿真程序,基于Matlab的CDMA通信完整系统分析及仿真.doc

    基于Matlab的CDMA通信完整系统分析及仿真 课程论文 题 目: 基于Matlab CDMA多址技术的仿真 学生姓名: 苏未然 学生学号: 1008030130 系 别: 电气信息工程学院 专 业 ...

  8. [C#] 控制电脑蓝牙与外部蓝牙设备通信

    源码:  https://github.com/chinayixia/c-bluetooth-pc-communicate-with-devices_20190820.git using System ...

  9. 雅马哈机械手程序 程序里有跟相机Socket通信数据处理,此流程为锁螺丝

    雅马哈机械手程序 程序里有跟相机Socket通信数据处理,此流程为锁螺丝,对每个螺丝位置进行拍照定位补偿,托盘定义里也设计到 9212615053398703咸鱼也有梦想@@

最新文章

  1. 马斯克连发三推,发布退出OpenAI内情
  2. Windows安装MongoDB
  3. webpack 入口文件 php,webpack,jsx_webpack jsx 找不到入口文件,webpack,jsx - phpStudy
  4. QML基础类型之palette
  5. Mysql的两种“排名第几且有可能为空的记录”写法(力扣176)
  6. Oracle数据库管理
  7. 在Hibernate中使用存储过程
  8. 深度学习的实用层面 —— 1.12 梯度的数值逼近
  9. jQuery each、节点操作、动画演示、尺寸操作、扩展方法
  10. python打印当前文件的绝对路径,并解决打印为空
  11. php日志,记录日志
  12. STC8H开发(十四): I2C驱动RX8025T高精度实时时钟芯片
  13. 如何快速又优雅的一键保存网页
  14. 《剑指offer》-二叉树的下一个节点
  15. FileZilla的安装流程
  16. IC验证培训——SystemVerilog通用程序库(上)
  17. Oracle存储过程基本语法 存储过程
  18. 汇编语言-王爽 第7章 更灵活的定位内存地址的方法-笔记
  19. Nginx_01_Nginx三大基础功能(静态服务器、虚拟主机、负载均衡/服务端代理)
  20. kl变换简单的解释入门_2010年20个最佳入门指南解释者主题

热门文章

  1. 论文复现:模拟风电不确定性——拉丁超立方抽样生成及缩减场景(Matlab全代码)
  2. 群控源码云控安卓PC服务器三端最新源码
  3. 雨林木风系统md5值_除了华为鸿蒙OS系统以外!都还有哪些国产操作系统:好用又美观呢?...
  4. ECG分析:基于深度学习的ECG心律失常分类入门(4)
  5. 【基础篇】详解Zookeeper客户端Curator
  6. 走过14个双11,淘宝天猫迎来价值重估
  7. uni app 开发微信小程序及上线体验
  8. android NFC读取UID
  9. CBTC中ATP的功能需求与应用举例
  10. CSS文字溢出省略号