Android-ohjelma, jota teen
töissä toimii kaukosäätimenä erilaisille moottorinohjaimille.
Kaukosäädin toimii bluetoothilla. Androidin SDK:n mukana tulee hyvä
esimerkkiprojekti bluetoothin käyttämisestä, jonka pohjalta on
helppo aloittaa. Androidiin bluetooth muistuttaa mitä tahansa
verkkosockettia jolla on sisääntulo ja ulostulostreamit, joihin voi
kirjoittaa samanaikaisesti. Bluetooth toimikin testipuhelimellani
(2.1) suhteellisen pienen työn jälkeen moitteettomasti.
Viime viikolla testasin
laitteilla, joissa oli Androidin versiot 2.3 ja 4.0.1 ja näissä ei
ollut toivoakaan saada yhteyttä testilankkuun. Ongelmat johtuivat
vielä eri syistä molemmissa laitteissa. Pahinta oli että
toimimattomuus oli satunnaista, joten en ollut täysin varma onko
vika testilankussa vai puhelimessa.
Löysin muutaman Androidin
ratkaisemattoman bugiraportin, joissa viitattiin käsittelemiini
ongelmiin. Ratkaisuksi annettiin muutamia väliaikaisia
korjauskikkoja, mutta nämäkään eivät auttaneet tapauksessani.
Ongelmien lähteenä on
sokettiyhteyden muodostus, joka toimii blokkaavasti 2.1 versiossa,
mutta ei muissa testaamissani laitteissa.
Log.i(BT_TAG, "Connecting"); btSocket.connect(); Log.i(BT_TAG, "Connected");
2.1-versiossa suoritus pysähtyy connect()-kutsuun kunnes yhteys on luotu, mutta muissa versioissa yhteys luodaan, vaikka sitä todellisuudessa ei ole. Yhteys katkeaa vasta kun sokettiin yritetään kirjoittaa jotain.
Ratkaisuna tein ylimääräisen kättelyn varmistamaan, onko yhteys todella luotu. Heti kun input ja output streamit on luotu lähetän outputtiin kättelykomennon ja jos vastaus saadaan, siirrytään vasta silloin yhdistetyyn tilaan. Jos vastausta ei saada, onneksi Android osaa itse heittää poikkeuksen ja sulkea soketin.
Tässä ei sinänsä ole mitään erikoista, mutta tuntuu turhalta, koska käyttöjärjestelmän pitäisi hoitaa Bluetooth-protokollan mukaisen yhteyden luomisen. Varsin ikävää on, etteivät eri Android-versiot toimi luvatulla tavalla.
private class ConnectedThread extends Thread { private BluetoothSocket mmSocket; private InputStream mmInStream; private OutputStream mmOutStream; private boolean isAvailable = false; public ConnectedThread(BluetoothSocket socket) { Log.d(BT_TAG, "create ConnectedThread"); mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; // Get the BluetoothSocket input and output streams try { tmpIn = socket.getInputStream(); tmpOut = socket.getOutputStream(); } catch (IOException e) { Log.e(BT_TAG, "temp sockets not created", e); } mmInStream = tmpIn; mmOutStream = tmpOut; //Handshake write(HANDSHAKE); // sendSuccessfulConnectionBroadCast(); } public void run() { Log.i(BT_TAG, "BEGIN mConnectedThread"); byte[] buffer = new byte[Protocol.RESPONSE_LENGTH]; int i = 0; // Keep listening to the InputStream while connected while (true) { try { // Read from the InputStream // bytes = mmInStream.read(buffer); int readByte = mmInStream.read(); Log.i(BT_TAG, "Read: " + readByte); buffer[i] = (byte) readByte; i++; //Listen for the handshake confirmation if (i == Protocol.RESPONSE_LENGTH) { if (!isAvailable) { isAvailable = true; listenState = false; sendSuccessfulConnectionBroadCast(); i = 0; continue; } GlobalHandler .getHandler() .obtainMessage( GlobalHandler.MESSAGE_RESPONSE, buffer).sendToTarget(); Log.i(BT_TAG, "Read: " + buffer[0] + " " + buffer[1] + " " + buffer[2] + " " + buffer[3] + " " + buffer[4]); i = 0; listenState = false; } } catch (IOException e) { Log.e(BT_TAG, "Disconnected", e); break; } } }
Comments
Post a Comment