Android通过蓝牙向Arduino发送字符串失败,请求代码排查
Hey there! Let's break down why your Android app can connect to the HC-05 but won't send strings successfully. I'll walk through the most common issues based on the code structure you shared, plus some critical checks you might have missed.
First, let's make sure your "Connect" button is setting up the socket correctly. HC-05 uses the Serial Port Profile (SPP), so you must use the standard SPP UUID: 00001101-0000-1000-8000-00805F9B34FB to create the socket. Also, never run connection logic on the main thread—it'll trigger a NetworkOnMainThreadException and leave you with a "fake" connected state.
Here's a correct connection implementation using a coroutine (or use AsyncTask if you're targeting older Android versions):
// Inside your Connect button click listener connectButton.setOnClickListener(v -> { if (device == null) { Toast.makeText(this, "No device selected", Toast.LENGTH_SHORT).show(); return; } // Run connection in background CoroutineScope(Dispatchers.IO).launch(() -> { try { UUID sppUuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); socket = device.createRfcommSocketToServiceRecord(sppUuid); socket.connect(); outputStream = socket.getOutputStream(); // Update UI on main thread runOnUiThread(() -> Toast.makeText(this, "Connected successfully", Toast.LENGTH_SHORT).show()); } catch (IOException e) { e.printStackTrace(); runOnUiThread(() -> Toast.makeText(this, "Connection failed: " + e.getMessage(), Toast.LENGTH_LONG).show()); } }); });
Most of the time, send failures happen because you're not adding a terminator character (like \n) or not flushing the output stream. Arduino typically waits for a newline to know when a string ends—without it, it'll hang waiting for more data.
Check your send button code against this correct implementation:
sendButton.setOnClickListener(v -> { if (socket == null || !socket.isConnected() || outputStream == null) { Toast.makeText(this, "Not connected to HC-05", Toast.LENGTH_SHORT).show(); return; } String inputText = editText.getText().toString().trim(); if (inputText.isEmpty()) { Toast.makeText(this, "Enter a string first", Toast.LENGTH_SHORT).show(); return; } // Add newline terminator for Arduino String command = inputText + "\n"; try { outputStream.write(command.getBytes()); outputStream.flush(); // Force all data to send immediately runOnUiThread(() -> Toast.makeText(this, "Sent: " + inputText, Toast.LENGTH_SHORT).show()); } catch (IOException e) { e.printStackTrace(); runOnUiThread(() -> Toast.makeText(this, "Send failed: " + e.getMessage(), Toast.LENGTH_LONG).show()); } });
Double-check that your command variable is actually getting populated with the EditText's content—if it's empty or unassigned, nothing will send.
Android 6.0+ requires dynamic permissions for Bluetooth operations, and Android 12+ split permissions into BLUETOOTH_SCAN and BLUETOOTH_CONNECT. If you skip these, your app might connect but not have permission to write to the socket.
First, add these permissions to your AndroidManifest.xml:
<uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- For Android 12+ --> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
Then, request these permissions dynamically before attempting to connect to the HC-05.
Even though you asked about Android code, a misconfigured Arduino can make it look like the app isn't sending data. Make sure:
- Your Arduino uses the correct baud rate (HC-05 defaults to 9600)
- You're reading strings with a terminator, like
Serial.readStringUntil('\n') - The HC-05's TX pin is connected to Arduino's RX pin, and vice versa
Example Arduino code for testing:
void setup() { Serial.begin(9600); // Match HC-05's baud rate } void loop() { if (Serial.available()) { String received = Serial.readStringUntil('\n'); Serial.println("Received from HC-05: " + received); } }
If you're connecting/disconnecting multiple times, failing to close the socket and output stream can leave resources hanging, causing future send attempts to fail. Add this to your Activity's lifecycle:
@Override protected void onDestroy() { super.onDestroy(); try { if (outputStream != null) outputStream.close(); if (socket != null) socket.close(); } catch (IOException e) { e.printStackTrace(); } }
内容的提问来源于stack exchange,提问作者Michael Schwingshackl




