手把手教你Android手机与BLE终端通信--连接,发送和接收数据
假设你还没有看上一篇 手把手教你Android手机与BLE终端通信--搜索,你就先看看吧,由于这一篇要接着讲搜索到蓝牙后的连接。和连接后的发送和接收数据。
评论里有非常多人问假设一条信息特别长,怎么不丢包,或者怎么推断一个完整的信息发送完了呢。
我写的时候连的串口是我们公司硬件project师设计的,他定义好了信息的格式。什么字符开头。什么字符结尾,中间哪几位代表什么意思,我假设不能成功取到一对开头和结尾而且长度也符合我就会丢弃那点信息,取得的完整信息则会依据硬件project师的文档取出app对应地方用到的对应信息。嗯。就是这样。假设你不知道一个串口发给你什么信息,那一定是你拿来玩的串口,工作中用到的都是定制的,不然连接串口干什么呢。
我的基本实现就是全部蓝牙操作都写在BluetoothController中,他有消息要发送时发送到BLEService中,service再发广播提示MainActivity更新页面。好了,切入正题。。
1。连接
首先点击搜索到的蓝牙的listview,连接点击的那个蓝牙:
listview.setOnItemClickListener(new OnItemClickListener() { @Override
public void onItemClick(AdapterView<? > arg0, View arg1, int index,
long arg3) {
BluetoothController.getInstance().connect(list.get(index));
}
});
connect方法仍然写在controller中,那个与蓝牙控制类。
/**
* 连接蓝牙设备
*
* @param device
* 待连接的设备
*/
public void connect(EntityDevice device) {
deviceAddress=device.getAddress();
deviceName=device.getName();
BluetoothDevice localBluetoothDevice = bleAdapter
.getRemoteDevice(device.getAddress());
if (bleGatt != null) { bleGatt.disconnect();
bleGatt.close();
bleGatt = null;
}
bleGatt = localBluetoothDevice.connectGatt(App.app, false,
bleGattCallback);
}
bleGatt是与蓝牙沟通的控制类,系统自带的BluetoothGatt类,它能够连接。断开某设备,或者获取服务,写数据。
蓝牙有非常多服务。但我们要找那个可读写的服务,以下会有查找服务。
你应该注意到bleGattCallback。BluetoothGattCallback,也是系统自带的类。是连接回调类,连接后出现什么情况怎么处理就在这里了。它有非常多方法须要重写。我们仅仅重写两三个。关于连接我们须要重写的是onConnectionStateChange(BluetoothGatt paramAnonymousBluetoothGatt, int oldStatus,int newStatus),第一个參数不用管。我也不知道是什么,第二个參数是原来的状态,第三个參数是后来的状态,这本来就是状态改变回调方法嘛。
对了。0表示未连接上,2表示已连接设备。当成功连接后我们要更新界面,未连接也要更新。由于可能是连接过程中意外中断,也可能有意中断,提醒下亲爱的用户还是比較好的。
/**
* 连接状态改变
*/
public void onConnectionStateChange(
BluetoothGatt paramAnonymousBluetoothGatt, int oldStatus,
int newStatus) {
if (newStatus == 2)// 已连接状态。表明连接成功
{
Message msg=new Message();
msg.what=ConstantUtils.WM_BLE_CONNECTED_STATE_CHANGE;
Bundle bundle=new Bundle();
bundle.putString("address", deviceAddress);
bundle.putString("name", deviceName);
msg.obj=bundle;
serviceHandler.sendMessage(msg);
paramAnonymousBluetoothGatt.discoverServices();
//连接到蓝牙后查找能够读写的服务。蓝牙有非常多服务
return;
}
if (newStatus == 0)// 断开连接或未连接成功
{
serviceHandler.sendEmptyMessage(ConstantUtils.WM_STOP_CONNECT);
return;
}
paramAnonymousBluetoothGatt.disconnect();
paramAnonymousBluetoothGatt.close();
return;
}
这样连接状态改变的消息就发到了service, service接收到消息后发广播提醒界面更新
Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case ConstantUtils.WM_BLE_CONNECTED_STATE_CHANGE:// 连接上某个设备的消息
Bundle bundle = (Bundle) msg.obj;
String address = bundle.getString("address");
String name = bundle.getString("name");
// 连接状态改变广播
Bundle bundle1 = new Bundle();
bundle1.putString("address", address);
bundle1.putString("name", name);
Intent intentDevice = new Intent(
ConstantUtils.ACTION_CONNECTED_ONE_DEVICE);
intentDevice.putExtras(bundle1);
sendBroadcast(intentDevice);
break; case ConstantUtils.WM_STOP_CONNECT:
Intent stopConnect = new Intent(
ConstantUtils.ACTION_STOP_CONNECT);
sendBroadcast(stopConnect);
break;
然后主界面MainActivity接收到广播后更新页面。假设是连接就把连接的设备地址打印出来,假设是断开了,就清除打印而且弹一个toast.当然这些代码在一个receiver中。
else if (intent.getAction().equalsIgnoreCase(ConstantUtils.ACTION_CONNECTED_ONE_DEVICE)){
connectedDevice.setText("连接的蓝牙是:"+intent.getStringExtra("address"));
} else if (intent.getAction().equalsIgnoreCase(ConstantUtils.ACTION_STOP_CONNECT)){
connectedDevice.setText("");
toast("连接已断开");
}
为了測试断开。我关了蓝牙,你能够试试。
2,接收数据
首先你须要下载一个串口助手。能够看到串口接收到的数据。也能够通过串口发送数据到跟他连接的设备。
查看接收到的数据仅仅须要重写上面串口回调BluetoothGattCallback的一个方法,public void onCharacteristicChanged(BluetoothGatt paramAnonymousBluetoothGatt, BluetoothGattCharacteristic paramAnonymousBluetoothGattCharacteristic)
/**
* 与蓝牙通信回调
*/
public BluetoothGattCallback bleGattCallback = new BluetoothGattCallback() {
/**
* 收到消息
*/
public void onCharacteristicChanged(
BluetoothGatt paramAnonymousBluetoothGatt,
BluetoothGattCharacteristic paramAnonymousBluetoothGattCharacteristic) { byte[] arrayOfByte = paramAnonymousBluetoothGattCharacteristic
.getValue();
if(BluetoothController.this.serviceHandler!=null){
Message msg=new Message();
msg.what=ConstantUtils.WM_RECEIVE_MSG_FROM_BLE;
//byte数组转换为十六进制字符串
msg.obj=ConvertUtils.getInstance().bytesToHexString(arrayOfByte);
BluetoothController.this.serviceHandler.sendMessage(msg);
}
//也能够先打印出来看看
Log.i("TEST",ConvertUtils.getInstance().bytesToHexString(arrayOfByte));
}
接下来的操作还是一样,接受到数据发消息到service,service发广播更新到activity界面。
byteToHexString是把byte数组转化成16进制的数值的字符串。
3,发送数据
在输入框上填入要发送的数据,点button发送数据
btnSend.setOnClickListener(new OnClickListener() { @Override
public void onClick(View arg0) {
String str=editSend.getText().toString();
if(str!=null&&str.length()>0){
controller.write(str.getBytes());
}
else {
toast("请填上要发送的内容");
} }
});
发送方法也在controller中
/**
* 数据传输
*
* @param byteArray
* @return
*/
public boolean write(byte byteArray[]) {
if (bleGattCharacteristic == null)
return false;
if (bleGatt == null)
return false;
bleGattCharacteristic.setValue(byteArray);
return bleGatt.writeCharacteristic(bleGattCharacteristic);
} /**
* 数据传输
*
* @param byteArray
* @return
*/
public boolean write(String str) {
if (bleGattCharacteristic == null)
return false;
if (bleGatt == null)
return false;
bleGattCharacteristic.setValue(str);
return bleGatt.writeCharacteristic(bleGattCharacteristic);
}
这里又用来了一个新类,BluetoothGattCharacteristic,他封装了要发送数据。通过bleGatt发送就能够了。bleGatt管的就是连接。断开连接和发送。
最后,一定不要忘了蓝牙的服务,蓝牙有非常多服务,要找到我们要的,你怎么知道要那个服务呢,把每一个服务的属性都打印出来,你就发现仅仅有一个服务的属性是可读可写的。找到它赋值给数据封装类bleGattCharacteristic即可了。
重写回调的onServicesDiscovered(BluetoothGatt paramAnonymousBluetoothGatt, int paramAnonymousInt)方法发现服务。
public void onServicesDiscovered(
BluetoothGatt paramAnonymousBluetoothGatt, int paramAnonymousInt) {
BluetoothController.this.findService(paramAnonymousBluetoothGatt
.getServices());
}
/**
* 搜索服务
*
* @param paramList
*/
public void findService(List<BluetoothGattService> paramList) { Iterator localIterator1 = paramList.iterator();
while (localIterator1.hasNext()) {
BluetoothGattService localBluetoothGattService = (BluetoothGattService) localIterator1
.next();
if (localBluetoothGattService.getUuid().toString()
.equalsIgnoreCase(ConstantUtils.UUID_SERVER)) {
List localList = localBluetoothGattService.getCharacteristics();
Iterator localIterator2 = localList.iterator();
while (localIterator2.hasNext()) {
BluetoothGattCharacteristic localBluetoothGattCharacteristic = (BluetoothGattCharacteristic) localIterator2
.next();
if (localBluetoothGattCharacteristic.getUuid().toString()
.equalsIgnoreCase(ConstantUtils.UUID_NOTIFY)) {
bleGattCharacteristic = localBluetoothGattCharacteristic;
break;
}
}
break;
} } bleGatt.setCharacteristicNotification(bleGattCharacteristic, true);
}
服务号:
public final static String UUID_SERVER="0000ffe0-0000-1000-8000-00805f9b34fb";
public final static String UUID_NOTIFY="0000ffe1-0000-1000-8000-00805f9b34fb";
到哪儿都一样。
假设你看到这儿了,恭喜你,以下都是必备干货:
代码就是这样,包含上次的搜索都在以下的连接里。里面有.apk文件,你先跑跑看效果,还有串口助手exe文件。还有es里的代码,还有串口如何使用,如何配置,我真是太贴心了。
http://pan.baidu.com/s/1geCKYJL
(不要忘了在manifest中加一个权限,为了兼容6.0以上手机:
<uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION"/>
)
真的非常抱歉,假设看了这篇文章还有什么不懂的我已经解答不了了,我已经不维护这个app了,并且手上也没有蓝牙串中。没办法调试了。对不起了各位。
手把手教你Android手机与BLE终端通信--连接,发送和接收数据的更多相关文章
- Android BLE开发——Android手机与BLE终端通信初识
蓝牙BLE官方Demo下载地址: http://download.csdn.net/detail/lqw770737185/8116019参考博客地址: http://www.eoeandr ...
- Android BLE开发之Android手机与BLE终端通信
本文来自http://blog.csdn.net/hellogv/ ,引用必须注明出处! 近期穿戴设备发展得非常火.把相关技术也带旺了,当中一项是BLE(Bluetooth Low Energy).B ...
- 网络编程懒人入门(八):手把手教你写基于TCP的Socket长连接
本文原作者:“水晶虾饺”,原文由“玉刚说”写作平台提供写作赞助,原文版权归“玉刚说”微信公众号所有,即时通讯网收录时有改动. 1.引言 好多小白初次接触即时通讯(比如:IM或者消息推送应用)时,总是不 ...
- 手把手教你Android来去电通话自动录音的方法
我们在使用Android手机打电话时,有时可能会需要对来去电通话自动录音,本文就详细讲解实现Android来去电通话自动录音的方法,大家按照文中的方法编写程序就可以完成此功能. 来去电自动录音的关键在 ...
- Android 手机卫士--构建服务端json、请求网络数据
本文地址:http://www.cnblogs.com/wuyudong/p/5900384.html,转载请注明源地址. 数据的传递 客户端:发送http请求 http://www.oxx.com/ ...
- Android:手把手教你 实现Activity 与 Fragment 相互通信,发送字符串信息(含Demo)
前言Activity 与 Fragment 的使用在Android开发中非常多今天,我将主要讲解 Activity 与 Fragment 如何进行通信,实际上是要解决两个问题: Activity 如何 ...
- Android手机 "已安装了存在签名冲突的同名数据包"
如果你不是开发者:如果你在android上更新一个已经安装过较早版本软件时,安装到最后一步提示你:已安装了存在签名冲突的同名数据包,然后安装失败.这是因为旧版软件的签名信息与新版不一致造成的.你可以卸 ...
- android中如何发送及接收数据(两种方法)?
1.如在MainActivity.java中的按钮点击时设置: //发送数据方法1--简单型 i.putExtra("txt", "没错,我就是刚传来的信息!" ...
- 在Android手机上安装linux系统
在anroid手机中安装fedora系统.记住不只是教你安装fedora系统. 需要的备注与软件 1.一个已经root的Android手机,记住是root后的,root后的,root后的.(重要的事情 ...
随机推荐
- 在qemu上运行BusyBox
BusyBox 前文“在qemu环境中用gdb调试Linux内核”和“Initramfs 原理和实践”分别描述了怎么用qemu来运行一个编译好的内核,以及怎么指定initramfs,但都是简单的演示. ...
- Java 异常处理之 论 finally块何时候不走
一. exit退出异常: import java.util.Scanner; public class Test3exit { /** * @param 房山的猫 * finally什么时候不走 * ...
- NPE是什么
在编程中出现的空指针异常 Map类集合K/V能不能存储null值的情况,如下表格: remove元素要使用Iterator方式,如果并发操作,需要对Iterator对象加锁. Arrays.asLis ...
- WebApi-JSON序列化循环引用
Overview 最近被序列化,循环引用的问题,让我浑身酸爽.遇到这种异常是在搭建WebApi的时候,当我返回Linq实例类集合的时候出现的. 下定决心要解决这个问题.循环引用引起的原因是: 比如说: ...
- CentOS7.4 关闭firewall防火墙,改用iptables
1.关闭默认的firewall防火墙 systemctl stop firewalld.service #停止firewall systemctl disable firewalld.service ...
- 网站(Web)压测工具Webbench源码分析
一.我与webbench二三事 Webbench是一个在linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的性能.Webbench ...
- Ruby on rails配置环境问题【慢慢添加】
1, ruby -v 与 rvm list 显示不同的版本号 ,使用rvm use 2.2.3后,报如下错误: RVM is not a function 解决办法: $ source ~/.rv ...
- centos7搭建.netcore运行环境
开发环境介绍 1.操作系统:Windows Server 2008 R2 Enterprise 2.IDE:VisualStudio2017 3..Net Core 2.0 SDK 本文假设你已经满足 ...
- JVM垃圾回收(GC)流程
/* 首先介绍一下JVM中堆内存的组成: JVM堆内存主要由三部分组成: (1)新生代: 伊甸园区,存活区,伸缩区 (2)老年代: 老年区,伸缩区 (3)元空间(永久代): 元空间,伸缩区 注意:JD ...
- 成为一名JAVA高级工程师你需要学什么【转】
宏观上: 1.技术广度方面至少要精通多门开源技术吧,研究过struts\spring等的源码. 2.项目经验方面从头到尾跟过几个大项目,头是指需求阶段,包括需求调研.尾是指上线交付之后,包括维护阶段. ...