当前位置: 移动技术网 > IT编程>移动开发>Android > Android单片机与蓝牙模块通信实例代码

Android单片机与蓝牙模块通信实例代码

2019年07月24日  | 移动技术网IT编程  | 我要评论

米奇贝儿,a计划续集粤语,生菜岛

啦啦毕业了,毕业前要写毕业设计,需要写一个简单的蓝牙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已经开发完成,亲测可用,如果有什么错误,欢迎评论指正谈论^_^。

到此,本文全部内容就给大家介绍完了,亲自测试过,代码安全可靠,放心实用,如果有任何问题欢迎给我留言,小编会及时回复的!

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网