Devo trasmettere alcuni dati dalla mia app Android tramite Bluetooth (ad Arduino). Non sto leggendo/ricevendo nulla da Arduino. Per le mie esigenze single threaded, sono andato con un IntentService. Dopo l'accoppiamento, il mio codice funziona correttamente la prima volta che mi collego e inviamo i dati. Mi disconnetto dopo aver inviato dati senza errori. Ma quando provo a collegare la seconda volta in poi, ottengo il seguente errore quando provo myBluetoothSocket.connect():Problemi di connessione Bluetooth con IntentService
lettura non è riuscita, presa potrebbe chiusa o timeout, leggi ret: -1
L'unica soluzione è spegnere il dispositivo Arduino e riconnettersi (non è d'aiuto se faccio forza per fermare l'app e provare a ricollegarla).
Si noti che tutto funziona correttamente se si generano 2 thread (uno per leggere e scrivere ciascuno) indipendentemente dal numero di volte in cui mi collego e inviamo dati (provando quindi che non c'è nulla di sbagliato sul lato Arduino, "trattenere" un vecchio connessione).
Ecco il mio codice Android:
import android.app.IntentService;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.content.Context;
import android.os.Build;
import android.os.ParcelUuid;
import android.widget.Toast;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.UUID;
public class DataTransmissionService extends IntentService {
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private static final String TAG = "DataTransmissionService";
private BluetoothAdapter btAdapter = null;
private BluetoothSocket btSocket = null;
private OutputStream outStream = null;
private BluetoothDevice device = null;
public DataTransmissionService() {
super("DataTransmissionService");
}
@Override
protected void onHandleIntent(Intent intent) {
cleanup();
if (intent != null){
btAdapter = BluetoothAdapter.getDefaultAdapter();
pairedDeviceAddress = "already_paired_device_mac_addr";
try {
log.d(TAG, pairedDeviceAddress);
device = btAdapter.getRemoteDevice(pairedDeviceAddress);
log.d(TAG, "Device bond state : " + device.getBondState());
} catch (Exception e) {
log.e(TAG, "Invalid address: " + e.getMessage());
return;
}
try {
btSocket = createBluetoothSocket(device);
} catch (IOException e) {
log.e(TAG, "Socket creation failed: " + e.getMessage());
return;
}
try {
if (!btSocket.isConnected()) {
btSocket.connect();
log.d(TAG, "Connected");
} else {
log.d(TAG, "Already Connected"); //flow never reaches here for any use case
}
} catch (IOException e) {
log.e(TAG, "btSocket.connect() failed : " + e.getMessage());
return;
}
try {
outStream = btSocket.getOutputStream();
} catch (IOException e) {
log.e(TAG, "Failed to get output stream:" + e.getMessage());
return;
}
sendData("test");
//cleanup(); called in onDestroy()
}
}
@Override
public void onDestroy(){
cleanup();
//notify ui
super.onDestroy();
}
private void cleanup(){
try {
if (outStream != null) {
outStream.close();
outStream = null;
}
} catch (Exception e) {
log.e(TAG, "Failed to close output stream : " + e.getMessage());
}
try {
if (btSocket != null) {
btSocket.close();
btSocket = null;
}
}catch (Exception e) {
log.e(TAG, "Failed to close connection : " + e.getMessage());
}
}
private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
/*if(Build.VERSION.SDK_INT >= 10){
try {
final Method m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", new Class[] { UUID.class });
return (BluetoothSocket) m.invoke(device, MY_UUID);
} catch (Exception e) {
log.e(TAG, "Could not create Insecure RFComm Connection",e);
}
}*/
return device.createRfcommSocketToServiceRecord(MY_UUID);
}
private void sendData(String message) {
byte[] msgBuffer = message.getBytes();
log.d(TAG, "Sending : " + message);
try {
outStream.write(msgBuffer);
} catch (IOException e) {
log.e(TAG, "failed to write " + message);
}
}
}
Ho testato su Nexus 5 e dispositivi Samsung S5 (in esecuzione 5.1 e 5.0, rispettivamente).
ho la sensazione vostro problema risiede nell'uso di un 'IntentService' piuttosto che un normale' Service' e/o personalizzati 'Discussione '. Dal documento 'IntentService': * il servizio viene avviato secondo necessità, gestisce ogni Intent a sua volta utilizzando un thread di lavoro e si arresta automaticamente quando termina il lavoro. * Questo potrebbe causare il caos se si sta tentando di mantenere un BT connessione attraverso intenti. – pathfinderelite
Questo è esattamente ciò di cui ho bisogno. Connetti, invia dati e termina la connessione. La prossima connessione probabilmente accadrà dopo molto tempo, generando un nuovo servizio. Mantenere le discussioni sembra complicato per un semplice caso d'uso come questo. Ciò garantisce anche il trattamento automatico di un dispositivo alla volta (parte del mio caso d'uso). – SlowAndSteady
Quello che dici di Arduino non "trattiene" la connessione sembra ragionevole, ma il fatto che tu debba spegnere e riaccendere l'Arduino per potermi connettere di nuovo mi fa meravigliare. Forse l'Arduino va in qualche modo in uno stato diverso se leggi e scrivi sullo stesso thread? (Lo so, sembra strano). Cosa succede se ti connetti ad Arduino con un telefono, disconnetti, quindi prova a connetterti con il secondo telefono? Inoltre, hai modo di vedere lo stato del modem bluetooth di Arduino, per vedere se è in qualche modo diverso dopo averlo disconnesso la prima volta, rispetto a prima? – hBrent