Android单片机与蓝牙模块通信实例代码
啦啦毕业了,毕业前要写毕业设计,需要写一个简单的蓝牙app进行交互,通过参考网上资料,问题顺利搞定,下面小编把具体实现思路分享给大家,供大家参考。
1、android蓝牙编程
蓝牙3.0及以下版本编程需要使用uuid,uuid是通用唯一识别码(universally unique identifier),这是一个软件构建的标准,也是被开源基金会组织应用在分布式计算环境领域的一部分。在蓝牙3.0及下一版本中,uuid被用于唯一标识一个服务,比如文件传输服务,串口服务、打印机服务等,如下:
#蓝牙串口服务 serialportserviceclass_uuid = '{00001101-0000-1000-8000-00805f9b34fb}' lanaccessusingpppserviceclass_uuid = '{00001102-0000-1000-8000-00805f9b34fb}' #拨号网络服务 dialupnetworkingserviceclass_uuid = '{00001103-0000-1000-8000-00805f9b34fb}' #信息同步服务 irmcsyncserviceclass_uuid = '{00001104-0000-1000-8000-00805f9b34fb}' sdp_obexobjectpushserviceclass_uuid = '{00001105-0000-1000-8000-00805f9b34fb}' #文件传输服务 obexfiletransferserviceclass_uuid = '{00001106-0000-1000-8000-00805f9b34fb}' irmcsynccommandserviceclass_uuid = '{00001107-0000-1000-8000-00805f9b34fb}'
蓝牙的连接有主从设备,提供服务的可以认为是从设备。主设备通过uuid访问从设备提供具有相同uuid的服务,从而建立客服端—服务器(c/s)模式。
2、编程步骤
android使用蓝牙,需要获得权限,蓝牙权限获得代码如下:
<!-- 蓝牙权限 --> <uses-permission android:name="android.permission.bluetooth"/> <uses-permission android:name="android.permission.bluetooth_admin"/>
获取本地蓝牙适配器,如果蓝牙未开启,开启蓝牙设备:
bluetoothadapter = bluetoothadapter.getdefaultadapter(); if (bluetoothadapter == null) { // device does not support bluetooth return; } // 开启蓝牙 int request_enable_bt = 1; if (!bluetoothadapter.isenabled()) { intent intent = new intent(bluetoothadapter.action_request_enable); startactivityforresult(intent, request_enable_bt); }
搜索已配对的蓝牙设备,并添加到已配对列表中:
// 查询配对设备 list<string> devices = new arraylist<string>(); set<bluetoothdevice> bondeddevices = bluetoothadapter.getbondeddevices(); for (bluetoothdevice device : bondeddevices) { devices.add(device.getname() + "-" + device.getaddress()); }
搜索未配对蓝牙设备,并添加到未配对列表:
mbluetoothadapter.startdiscovery(); //开始收索 搜索接收函数: final broadcastreceiver mreceiver = new broadcastreceiver() { public void onreceive(context context, intent intent) { string action = intent.getaction(); // when discovery finds a device if (bluetoothdevice.action_found.equals(action)) { // get the bluetoothdevice object from the intent bluetoothdevice device = intent.getparcelableextra(bluetoothdevice.extra_device); // add the name and address to an array adapter to show in a listview marrayadapter.add(device.getname() + "\n" + device.getaddress()); } } }; // 收索接收函数需要注册: // register the broadcastreceiver intentfilter filter = new intentfilter(bluetoothdevice.action_found); registerreceiver(mreceiver, filter); // don't forget to unregister during ondestroy
如果是服务器端,需要建立监听,注意监听的是某个服务的uuid,服务器监听类如下:
private class connectthread extends thread { private final string my_uuid = "00001101-0000-1000-8000-00805f9b34fb"; private final bluetoothsocket socket; private final bluetoothdevice device; public connectthread(bluetoothdevice device) { this.device = device; bluetoothsocket tmp = null; try { tmp = device.createrfcommsockettoservicerecord(uuid.fromstring(my_uuid)); } catch (ioexception e) { e.printstacktrace(); } this.socket = tmp; } public void run() { bluetoothadapter.canceldiscovery(); try { socket.connect(); connectedthread = new connectedthread(socket); connectedthread.start(); } catch (ioexception e) { try { socket.close(); } catch (ioexception ee) { ee.printstacktrace(); } return; } //manageconnectedsocket(socket); } public void cancel() { try { socket.close(); } catch (ioexception e) { e.printstacktrace(); } } }
客户端与服务器端建立连接成功后,需要connectedthread类接收发送数据:
// 客户端与服务器建立连接成功后,用connectedthread收发数据 private class connectedthread extends thread { private final bluetoothsocket socket; private final inputstream inputstream; private final outputstream outputstream; public connectedthread(bluetoothsocket socket) { this.socket = socket; inputstream input = null; outputstream output = null; try { input = socket.getinputstream(); output = socket.getoutputstream(); } catch (ioexception e) { e.printstacktrace(); } this.inputstream = input; this.outputstream = output; } public void run() { byte[] buff = new byte[1024]; int bytes; while (true) { try { bytes = inputstream.read(buff); string str = new string(buff, "iso-8859-1"); str = str.substring(0, bytes); log.e("recv", str); } catch (ioexception e) { e.printstacktrace(); break; } } } public void write(byte[] bytes) { try { outputstream.write(bytes); } catch (ioexception e) { e.printstacktrace(); } } public void cancel() { try { socket.close(); } catch (ioexception e) { e.printstacktrace(); } } }
到此为止就是蓝牙开发的大致步骤,其中没有涉及到蓝牙客户端建立连接类,不过可查阅ble和经典蓝牙android开发。
3、毕设蓝牙app介绍
毕设蓝牙app需要接收单片机通过蓝牙模块发送上来的数据,并且蓝牙app也可以给单片机发送数据来进行控制。页面布局如下,一个是整体页面,一个是设置页面,测试手机是魅蓝note。因为毕设做的是十字路口红绿灯控制系统,所有页面布局有4个led灯,分别代表路口的4个红绿灯,会根据时间不同显示不同的颜色(红/绿/黄),并且会显示倒计时,最后来一张红绿灯系统整体图。
activity_main.xml文件如下:
<?xml version="1.0" encoding="utf-8"?> <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="wrap_content" android:paddingleft="@dimen/activity_horizontal_margin" android:paddingright="@dimen/activity_horizontal_margin" android:paddingtop="@dimen/activity_vertical_margin" android:paddingbottom="@dimen/activity_vertical_margin" tools:context=".mainactivity"> <linearlayout android:id="@+id/linear_layout_top" android:layout_alignparenttop="true" android:layout_width="match_parent" android:layout_height="40dp"> <textview android:id="@+id/notice_view" android:layout_width="0dp" android:layout_height="40dp" android:text="蓝牙未开启" android:layout_weight="3"/> <textview android:id="@+id/notice_recv_view" android:layout_width="0dp" android:layout_height="30dp" android:layout_weight="3"/> <textview android:id="@+id/notice_send_view" android:layout_width="0dp" android:layout_height="30dp" android:layout_weight="3"/> <button android:id="@+id/turn_on_off" android:layout_width="0dp" android:layout_height="40dp" android:layout_weight="2" android:text="on"/> </linearlayout> <textview android:id="@+id/led1" android:layout_centerhorizontal="true" android:layout_below="@+id/linear_layout_top" android:layout_width="40dp" android:layout_height="20dp" android:gravity="center" android:text="led1"/> <textview android:id="@+id/led0" android:layout_centerhorizontal="true" android:layout_below="@+id/led1" android:layout_width="40dp" android:layout_height="20dp" android:gravity="center" android:text="+"/> <textview android:id="@+id/led3" android:layout_below="@+id/led1" android:layout_toleftof="@+id/led1" android:layout_width="40dp" android:layout_height="20dp" android:gravity="center" android:text="led3"/> <textview android:id="@+id/led2" android:layout_centerhorizontal="true" android:layout_below="@+id/led3" android:layout_width="40dp" android:layout_height="20dp" android:gravity="center" android:text="led2"/> <textview android:id="@+id/led4" android:layout_below="@+id/led1" android:layout_torightof="@+id/led1" android:layout_width="40dp" android:layout_height="20dp" android:gravity="center" android:text="led4"/> <scrollview android:id="@+id/scroll_view" android:layout_below="@+id/led2" android:layout_above="@+id/linear_layout_bottom" android:layout_width="match_parent" android:layout_height="match_parent"> <textview android:id="@+id/recv_view" android:text="" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </scrollview> <linearlayout android:id="@+id/linear_layout_bottom" android:layout_alignparentbottom="true" android:layout_width="match_parent" android:layout_height="50dp"> <button android:id="@+id/clear_recv_view" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:text="clear" /> <edittext android:id="@+id/send_text" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="3" android:hint="输入框,默认@#结尾"/> <button android:id="@+id/send" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:text="send" /> </linearlayout> </relativelayout>
mainactivity.java文件如下:
package com.luoxn28.bluetooth; import android.bluetooth.bluetoothadapter; import android.bluetooth.bluetoothdevice; import android.bluetooth.bluetoothsocket; import android.content.intent; import android.graphics.color; import android.os.bundle; import android.os.message; import android.support.v7.app.actionbaractivity; import android.view.menu; import android.view.menuitem; import android.view.view; import android.widget.button; import android.widget.edittext; import android.widget.scrollview; import android.widget.textview; import android.widget.toast; import java.io.ioexception; import java.io.inputstream; import java.io.outputstream; import java.util.arraylist; import java.util.list; import java.util.set; import java.util.uuid; public class mainactivity extends actionbaractivity implements view.onclicklistener { public static final int recv_view = 0; public static final int notice_view = 1; private bluetoothadapter bluetoothadapter = null; private connectthread connectthread = null; private connectedthread connectedthread = null; private textview noticeview = null; private button turnonoff = null; private textview led0, led1, led2, led3, led4; scrollview scrollview = null; private textview recvview = null; private button clearrecvview = null; private edittext sendtext = null; private button send = null; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); // 获取bluetoothadapter bluetoothadapter = bluetoothadapter.getdefaultadapter(); if (bluetoothadapter == null) { // device does not support bluetooth return; } // 注册监听事件 noticeview = (textview) findviewbyid(r.id.notice_view); turnonoff = (button) findviewbyid(r.id.turn_on_off); led0 = (textview) findviewbyid(r.id.led0); led1 = (textview) findviewbyid(r.id.led1); led2 = (textview) findviewbyid(r.id.led2); led3 = (textview) findviewbyid(r.id.led3); led4 = (textview) findviewbyid(r.id.led4); scrollview = (scrollview) findviewbyid(r.id.scroll_view); recvview = (textview) findviewbyid(r.id.recv_view); clearrecvview = (button) findviewbyid(r.id.clear_recv_view); sendtext = (edittext) findviewbyid(r.id.send_text); send = (button) findviewbyid(r.id.send); turnonoff.setonclicklistener(this); clearrecvview.setonclicklistener(this); send.setonclicklistener(this); if (!bluetoothadapter.isenabled()) { noticeview.settext("蓝牙未开启"); } else { noticeview.settext("蓝牙已开启"); } noticeview.setbackgroundcolor(color.gray); led0.setbackgroundcolor(color.gray); led1.setbackgroundcolor(color.gray); led2.setbackgroundcolor(color.gray); led3.setbackgroundcolor(color.gray); led4.setbackgroundcolor(color.gray); } private boolean ison = false; @override public void onclick(view view) { switch (view.getid()) { case r.id.turn_on_off: // 发送'0'或者'1'都可以 if (bluetoothadapter == null || !bluetoothadapter.isenabled()) { toast.maketext(this, "蓝牙未开启", toast.length_short).show(); break; } if (connectedthread == null) { toast.maketext(this, "未连接设备", toast.length_short).show(); break; } string turn_string = "1@#"; connectedthread.write(turn_string.getbytes()); if (ison == false) { ison = true; // 打开了 turnonoff.settext("off"); led1.settext(""); led2.settext(""); led3.settext(""); led4.settext(""); } else { ison = false; // 关闭了 turnonoff.settext("on"); led1.settext("led1"); led2.settext("led2"); led3.settext("led3"); led4.settext("led4"); } break; case r.id.clear_recv_view: // 清空接收框 recvview.settext(""); break; case r.id.send: // 发送数据,默认以"@#"结尾 if (bluetoothadapter == null || !bluetoothadapter.isenabled()) { toast.maketext(this, "蓝牙未开启", toast.length_short).show(); return; } if (connectedthread == null) { toast.maketext(this, "未连接设备", toast.length_short).show(); break; } string inputtext = sendtext.gettext().tostring() + "@#"; // 发送给单片机数据以"@#结尾",这样单片机知道一条数据发送结束 //toast.maketext(mainactivity.this, inputtext, toast.length_short).show(); connectedthread.write(inputtext.getbytes()); break; default: break; } } private android.os.handler handler = new android.os.handler() { public void handlemessage(message msg) { bundle bundle = null; switch (msg.what) { case recv_view: if (ison == false) { ison = true; turnonoff.settext("off"); } bundle = msg.getdata(); string recv = bundle.getstring("recv"); recvview.append(recv + "\n"); scrollview.fullscroll(scrollview.focus_down); // 滚动到底部 if (recv.isempty() || recv.contains(" ") || recv.contains("#")) { break; } int num = integer.valueof(recv) / 2; // 0-60s if (num <= 20) { led1.settext(""); led2.settext(""); led3.settext(""); led4.settext(""); led1.setbackgroundcolor(color.red); led2.setbackgroundcolor(color.red); led3.setbackgroundcolor(color.green); led4.setbackgroundcolor(color.green); } else if (num < 30) { int n = 30 - num; led1.settext("" + n); led2.settext("" + n); if (num < 28) { led3.setbackgroundcolor(color.green); led4.setbackgroundcolor(color.green); } else { led3.setbackgroundcolor(color.yellow); led4.setbackgroundcolor(color.yellow); } } else if (num <= 50) { led1.settext(""); led2.settext(""); led3.settext(""); led4.settext(""); led1.setbackgroundcolor(color.green); led2.setbackgroundcolor(color.green); led3.setbackgroundcolor(color.red); led4.setbackgroundcolor(color.red); } else { int n = 60 - num; led3.settext("" + n); led4.settext("" + n); if (num < 58) { led1.setbackgroundcolor(color.green); led2.setbackgroundcolor(color.green); } else { led1.setbackgroundcolor(color.yellow); led2.setbackgroundcolor(color.yellow); } } break; case notice_view: bundle = msg.getdata(); string notice = bundle.getstring("notice"); noticeview.settext(notice); break; default: break; } } }; @override public boolean oncreateoptionsmenu(menu menu) { // inflate the menu; this adds items to the action bar if it is present. getmenuinflater().inflate(r.menu.menu_main, menu); return true; } @override public boolean onoptionsitemselected(menuitem item) { int id = item.getitemid(); if (id == r.id.start_bluetooth) { if (bluetoothadapter != null) { // 开启蓝牙 int request_enable_bt = 1; if (!bluetoothadapter.isenabled()) { intent intent = new intent(bluetoothadapter.action_request_enable); startactivityforresult(intent, request_enable_bt); noticeview.settext("开启蓝牙成功"); //toast.maketext(this, "开启蓝牙成功", toast.length_short).show(); } else { toast.maketext(this, "蓝牙已开启", toast.length_short).show(); } } return true; } else if (id == r.id.show_devices) { if (bluetoothadapter != null) { if (!bluetoothadapter.isenabled()) { toast.maketext(this, "蓝牙未开启", toast.length_short).show(); return true; } // 查询配对设备 list<string> devices = new arraylist<string>(); set<bluetoothdevice> bondeddevices = bluetoothadapter.getbondeddevices(); for (bluetoothdevice device : bondeddevices) { devices.add(device.getname() + "-" + device.getaddress()); } stringbuilder text = new stringbuilder(); for (string device : devices) { text.append(device + "\n"); } toast.maketext(this, text, toast.length_short).show(); } return true; } else if (id == r.id.find_devices) { toast.maketext(this, "该功能暂时不可用", toast.length_short).show(); } else if (id == r.id.connect_devices) { if (bluetoothadapter == null || !bluetoothadapter.isenabled()) { toast.maketext(this, "蓝牙未开启", toast.length_short).show(); return true; } // 查询配对设备 建立连接,只能连接第一个配对的设备 list<string> devices = new arraylist<string>(); set<bluetoothdevice> bondeddevices = bluetoothadapter.getbondeddevices(); for (bluetoothdevice device : bondeddevices) { connectthread = new connectthread(device); connectthread.start(); //toast.maketext(this, "连接成功", toast.length_short).show(); break; } } return super.onoptionsitemselected(item); } private class connectthread extends thread { private final string my_uuid = "00001101-0000-1000-8000-00805f9b34fb"; private final bluetoothsocket socket; private final bluetoothdevice device; public connectthread(bluetoothdevice device) { this.device = device; bluetoothsocket tmp = null; try { tmp = device.createrfcommsockettoservicerecord(uuid.fromstring(my_uuid)); } catch (ioexception e) { e.printstacktrace(); } this.socket = tmp; } public void run() { bluetoothadapter.canceldiscovery(); try { socket.connect(); connectedthread = new connectedthread(socket); connectedthread.start(); } catch (ioexception e) { try { socket.close(); } catch (ioexception ee) { ee.printstacktrace(); } return; } //manageconnectedsocket(socket); } public void cancel() { try { socket.close(); } catch (ioexception e) { e.printstacktrace(); } } } // 客户端与服务器建立连接成功后,用connectedthread收发数据 private class connectedthread extends thread { private final bluetoothsocket socket; private final inputstream inputstream; private final outputstream outputstream; public connectedthread(bluetoothsocket socket) { this.socket = socket; inputstream input = null; outputstream output = null; try { input = socket.getinputstream(); output = socket.getoutputstream(); } catch (ioexception e) { e.printstacktrace(); } this.inputstream = input; this.outputstream = output; } public void run() { stringbuilder recvtext = new stringbuilder(); byte[] buff = new byte[1024]; int bytes; bundle tmpbundle = new bundle(); message tmpmessage = new message(); tmpbundle.putstring("notice", "连接成功"); tmpmessage.what = notice_view; tmpmessage.setdata(tmpbundle); handler.sendmessage(tmpmessage); while (true) { try { bytes = inputstream.read(buff); string str = new string(buff, "iso-8859-1"); str = str.substring(0, bytes); // 收到数据,单片机发送上来的数据以"#"结束,这样手机知道一条数据发送结束 //log.e("read", str); if (!str.endswith("#")) { recvtext.append(str); continue; } recvtext.append(str.substring(0, str.length() - 1)); // 去除'#' bundle bundle = new bundle(); message message = new message(); bundle.putstring("recv", recvtext.tostring()); message.what = recv_view; message.setdata(bundle); handler.sendmessage(message); recvtext.replace(0, recvtext.length(), ""); } catch (ioexception e) { e.printstacktrace(); break; } } } public void write(byte[] bytes) { try { outputstream.write(bytes); } catch (ioexception e) { e.printstacktrace(); } } public void cancel() { try { socket.close(); } catch (ioexception e) { e.printstacktrace(); } } } }
menu_main.xml文件如下:
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" tools:context=".mainactivity"> <item android:id="@+id/show_devices" android:title="@string/show_devices" android:orderincategory="100" app:showasaction="never" /> <item android:id="@+id/start_bluetooth" android:title="@string/start_bluetooth" android:orderincategory="100" app:showasaction="never" /> <item android:id="@+id/find_devices" android:title="@string/find_devices" android:orderincategory="100" app:showasaction="never" /> <item android:id="@+id/connect_devices" android:title="@string/connect_devices" android:orderincategory="100" app:showasaction="never" /> </menu>
strings.xml文件如下:
<resources> <string name="app_name">bluetooth</string> <string name="action_settings">settings</string> <string name="start_bluetooth">开启蓝牙</string> <string name="show_devices">查询配对设备</string> <string name="find_devices">搜索设备</string> <string name="connect_devices">连接设备</string> </resources>
到这里整个app已经开发完成,亲测可用,如果有什么错误,欢迎评论指正谈论^_^。
到此,本文全部内容就给大家介绍完了,亲自测试过,代码安全可靠,放心实用,如果有任何问题欢迎给我留言,小编会及时回复的!
下一篇: java 实现最小二叉树堆排序的实例