当前位置:首页 > 嵌入式培训 > 嵌入式学习 > 讲师博文 > Android蓝牙调试助手实现

Android蓝牙调试助手实现 时间:2018-08-15      来源:未知

蓝牙( Bluetooth ):是一种无线技术标准,可实现固定设备、移动设备和楼宇个人域网之间的短距离数据交换(使用2.4—2.485GHz的ISM波段的UHF无线电波)。蓝牙技术初由电信巨头爱立信公司于1994年创制,当时是作为RS232数据线的替代方案。蓝牙可连接多个设备,克服了数据同步的难题。

蓝牙4.0是2012年新蓝牙版本,是3.0的升级版本;较3.0版本更省电、成本低、3毫秒低延迟、超长有效连接距离、AES-128加密等;通常用在蓝牙耳机、蓝牙音箱等设备上。

本项目是基于蓝牙4.0的串口调试助手。主要应用在携带蓝牙4.0的设备上,功能是主动扫描周边的蓝牙设备,连接成功后,模块所发送的数据会显示在对应的区域。同时,还能够向模块发送信息。接受和发送的信息都可以选择为十六进制。

第 1 章 使用说明

软件共分为三个部分:数据接收区,数据发送区,设备扫描区。

点击搜索,软件会开始进行周边蓝牙设备的扫描,需要等待五分钟。

扫描完成后,设备会在右侧显示出来,点击设备就可以连接。

这是结婚搜到的数据就会显示在左侧,当不需要的时候,点击右下角的断开,就可以中断和设备的连接。

第 2 章 环境搭建

2.1 Android 开发环境的安装与配置

Android应用软件开发需要的开发环境在路径“光盘\Android应用开发环境\”下:

JDK: JDK\JDK8\jdk-8u5-windows-i586.exe(32bit)或者jdk-8u5-windows-x64.exe(64bit)

(从JDK 8.0开始不支持Windows XP操作系统,使用Windows XP的用户可以使用JDK7目录下的内容)

ADT: adt-bundle-windows-x86.7z(32bit)或者adt-bundle-windows-x86_64.7z(64bit)

以下主要介绍在Windows环境下搭建Android开发环境的步骤和注意事项。

2.2 安装JDK和配置Java开发环境

双击JDK\JDK8\jdk-8u5-windows-i586.exe(32bit操作系统)或者jdk-8u5-windows-x64.exe(64bit操作系统)进行安装(从JDK 8.0开始不支持Windows XP操作系统,使用Windows XP的用户可以使用JDK7目录下的内容选择代替JDK8目录下的内容)。接受许可证,选择需要安装的组件和安装路径后,单击“下一步”按钮,完成安装过程。

安装完成后,利用以下步骤检查安装是否成功:打开Windows CMD窗口,在CMD窗口中输入java –version命令,如果屏幕出现下图所示的代码信息,说明JDK安装成功。

XP下安装JDK7如下:

非XP下安装JDK8如下:

2.3 解压adt-bundle-windows

JDK安装成功后,使用软件解压ADT目录下的adt-bundle-windows-x86.7z(32bit)或者adt-bundle-windows-x86_64.7z(64bit)。

注意:解压路径不包含中文;

2.4 运行Eclipse

解压完毕后,直接执行其中的eclipse\eclipse.exe文件,Eclipse可以自动找到用户前期安装的JDK路径。

2.5 配置Eclipse

运行解压目录下的eclipse\eclipse.exe,为自己选择一个工作目录Workspace,不要有中文路径,不选择默认也可以。

需要为Eclipse关联SDK的安装路径,即解压路径下的sdk目录。在Eclipse中,点击Window->Preferences,会看到其中添加了Android的配置,按图所示的操作,然后点击Apply,后点击OK即可。

完成以上步骤后,设置Eclipse环境

勾选Android相关的工具,点击OK(如果已经勾选,则不理会)。

第 3 章 源码编译

3.1 导入源码

打开Eclipse环境,选择File->Import。

然后,导入光盘资料中的“BlueHelper”工程,勾选下图中的选项。

点击finish完成工程的导入

3.2 运行程序

注意:如果在调试开发板的时候,出现ADB连接不上的问题(已知华清远见FSPAD723开源平板),可以试着替换Android SDK的ADB工具(把光盘\Android应用开发环境\ADB\ADB1.0.26\下的4个文件拷贝到用户ADT解压目录下的sdk\platform-tools中)

开发期间,在实际的设备上运行Android程序与在模拟器上运行该程序的效果几乎相同,需要做的就是用USB电缆连接手机与计算机,并安装一个对应的设备驱动程序。如果模拟器窗口已打开,请将其关闭。只要将开发平台通过USB下载线与计算机相连,应用程序就会在开发平台上加载并运行。

在Eclipse中选择“Run” →“Run”(或Debug)命令(或者在工程上点击右键),这时会弹出一个窗口,让你选择用模拟器还是手机来显示,如果选择手机,即可在手机上运行该程序。

第 4 章 详细设计

4.1 BlueTool蓝牙工具

蓝牙4.0采用了新的协议,与2.0并不通用,所以这里封装了工具类来进行数据的沟通。

BluetoothGatt类是连接远程设备返回的代理类,我们需要用这个类来进行服务和特征值得获取。

NormalText Code

private BluetoothGatt bluetoothGatt = null;

private BluetoothAdapter bluetoothAdapter = null;

private BluetoothGattService bluetoothService = null;

private BluetoothGattCharacteristic characteristic = null;

这里定义的UUID是连接特定的服务和特征值,如果有需要的话,可以在这里进行更改来实现别的需求。

NormalText Code

public static String serviceUUID = "00001234-0000-1000-8000-00805f9b34fb";

public static String characteristicUUID = "0000fff6-0000-1000-8000-00805f9b34fb";

连接蓝牙的第一步,需要先扫描设备,这里给出扫描的方法,需要调用协议中已经实现的方法startLeScan()来获得设备,之后,再通过stopLeScan()函数来停止扫描。

NormalText Code

// 搜索设备并添加到列表中

public Boolean SearchToList() {// 打开蓝牙,搜索设备

if (bluetoothAdapter != null) {

if (bluetoothAdapter.getState() == BluetoothAdapter.STATE_OFF) {

// 打开蓝牙

bluetoothAdapter.enable();

log.E("打开蓝牙!");

// 搜索设备

bluetoothAdapter.startLeScan(scanCallback);

log.E("开始搜索!");

return true;

} else {

// 搜索设备

bluetoothAdapter.startLeScan(scanCallback);

log.E("开始搜索!");

return true;

}

} else {

log.E("bluetoothAdapter == null");

return false;

}

}

当startLeScan()扫描到设备的时候,会回调下面的这个函数,我们要做的就是在这个函数中将扫描到的设备添加进设备列表就行。

NormalText Code

private BluetoothAdapter.LeScanCallback scanCallback = new BluetoothAdapter.LeScanCallback() {

@Override

public void onLeScan(final BluetoothDevice device, int rssi,

byte[] scanRecord) {

if ((device != null) && (deviceList != null)) {

if ((Isrepeat(device, deviceList) == false)

&& (device.getName() != null)) {

deviceList.add(device);

deviceName.add(device.getName());

deviceAddr.add(device.getAddress());

}

}

}

};

连接完成后,需要获得特征值进行读写操作。

NormalText Code

// 连接设备并获得特征值

public synchronized boolean BLEConnect(BluetoothDevice remoteDev) {

if (remoteDev == null) {

return false;

}

bluetoothGatt = remoteDev.connectGatt(context, false, gattCallback);

return true;

}

当connectGatt函数返回之后,会回调BluetoothGattCallback 变量当中的onConnectionStateChange函数,然后在这个函数中,我们要继续调用discoverServices这个函数来发现设备所提供的服务。当discoverServices被调用的时候,也会进行onServicesDiscovered这个函数的回调。在这个函数中,如果我们想要读取设备的数据,需要通过setCharacteristicNotification来设定接受通知,这样,当设备有数据传过来的时候,会自动通知程序,我们只需要在onCharacteristicChanged中将返回的数据取出来就行。

NormalText Code

private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {

@Override

public void onConnectionStateChange(BluetoothGatt gatt, int status,

int newState) {

if (bluetoothGatt != null) {

if (newState == BluetoothProfile.STATE_CONNECTED) {

log.E("连接成功!");

handler.sendEmptyMessage(3);

gatt.discoverServices();

} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {

log.E("连接断开!");

handler.sendEmptyMessage(4);

}

}

}

@Override

public void onServicesDiscovered(BluetoothGatt gatt, int status) {

if (gatt != null) {

bluetoothService = gatt

.getService(UUID.fromString(serviceUUID));

if (bluetoothService != null) {

characteristic = bluetoothService.getCharacteristic(UUID

.fromString(characteristicUUID));

if (characteristic != null) {

bluetoothGatt.setCharacteristicNotification(

characteristic, true);

// bluetoothGatt.readCharacteristic(characteristic);

} else {

log.E("characteristic == null");

}

} else {

log.E("bluetoothService == null");

}

}

}

@Override

public void onCharacteristicChanged(BluetoothGatt gatt,

BluetoothGattCharacteristic characteristic) {

// log.E("onCharacteristicChanged");

readDate = characteristic.getValue();

if ((readDate != null) && (readDate.length > 0)) {

// log.E("接收数据成功!" + printHex(readDate) + "-" +

// readDate.length);

handler.sendEmptyMessage(1);

handler.sendEmptyMessage(2);

} else {

log.E("接收数据失败!");

}

}

@Override

public void onCharacteristicWrite(BluetoothGatt gatt,

BluetoothGattCharacteristic characteristic, int status) {

log.E("onCharacteristicWrite" + "-" + status);

}

@Override

public void onCharacteristicRead(BluetoothGatt gatt,

BluetoothGattCharacteristic characteristic, int status) {

log.E("onCharacteristicRead" + "-" + status);

};

};

4.2 Bluehelper调试助手

主界面的程序,是通过Handler机制进行消息的传递的。

NormalText Code

@SuppressLint("HandlerLeak")

private final Handler handler = new Handler() {

@Override

public void handleMessage(Message msg) {

switch (msg.what) {

case 0:// 刷新搜索列表

devices = blue.GetdeviceName();

adapter.clear();

for (int i = 0; i < devices.size(); i++) {

adapter.add(blue.GetdeviceName().get(i) + " : "

+ blue.GetdeviceAddr().get(i));

}

adapter.notifyDataSetChanged();

break;

case 1:// 更新接收界面

if (hexrece.isChecked()) {

txtrece.append(printHex(BlueTool.readDate) + " \n");

} else {

txtrece.append(BlueTool.readDate.toString() + " \n");

}

scroll.fullScroll(ScrollView.FOCUS_DOWN);// 滚动到底

break;

case 2:// 持续读取数据

if (threadon == false) {

threadon = true;

// new readThread().start();

}

break;

case 3:// 改变按钮

close.setVisibility(0);

Toast.makeText(Bluehelper.this, "连接成功".toString(),

Toast.LENGTH_SHORT).show();

break;

case 4:// 改变按钮

close.setVisibility(4);

Toast.makeText(Bluehelper.this, "连接断开".toString(),

Toast.LENGTH_SHORT).show();

break;

case 5:// 改变按钮

Toast.makeText(Bluehelper.this, "没有搜索到设备".toString(),

Toast.LENGTH_SHORT).show();

break;

case 10:// 改变按钮

Toast.makeText(Bluehelper.this, msg.obj.toString(),

Toast.LENGTH_SHORT).show();

break;

default:

break;

}

}

};

在onCreate函数中,我们需要设定界面中各个按键的回调函数。

NormalText Code

adapter = new ArrayAdapter(Bluehelper.this,

android.R.layout.simple_list_item_1, new ArrayList());

list.setAdapter(adapter);

list.setOnItemClickListener(new OnItemClickListener() {

@Override

public void onItemClick(AdapterViewparent, View view,

int position, long id) {

if (close.getVisibility() == 4) {

// log.E("点击位置:" + position);

new connectThread(position).start();

}

}

});

search.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

new searchThread().start();

}

});

close.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

if (blue != null) {

blue.Quit();

}

close.setVisibility(4);

}

});

clear.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

txtrece.setText("");

}

});

send.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

if (close.getVisibility() == 0) {

if (txtsend.getText().toString().length() > 0) {

if (hexsend.isChecked()) {

blue.write(BlueTool.StrToByte(txtsend.getText()

.toString()));

} else {

blue.write(txtsend.getText().toString().getBytes());

}

}

} else {

Toast.makeText(Bluehelper.this, "请先连接设备".toString(),

Toast.LENGTH_SHORT).show();

}

}

});

searchThread 连接线程,主要工作就是调用蓝牙工具中的SearchToList,等待扫描5s后,再停止扫描。

NormalText Code

class searchThread extends Thread {

@Override

public void run() {

// log.E("开始蓝牙搜索。。。。。");

Message msg = new Message();

msg.what = 10;

msg.obj = "开始搜索。。。";

handler.sendMessage(msg);

blue.Clear();

handler.sendEmptyMessage(0);

Boolean on = blue.SearchToList();

try {

sleep(5000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

blue.Disserach();

if (blue.GetdeviceName().size() > 0) {

log.E("搜索到的设备:" + blue.GetdeviceName());

if (true == on) {

handler.sendEmptyMessage(0);

} else {

log.E("搜索异常!");

}

} else {

log.E("没有搜索到设备!");

handler.sendEmptyMessage(5);

}

}

}

上一篇:主流嵌入式操作系统有哪些

下一篇:数模转换(芯片PCF8591)

热点文章推荐
华清学员就业榜单
高薪学员经验分享
热点新闻推荐
前台专线:010-82525158 企业培训洽谈专线:010-82525379 院校合作洽谈专线:010-82525379 Copyright © 2004-2022 北京华清远见科技集团有限公司 版权所有 ,京ICP备16055225号-5京公海网安备11010802025203号

回到顶部