Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android單片機與藍牙模塊通信實例代碼

Android單片機與藍牙模塊通信實例代碼

編輯:關於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已經開發完成,親測可用,如果有什麼錯誤,歡迎評論指正談論^_^。

到此,本文全部內容就給大家介紹完了,親自測試過,代碼安全可靠,放心實用,如果有任何問題歡迎給我留言,小編會及時回復的!

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved