Android蓝牙开发与蓝牙模块进行通讯(基于eclipse)
private void search() {BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();if (!adapter.isEnabled()) {adapter.enable();}Intent enable = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);enable.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 3600); //3600为蓝牙设备可见时间startActivity(enable);Intent searchIntent = new Intent(this, ComminuteActivity.class);startActivity(searchIntent);}
首先,需要获得一个BluetoothAdapter,可以通过getDefaultAdapter()获得系统默认的蓝牙适配器,当然我们也可以自己指定,但这个真心没有必要,至少我是不需要的。然后我们检查手机的蓝牙是否打开,如果没有,通过enable()方法打开。接着我们再设置手机蓝牙设备的可见,可见时间可以自定义。
完成这些必要的设置后,我们就可以正式开始与蓝牙模块进行通信了:
public class ComminuteActivity extends Activity {private BluetoothReceiver receiver;private BluetoothAdapter bluetoothAdapter;private List<String> devices;private List<BluetoothDevice> deviceList;private Bluetooth client;private final String lockName = "BOLUTEK";private String message = "000001";private ListView listView;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.search_layout);listView = (ListView) this.findViewById(R.id.list);deviceList = new ArrayList<BluetoothDevice>();devices = new ArrayList<String>();bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();bluetoothAdapter.startDiscovery();IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);receiver = new BluetoothReceiver();registerReceiver(receiver, filter);listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {setContentView(R.layout.connect_layout);BluetoothDevice device = deviceList.get(position);client = new Bluetooth(device, handler);try {client.connect(message);} catch (Exception e) {Log.e("TAG", e.toString());}}});}@Overrideprotected void onDestroy() {unregisterReceiver(receiver);super.onDestroy();}private final Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case Bluetooth.CONNECT_FAILED:Toast.makeText(ComminuteActivity.this, "连接失败", Toast.LENGTH_LONG).show();try {client.connect(message);} catch (Exception e) {Log.e("TAG", e.toString());}break;case Bluetooth.CONNECT_SUCCESS:Toast.makeText(ComminuteActivity.this, "连接成功", Toast.LENGTH_LONG).show();break;case Bluetooth.READ_FAILED:Toast.makeText(ComminuteActivity.this, "读取失败", Toast.LENGTH_LONG).show();break;case Bluetooth.WRITE_FAILED:Toast.makeText(ComminuteActivity.this, "写入失败", Toast.LENGTH_LONG).show();break;case Bluetooth.DATA:Toast.makeText(ComminuteActivity.this, msg.arg1 + "", Toast.LENGTH_LONG).show();break;}}};private class BluetoothReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (BluetoothDevice.ACTION_FOUND.equals(action)) {BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);if (isLock(device)) {devices.add(device.getName());}deviceList.add(device);}showDevices();}}private boolean isLock(BluetoothDevice device) {boolean isLockName = (device.getName()).equals(lockName);boolean isSingleDevice = devices.indexOf(device.getName()) == -1;return isLockName && isSingleDevice;}private void showDevices() {ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,devices);listView.setAdapter(adapter);} }
要想与任何蓝牙模块进行通信,首先得搜到该设备:
private class BluetoothReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (BluetoothDevice.ACTION_FOUND.equals(action)) {BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);if (isLock(device)) {devices.add(device.getName());}deviceList.add(device);}showDevices();}}
在这之前,我们得先调用一个方法:
bluetoothAdapter.startDiscovery();
startDiscovery()方法是一个异步方法,它会对其他蓝牙设备进行搜索,持续时间为12秒。搜索过程其实是在System Service中进行,我们可以通过cancelDiscovery()方法来停止这个搜索。在系统搜索蓝牙设备的过程中,系统可能会发送以下三个广播:ACTION_DISCOVERY_START(开始搜索),ACTION_DISCOVERY_FINISHED(搜索结束)和ACTION_FOUND(找到设备)。ACTION_FOUND这个才是我们想要的,这个Intent中包含两个extra fields:EXTRA_DEVICE和EXTRA_CLASS,包含的分别是BluetoothDevice和BluetoothClass,BluetoothDevice中的EXTRA_DEVICE就是我们搜索到的设备对象。 确认搜索到设备后,我们可以从得到的BluetoothDevice对象中获得设备的名称和地址。
在android中使用广播需要我们注册,这里也不例外:
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);receiver = new BluetoothReceiver();registerReceiver(receiver, filter);
广播注册后需要我们撤销,这个可以放在这里进行:
@Overrideprotected void onDestroy() {unregisterReceiver(receiver);super.onDestroy();}
这样在Activity结束的时候就会自动撤销该广播,而不需要我们手动执行。
我这里使用一个ListView来显示搜索到的蓝牙设备,但因为需要只限定一个蓝牙设备,所以这里进行了检查,检查该设备是否是我们的目标设备,如果是,就添加。当然,为了防止重复添加,有必要增加这么一句:
boolean isSingleDevice = devices.indexOf(device.getName()) == -1;
搜索到该设备后,我们就要对该设备进行连接。
public void connect(final String message) {Thread thread = new Thread(new Runnable() {public void run() {BluetoothSocket tmp = null;Method method;try {method = device.getClass().getMethod("createRfcommSocket", new Class[]{int.class});tmp = (BluetoothSocket) method.invoke(device, 1);} catch (Exception e) {setState(CONNECT_FAILED);Log.e("TAG", e.toString());}socket = tmp;try {socket.connect();isConnect = true;} catch (Exception e) {setState(CONNECT_FAILED);Log.e("TAG", e.toString());}
连接设备之前需要UUID,所谓的UUID,就是用来进行配对的,全称是Universally Unique Identifier,是一个128位的字符串ID,用于进行唯一标识。网上的例子,包括谷歌的例子,它们的UUID都是说能用但是我用不了的,都会报出这样的错误:
Service discovery failed
原因可能是作为唯一标识的UUID没有发挥作用,所以,我就利用反射的原理,让设备自己提供UUID。
这个错误在我们把手机既当做客户端有当做服务端的时候,同样也有可能出现,因为作为服务器的时候,我们需要的也是同一个UUID:
mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
作为客户端是这样的:
device.createRfcommSocketToServiceRecord(MY_UUID);
当两个UUID想同时建立Rfcomm的通道时,我们的选择都是在两个线程中分别实现,但是忽略了一件最重要的事情:同一个时间只能充当一个角色!所以,解决这个问题的方法就是在我们相连接的设备上也安装同样的应用程序,谁先发起连接谁就是客户端,但我这里是蓝牙模块啊!!怎么能安装我的应用程序呢!!解决办法就在下面的通信中。
连接设备之前还有一件事必须确保:
bluetoothAdapter.cancelDiscovery();
这是为了停掉搜索设备,否则连接可能会变得非常慢并且容易失败。
有关于Socket的编程都需要我们设置一些状态值来标识通信的状态,以方便我们调错,而且连接应该放在一个线程中进行,要让该线程与我们程序的主线程进行通信,我们需要使用Handle,关于Handle的使用,可以参考我的另一篇博客http://www.cnblogs.com/wenjiang/p/3180324.html,这里不多讲。
在使用Socket中,我注意到一个方法:isConnect(),它返回的是布尔值,但是根本就不需要使用到这个方法,Socket的连接如果没有报错,说明是已经连接上了。
在谷歌提供的例子中,我们可以看到谷歌的程序员的程序水平很高,一些好的编码习惯我们可以学习一下,像是在try..catch中才定义的变量,我们应该在try...catch之前声明一个临时变量,然后再在try...catch后赋值给我们真正要使用的变量。这种做法的好处就是:如果我们直接就是使用真正的变量,当出现异常的时候,该变量的使用就会出现问题,而且很难进行排查,如果是临时变量,我么可以通过检查变量的值来确定是否是赋值时出错。
谷歌的例子中最大的感想就是满满的异常检查,但也是因为这个,导致它的可读性不高。java的异常处理机制有时候对于代码的阅读真的不是一件舒服的事情,能避免就尽量避免。
如果连接没有问题,我们就可以和蓝牙模块进行通信:
if (isConnect) {try {OutputStream outStream = socket.getOutputStream();outStream.write(getHexBytes(message));} catch (IOException e) {setState(WRITE_FAILED);Log.e("TAG", e.toString());}try {InputStream inputStream = socket.getInputStream();int data;while (true) {try {data = inputStream.read();Message msg = handler.obtainMessage();msg.what = DATA;msg.arg1 = data;handler.sendMessage(msg);} catch (IOException e) {setState(READ_FAILED);Log.e("TAG", e.toString());break;}}} catch (IOException e) {setState(WRITE_FAILED);Log.e("TAG", e.toString());}}if (socket != null) {try {socket.close();} catch (IOException e) {Log.e("TAG", e.toString());}}}}
这里包括写入和读取,用法和基本的Socket是一样的,但是写入的时候,需要将字符串转化为16进制:
private byte[] getHexBytes(String message) {int len = message.length() / 2;char[] chars = message.toCharArray();String[] hexStr = new String[len];byte[] bytes = new byte[len];for (int i = 0, j = 0; j < len; i += 2, j++) {hexStr[j] = "" + chars[i] + chars[i + 1];bytes[j] = (byte) Integer.parseInt(hexStr[j], 16);}return bytes;}
当然,这里只是将手机当做客户端,但是接收蓝牙模块发送过来的信息是没有必要特意创建服务端的,我们只要一个不断监听并读取对方消息的循环就行。
很简单的程序就能实现像是蓝牙串口助手的功能,由于是项目的代码,不能贴完整的代码,但是基本上都在上面了,大家可以参考一下。要想使用蓝牙,相应的权限也是必不可少的:
<uses-permission android:name="android.permission.BLUETOOTH"/><uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
这篇博客出自:http://www.cnblogs.com/wenjiang/p/3200138.html
项目可以借鉴,但是打开项目稍微有些问题
代码放在github上:https://github.com/wenjiang/Bluetooth2.git (借鉴博客)
在此基础上,可以用Android studio 来尝试修改代码建立蓝牙通信!
本人的后续项目建成上传至github上。
Android蓝牙开发与蓝牙模块进行通讯(基于eclipse)相关推荐
- Android蓝牙开发 — 经典蓝牙BLE蓝牙
一,前期基础知识储备 1)蓝牙是一种支持设备之间短距离通信的无线电技术(其他还包括红外,WIFI): 支持移动电话.笔记本电脑.无线耳机等设备之间进行信息的交换: Android支持的蓝牙协议栈:Bl ...
- Android蓝牙开发—经典蓝牙详细开发流程
文章目录 开发流程 权限 核心API BlueToothAdapter getDefaultAdapter():获取BluetoothAdapter对象 判断设备是否支持蓝牙 判断蓝牙是否开启 get ...
- 【Android】蓝牙开发——经典蓝牙:配对与解除配对 实现配对或连接时不弹出配对框
目录 一.配对方法 二.解除配对方法 三.配对/解除配对结果 四.justwork配对模式下,不弹出配对框 五.pincode配对模式下,不弹出配对框 六.小结 在之前的文章[Android]蓝牙开发 ...
- android pin码 经典蓝牙_Android蓝牙开发—经典蓝牙详细开发流程
Android蓝牙开发-经典蓝牙详细开发流程 发布时间:2018-07-16 13:41, 浏览次数:637 , 标签: Android Android蓝牙开发前,首先要区分是经典蓝牙开发还是BLE( ...
- 蓝牙配对模式 java_【Android】蓝牙开发—— 经典蓝牙配对介绍(Java代码实现演示)附Demo源码...
目录 前言 一.连接&配对方法介绍 二.演示:第一次连接蓝牙设备 & 直接与蓝牙设备建立配对 三.总结 四.补充 五.Demo案例源码地址: 前言 前面两篇文章[Android]蓝 ...
- 【Android】蓝牙开发—— 经典蓝牙配对介绍(Java代码实现演示)附Demo源码
目录 前言 一.连接&配对方法介绍 二.演示:第一次连接蓝牙设备 & 直接与蓝牙设备建立配对 三.总结 四.补充 五.Demo案例源码地址: 前言 前面两篇文章[Android]蓝 ...
- 从零开始的nrf52832蓝牙开发(1)--蓝牙协议基础
想要进行蓝牙开发,第一步肯定要对蓝牙协议有所了解.除了要对蓝牙的一些专业术语有所熟悉,还应该对蓝牙协议每层功能有一定认知. 概略图: 物理层(PHY): 物理层规定了蓝牙频段:2400MHz~2483 ...
- Android笔记---蓝牙开发经典蓝牙和低功耗蓝牙
目录 前言 一般开发步骤 相关API介绍 一.通用API 1.BluetoothAdapter 2.BluetoothDevice 二.经典蓝牙(BT)API 1.BluetoothSocket 2. ...
- android蓝牙聊天设备,Android蓝牙开发——实现蓝牙聊天
最近课上刚好需要做一个课程设计关于蓝牙的就挑选了个蓝牙聊天室,其实关键还是在于对蓝牙API的了解 一.蓝牙API 与蓝牙开发主要的相关类是以下四个 BluetoothAdapter 字面上则理解为蓝牙 ...
- Android蓝牙开发——经典蓝牙的连接
1.蓝牙的基本操作 蓝牙权限 android.permission.BLUETOOTH //允许程序连接到已配对的蓝牙设备,请求连接/接收连接/传输数据需要改权限, 主要用于对配对后进行操作. and ...
最新文章
- Swift3.0语言教程比较、判断字符串
- 为什么要完成量子计算机,我们为啥要量子计算机?
- 详解KMP算法原理,以及完整java与C++实现
- ubuntu每次启动都出现检测到错误
- BZOJ 3564 信号增幅仪
- .net 导出excel_Qt编写的项目作品18-数据导出到Excel及Pdf和打印数据
- 2017 ACM Jordanian Collegiate Programming Contest
- ios mysql数据库查询语句_ios fmdb数据库查询语句
- spring中的context:include-filter和context:exclude-filter的区别
- 小波包分解、重构 matlab代码
- php 网页加背景音乐,网站背景音乐实现方法_HTML/Xhtml_网页制作
- Intellij IDEA2017破解
- java+桌球小游戏图片_java实战之桌球小游戏
- MNIST在CPU、FPGA、ARM上的运行对比
- maven中实现代码单元测试覆盖率统计
- 如何有效提高生产车间的生产效率呢?
- 微信服务器保留几年记录_企业微信朋友圈管理的工具
- 团体程序设计天梯赛 -- 练习集 (L1合集)
- 每日一题——二叉树的中序遍历
- 论文精读——HOG特征提取