2010-08-03 14 views
47

Obecnie pracuję nad aplikacją dla systemu Android, która łączy się z instrumentem za pośrednictwem Bluetooth i trzeba napisać polecenia tekstowe i otrzymywać odpowiedzi łańcuchowe z powrotem. Obecnie mam połączenie/odczyt/zapis działający dla TCP/IP przez Wi-Fi i próbuję teraz zaimplementować Bluetooth. Ale wpadam w pewne blokady na drodze. Szukałem w sieci próbując znaleźć przykłady czegoś podobnego i nie miałem szczęścia. Korzystam z przykładu zasobów dla programistów Androida: Mój główny punkt odniesienia to Czat przez Bluetooth.Wykrywanie usług zakończone niepowodzeniem za pomocą Bluetooth na Androidzie

Mój bieżący kod wydaje się działać. Następnie generuje wyjątek Service Discovery Failed w punkcie połączenia. Używam klasy DeviceListActivity do wykrywania i wybierania urządzenia, z którym chcę się połączyć. Zwraca anActivityResult, a następnie moja klasa Bluetooth czeka na to, aby obsłużyć to, a następnie łączy się z nim. Poniższy kod jest niemal identyczny z aplikacją czatu Bluetooth.

public void onActivityResult(int requestCode, int resultCode, Intent data) { 
    if(!m_BluetoothAdapter.isEnabled()) 
    { 
     m_BluetoothAdapter.enable(); 
    } 
    switch (requestCode) { 
     case REQUEST_CONNECT_DEVICE: 
      // When DeviceListActivity returns with a device to connect 
      if (resultCode == Activity.RESULT_OK) { 
       // Get the device MAC address 
       String address = data.getExtras() 
            .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS); 
       // Get the BLuetoothDevice object 
       BluetoothDevice device = m_BluetoothAdapter.getRemoteDevice(address); 
       // Attempt to connect to the device 
       connect(device); 
      } 
      break; 

     case REQUEST_ENABLE_BT: 
      // When the request to enable Bluetooth returns 
      if (resultCode == Activity.RESULT_OK) { 
       // Bluetooth is now enabled, so set up a chat session 
      } 
      else { 
       // User did not enable Bluetooth or an error occured 

       Toast.makeText(this, "Bluetooth not enabled", Toast.LENGTH_SHORT).show(); 
       finish(); 
      } 
    } 
} 

To jest moja funkcja connect:

private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); 

private void connect(BluetoothDevice device) { 
    m_Device = device; 
    BluetoothSocket tmp = null; 

    // Get a BluetoothSocket for a connection with the 
    // given BluetoothDevice 
    try { 
     tmp = device.createRfcommSocketToServiceRecord(MY_UUID); 
    } 
    catch (IOException e) { 

    } 
    m_Socket = tmp; 

    m_BluetoothAdapter.cancelDiscovery(); 

    try { 
     // This is a blocking call and will only return on a 
     // successful connection or an exception 
     m_Socket.connect(); 
    } 
    catch (IOException e) { 
     try { 
      m_Socket.close(); 
     } 
     catch (IOException e2) { 
     } 
     return; 
    } 
} 

Mamy nadzieję, że cokolwiek robię źle jest proste, ale obawiam się, że nigdy nie jest takie proste. To jest mój pierwszy raz, kiedy pracuję nad rozwojem technologii Bluetooth, i być może robię coś jawnie nie tak ... Ale nie jestem pewien, dlaczego otrzymałem wykrycie usługi, które nie powiodło się.

Możesz sparować/znaleźć urządzenie przez cały czas ręcznie na telefonie ... To wymaga hasła, ale nie sądzę, że to jest problem, który mam.

Odpowiedz

92

Po trzech dniach zostałem zorientowany dzięki kilku bardzo pomocnym postom.

musiałem wymienić:

tmp = device.createRfcommSocketToServiceRecord(MY_UUID); 

z:

Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class}); 
     tmp = (BluetoothSocket) m.invoke(device, 1); 

i voila to działa!

+1

czekaj, mam kilka aplikacji Bluetooth i ja nie znalazłem sytuacji, w której użycie odbicia (getclass.getmethod) jest konieczne. Czy możesz powiedzieć mi coś więcej na temat sprzętu, który wypróbowałeś? Bardzo interesuje mnie, czy w pewnych sytuacjach refleksja jest rzeczywiście konieczna. –

+0

Po kilku testach. Zauważyłem, że to właśnie telefon miał z tym problemy. HTC Incredible nie łączył się przy użyciu pierwszej metody, jednak Samsung Galaxy S i inny, nie pamiętam, który z nich nawiązał połączenie przy pierwszej próbie. – TxAg

+0

Byłem nękany tym wyjątkiem i to rozwiązanie wydawało się naprawić moje problemy. Czy rozumiesz, co się tutaj dzieje i dlaczego łagodzi problem niepowodzenia wyszukiwania usług? – GobiasKoffi

2

To była a suggested edit from an anonymous user próbująca odpowiedzieć na zaakceptowaną odpowiedź.

Jedną z dużych różnic między kodem przed i po jest przekazywany identyfikator UUID. Znalazłem moją odpowiedź tutaj: http://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#createRfcommSocketToServiceRecord(java.util.UUID)

musiałem wymienić:

tmp = device.createRfcommSocketToServiceRecord(MY_UUID); 

z:

private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); 
tmp = device.createRfcommSocketToServiceRecord(SPP_UUID); 

i voila to działa! Oryginalny kod jest przeznaczony dla aplikacji peer-to-peer na Androida. Nie ma sensu używać UUID aplikacji podczas łączenia się z prostym szeregowym urządzeniem bluetooth. To dlatego nie udaje się odkryć.

+0

A teraz [inny anonimowy użytkownik komentuje] (http://stackoverflow.com/suggested-edits/335727): Sugerowana edycja używa dokładnie tej samej metody co kod, który nie działa. Działający kod używa innej niepublicznej metody, która nie wymaga uuid. – Rup

+0

Wystąpił ten sam błąd, co powyżej, podczas próby napisania aplikacji Android, która łączy się ze skanerem Bluetooth. To rozwiązanie sprawdziło się u mnie. – zarazan

+0

To nonsens. – Monsignor

13

Jak API 15 można wykorzystać następujące metody:

Spróbuj wymienić swój UUID z wartości zwracanej getUuids() metody BluetoothDevice klasie. Co pracował dla mnie było coś takiego:

UUID uuid = bluetoothDevice.getUuids()[0].getUuid(); 
BluetoothSocket socket = bluetoothDevice.createRfcommSocketToServiceRecord(uuid); 

Powodem jest to, że działa to różne urządzenia obsługują różne UUID i coraz UUID urządzenia za pomocą getUuids jesteś wspieranie wszystkich funkcji i urządzeń.

Inną interesującą nową metodą (obsługiwaną od API 14) jest: BluetoothHealth.getConnectionState. Nie próbowałem go, ale wygląda obiecująco ...

1

Tak jak wspomniano powyżej, chodzi o to, że musisz użyć UUID, na który czeka serwer.

Jeśli łączysz się z urządzeniem Bluetooth, takim jak zestaw słuchawkowy lub mysz, musisz sprawdzić, na które UUID urządzenie nasłuchuje. Możesz zobaczyć takie identyfikatory UUID.

UUID[] uuids = bluetoothDevice.getUuids(); 

A jeśli chcesz wiedzieć, co te UUID znaczy zobaczyć this.

0

To jest naprawdę stary jedno pytanie, ale uważam, że za pomocą createInsecureRfcommSocketToServiceRecord() zamiast createRfcommSocketToServiceRecord() wraz z getUuids() wcześniej wspomniano rade dla mnie

UUID uuid = bluetoothDevice.getUuids()[0].getUuid(); 
BluetoothSocket socket = bluetoothDevice.createInsecureRfcommSocketToServiceRecord(uuid); 
Powiązane problemy