Üdv a digitális adatok izgalmas világában, ahol a bitek és bájtok szabadon repülnek a levegőben! 👋 Gondoltad valaha, hogy milyen menő lenne, ha az Android telefonod egy egyszerű számot, mondjuk egy hőmérsékletet vagy egy szenzor adatát elküldené egy másik eszközre, teljesen vezeték nélkül? Nos, ma pontosan erről fogunk beszélni: integer típusú adatok küldése Bluetooth-on keresztül Androidról. Készülj fel egy kalandos utazásra a kód, a bitek, és persze a Bluetooth hullámain! 🌊
De miért épp az integer? Miért nem valami bonyolultabb, mondjuk egy kép vagy egy videó? 🤔 Egyszerű a válasz: az integer a programozás alapköve. Egy egyszerű, de rendkívül sokoldalú adattípus, ami kiválóan alkalmas arra, hogy megértsük a vezeték nélküli adatátvitel mechanizmusát anélkül, hogy elvesznénk a bonyolult formátumok útvesztőjében. Ha egy integerrel megy, menni fog mással is, csak a csomagolás lesz más! Ráadásul a Bluetooth kiválóan alkalmas rövid távú, energiatakarékos kommunikációra, ami ideális szenzoradatok, vezérlőjelek vagy egyszerű numerikus információk továbbítására.
Az Előkészületek: Készüljünk Fel a Kalandra! ⚙️
Mielőtt fejest ugrunk a kódolásba, győződjünk meg róla, hogy minden készen áll. Nincs annál frusztrálóbb, mint amikor a projekt felénél derül ki, hogy valami hiányzik. 😊
1. Hardveres Háttér:
- Minimum két Android készülék: Az egyik lesz az „adó” (klienst), a másik a „vevő” (szerver). Vagy akár egy Android telefon és egy Bluetooth-képes mikrokontroller (pl. ESP32, Arduino Bluetooth modullal), de most maradjunk a két Androidos megoldásnál, mert az a legkézenfekvőbb.
- A Bluetooth modul mindkét eszközön legyen bekapcsolva és működjön! (Gondolom, ez evidens, de jobb a békesség! 😉)
2. Szoftveres Alapok:
- Android Studio: A fejlesztői környezet, ahol a varázslat történni fog. Győződj meg róla, hogy a legfrissebb stabil verzió van telepítve.
- Alapvető Java/Kotlin tudás: Bár igyekszem mindent érthetően elmagyarázni, némi programozási alapismeret sosem árt.
3. Az Android Manifest beállításai: A Jogosultságok Kérdése 🛡️
Az Android biztonsági okokból szigorúan kezeli a rendszererőforrásokhoz való hozzáférést. A Bluetooth használatához engedélyeket kell kérnünk az AndroidManifest.xml
fájlban. Fontos megjegyezni, hogy az Android 12 (API 31) óta új, finomabb szemcsés Bluetooth jogosultságok léptek életbe, amiket mindenképpen figyelembe kell vennünk:
<manifest ...>
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.INTERNET" /> <!-- Ha internetre is szükséged van -->
</manifest>
Miért van szükség ennyi jogosultságra? A BLUETOOTH
és BLUETOOTH_ADMIN
a régebbi API-khoz valók. Az Android 12-től bevezetett BLUETOOTH_SCAN
, BLUETOOTH_ADVERTISE
és BLUETOOTH_CONNECT
sokkal specifikusabbak: előbbi a készülékek felderítésére, középső a Bluetooth szolgáltatások hirdetésére, utóbbi pedig a meglévő eszközökhöz való csatlakozásra szolgál. A ACCESS_FINE_LOCATION
vagy ACCESS_COARSE_LOCATION
(helymeghatározás) pedig azért kellhet, mert a Bluetooth scannelésből következtetni lehet a felhasználó tartózkodási helyére. Igen, tudom, kissé túlbonyolítottnak tűnik, de ez van, ha a biztonság az első! 😂
Ezen felül futási időben (runtime) is ellenőriznünk és kérnünk kell az engedélyeket, különösen az Android 6.0 (Marshmallow) óta. Erre a ActivityCompat.requestPermissions()
metódus a legjobb megoldás.
A Bluetooth Lelke: Profilok és UUID-k ✨
Mielőtt továbbmegyünk, értsük meg a két kulcsfogalmat: Bluetooth profilok és UUID-k.
- Bluetooth Profilok: Ezek olyan specifikációk, amelyek meghatározzák, hogy az eszközök hogyan kommunikáljanak egymással egy adott feladat elvégzéséhez. Nekünk a legtöbb esetben a Serial Port Profile (SPP) lesz a barátunk. Ez a profil emulál egy soros portot, ami ideális egyszerű adatfolyamok, például bitek vagy stringek küldésére. Nagyon hasonlóan működik, mint a régi RS-232 soros kommunikáció, csak épp vezeték nélkül.
- UUID (Universally Unique Identifier): Ez egy 128 bites szám, ami egyedi azonosítót biztosít egy Bluetooth szolgáltatásnak. Amikor az egyik eszköz létrehoz egy szolgáltatást, és a másik csatlakozni akar hozzá, mindkettőnek ugyanazt az UUID-t kell használnia. Ez olyan, mint egy telefonszám a Bluetooth világában – ha nem tudod, nem tudsz hívni! Célszerű egy saját, egyedi UUID-t generálni, hogy ne ütközzünk más szolgáltatásokkal. Például:
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")
ez az SPP alapértelmezett UUID-je, de saját projektekhez jobb egy egyedit használni. Keress rá a „UUID generator” kulcsszóra, és máris van egy sajátod!
A Két Fél: Kliens és Szerver 🤝
A Bluetooth kommunikációhoz két szereplőre van szükség:
- Szerver (Server): Ez az az eszköz, amelyik „figyel” és várja a bejövő kapcsolatokat. Ő hozza létre a Bluetooth szolgáltatást (a „telefonszámot” – az UUID-t), és várja, hogy valaki felhívja.
- Kliens (Client): Ez az az eszköz, amelyik „kezdeményezi” a kapcsolatot. Ő keresi meg a szervert a Bluetooth eszközei között, majd megpróbál csatlakozni a szerver által meghirdetett szolgáltatáshoz (az UUID segítségével).
A mi esetünkben az egyik Android telefon lesz a szerver, a másik pedig a kliens.
A Szerver Oldal: Fogadásra Készen! 🎧
A szerver feladata, hogy létrehozzon egy BluetoothServerSocket
-et, ami folyamatosan figyelni fogja a bejövő kapcsolatokat. Amikor egy kliens megpróbál csatlakozni, a szerver elfogadja a kapcsolatot, és létrehoz egy BluetoothSocket
-et a tényleges adatátvitelhez.
// Valahol az Activityben vagy egy dedikált BluetoothService-ben
private val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter()
private var serverThread: AcceptThread? = null
private val MY_UUID: UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB") // Ezt cseréld le a sajátodra!
private val MY_APP_NAME = "MyIntegerReceiver"
fun startBluetoothServer() {
if (bluetoothAdapter == null) {
// Nincs Bluetooth támogatás
Log.e("Bluetooth", "Ezen az eszközön nincs Bluetooth támogatás.")
return
}
// Ellenőrizzük a Bluetooth engedélyt (Android 12+)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S &&
!bluetoothAdapter.isEnabled ||
ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
// Kérd a BLUETOOTH_CONNECT engedélyt, ha nincs
requestPermissions(arrayOf(Manifest.permission.BLUETOOTH_CONNECT), REQUEST_BLUETOOTH_CONNECT)
return
}
if (!bluetoothAdapter.isEnabled) {
val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT)
return
}
serverThread = AcceptThread()
serverThread?.start()
Log.d("BluetoothServer", "Bluetooth szerver elindult, várakozás kapcsolatra...")
}
private inner class AcceptThread : Thread() {
private val mmServerSocket: BluetoothServerSocket? by lazy(LazyThreadSafetyMode.NONE) {
try {
bluetoothAdapter?.listenUsingRfcommWithServiceRecord(MY_APP_NAME, MY_UUID)
} catch (e: SecurityException) {
Log.e("BluetoothServer", "Biztonsági hiba a szerver socket létrehozásakor", e)
null
} catch (e: IOException) {
Log.e("BluetoothServer", "Hiba a szerver socket létrehozásakor", e)
null
}
}
override fun run() {
var socket: BluetoothSocket? = null
// Folyamatosan figyeljük a bejövő kapcsolatokat, amíg hiba nem lép fel, vagy a szálat nem szakítjuk meg
while (true) {
try {
// Ez egy blokkoló hívás, visszatér, ha egy kapcsolatot elfogadtak
Log.d("BluetoothServer", "Várakozás kliens kapcsolatra...")
socket = mmServerSocket?.accept()
} catch (e: IOException) {
Log.e("BluetoothServer", "A szerver socket accept() metódusa sikertelen", e)
break // Kilépés a ciklusból hiba esetén
} catch (e: SecurityException) {
Log.e("BluetoothServer", "Engedélyezési hiba az accept() hívásakor", e)
break
}
socket?.let {
// Egy kapcsolatot elfogadtunk. Kezeljük az adatátvitelt egy új szálon.
Log.d("BluetoothServer", "Kapcsolat elfogadva klienssel: ${it.remoteDevice.name}")
manageConnectedSocket(it)
mmServerSocket?.close() // Egy kapcsolat után lezárjuk a szerver socket-et, ha csak egy kliens kell.
// Ha több kliens kell, ne zárjuk be itt, hanem kezeljük a kapcsolatokat listában.
break // Kilépés a ciklusból, ha már van kapcsolat
}
}
}
fun cancel() {
try {
mmServerSocket?.close()
Log.d("BluetoothServer", "Szerver socket lezárva.")
} catch (e: IOException) {
Log.e("BluetoothServer", "Nem sikerült lezárni a szerver socket-et", e)
}
}
}
A manageConnectedSocket(socket: BluetoothSocket)
metódus a lényeg. Ebben a függvényben fogjuk kezelni a bejövő és kimenő adatfolyamokat. Mivel a BluetoothSocket
adatfolyamai blokkolóak (azaz várnak az adatra, mielőtt továbblépnének), ezt mindenképpen egy külön szálon kell kezelni, különben lefagyna az alkalmazásod felhasználói felülete! 🥶
A Kliens Oldal: Kapcsolódjunk és Küldjünk! 🚀
A kliens feladata, hogy megkeresse a kívánt Bluetooth eszközt, majd csatlakozzon annak szolgáltatásához. Ehhez először is fel kell derítenie a környező Bluetooth eszközöket.
// Valahol az Activityben vagy egy dedikált BluetoothService-ben
private var clientThread: ConnectThread? = null
private val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter()
private val MY_UUID: UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB") // Ugyanaz, mint a szerveren!
// Az eszköz felfedezéséhez szükség van BroadcastReceiverre
private val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
when(intent.action) {
BluetoothDevice.ACTION_FOUND -> {
val device: BluetoothDevice? = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
device?.let {
// Megtaláltunk egy eszközt. Ezt megjeleníthetjük egy listában.
Log.d("BluetoothClient", "Eszköz megtalálva: ${it.name} - ${it.address}")
// Ha ez a mi szerverünk, csatlakozzunk hozzá!
if (it.name == "A_SZERVER_ESZKOZ_NEVE") { // Cseréld le a szerver eszköz nevére
bluetoothAdapter?.cancelDiscovery() // Leállítjuk a felderítést, ha megtaláltuk
connectToServer(it)
}
}
}
BluetoothAdapter.ACTION_DISCOVERY_FINISHED -> {
Log.d("BluetoothClient", "Eszköz felderítés befejeződött.")
}
}
}
}
fun startDiscoveryAndConnect() {
if (bluetoothAdapter == null) {
Log.e("Bluetooth", "Ezen az eszközön nincs Bluetooth támogatás.")
return
}
// Engedélyek ellenőrzése és kérése (Android 12+)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(arrayOf(Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT), REQUEST_BLUETOOTH_PERMISSIONS)
return
}
} else { // Régebbi Android verziókhoz
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), REQUEST_LOCATION_PERMISSION)
return
}
}
if (!bluetoothAdapter.isEnabled) {
val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT)
return
}
val filter = IntentFilter(BluetoothDevice.ACTION_FOUND)
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)
registerReceiver(receiver, filter)
bluetoothAdapter.startDiscovery()
Log.d("BluetoothClient", "Eszköz felderítés elindult...")
}
fun connectToServer(device: BluetoothDevice) {
clientThread = ConnectThread(device)
clientThread?.start()
}
private inner class ConnectThread(device: BluetoothDevice) : Thread() {
private val mmSocket: BluetoothSocket? by lazy(LazyThreadSafetyMode.NONE) {
try {
device.createRfcommSocketToServiceRecord(MY_UUID)
} catch (e: SecurityException) {
Log.e("BluetoothClient", "Biztonsági hiba a kliens socket létrehozásakor", e)
null
} catch (e: IOException) {
Log.e("BluetoothClient", "Hiba a kliens socket létrehozásakor", e)
null
}
}
override fun run() {
bluetoothAdapter?.cancelDiscovery() // Felderítést leállítjuk, ha már kapcsolódunk
mmSocket?.let { socket ->
try {
// Csatlakozás a szerverhez. Ez egy blokkoló hívás.
Log.d("BluetoothClient", "Csatlakozás a szerverhez...")
socket.connect()
Log.d("BluetoothClient", "Sikeresen csatlakozva a szerverhez!")
manageConnectedSocket(socket) // Adatküldés/fogadás kezelése
} catch (e: IOException) {
Log.e("BluetoothClient", "Nem sikerült csatlakozni a szerverhez: ${e.message}", e)
try {
socket.close()
} catch (e2: IOException) {
Log.e("BluetoothClient", "Nem sikerült lezárni a kliens socket-et csatlakozási hiba után", e2)
}
} catch (e: SecurityException) {
Log.e("BluetoothClient", "Engedélyezési hiba a csatlakozás során", e)
}
}
}
fun cancel() {
try {
mmSocket?.close()
Log.d("BluetoothClient", "Kliens socket lezárva.")
} catch (e: IOException) {
Log.e("BluetoothClient", "Nem sikerült lezárni a kliens socket-et", e)
}
}
}
Itt is a manageConnectedSocket(socket: BluetoothSocket)
metódus lesz a kulcs, ahogy a szerver oldalon is. Ezt egy közös osztályba is ki lehet szervezni, ami mindkét oldalon képes kezelni az adatfolyamokat.
Adatok Adása-Fogadása: Az Integer Vándorlása 🔢
Most jön a lényeg: hogyan alakítunk át egy integert bájttá és vissza? A Bluetooth socket-en keresztül csak bájtfolyamokat tudunk küldeni és fogadni. Egy Java/Kotlin integer (Int
) 32 bit (4 bájt) hosszú. Ezt kell megfelelően bájtokká alakítani.
// A manageConnectedSocket függvény része, ami egy külön szálon fut
private inner class ConnectedThread(private val mmSocket: BluetoothSocket) : Thread() {
private val mmInStream: InputStream = mmSocket.inputStream
private val mmOutStream: OutputStream = mmSocket.outputStream
private val buffer: ByteArray = ByteArray(1024) // puffer a bejövő adatoknak
override fun run() {
var bytes: Int // Bájtok száma olvasáskor
Log.d("ConnectedThread", "Adatfogadó szál elindult.")
// Folyamatosan hallgatjuk az InputStream-et
while (true) {
try {
// Beolvasunk a bejövő stream-ből. Ez egy blokkoló hívás.
bytes = mmInStream.read(buffer)
if (bytes > 0) {
// Itt kell az integert visszafejteni a bájtokból
if (bytes >= 4) { // Minimum 4 bájt kell egy integernek
val receivedInt = ByteBuffer.wrap(buffer, 0, 4).order(ByteOrder.LITTLE_ENDIAN).getInt()
Log.d("ConnectedThread", "Fogadott integer: $receivedInt")
// Itt frissíthetjük a UI-t pl. egy Handler segítségével
// uiHandler.obtainMessage(MESSAGE_READ, receivedInt).sendToTarget()
} else {
Log.w("ConnectedThread", "Nem elegendő bájt érkezett az integerhez. Bytes: $bytes")
}
}
} catch (e: IOException) {
Log.e("ConnectedThread", "A bemeneti stream megszakadt: ${e.message}", e)
// Kezeld a megszakadt kapcsolatot (pl. értesítsd a UI-t, próbálj újra csatlakozni)
break
}
}
}
// Integer küldése a távoli eszközre
fun write(number: Int) {
try {
// Integer átalakítása 4 bájtos ByteArray-vé
val byteArray = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(number).array()
mmOutStream.write(byteArray)
mmOutStream.flush() // Fontos a buffer ürítése!
Log.d("ConnectedThread", "Elküldött integer: $number")
} catch (e: IOException) {
Log.e("ConnectedThread", "Hiba az integer küldésekor: ${e.message}", e)
// Kezeld a hibát (pl. a kapcsolat megszakadt)
}
}
// Kapcsolat lezárása
fun cancel() {
try {
mmSocket.close()
Log.d("ConnectedThread", "Kapcsolat lezárva.")
} catch (e: IOException) {
Log.e("ConnectedThread", "Nem sikerült lezárni a connected socket-et", e)
}
}
}
// Példa a használatra az Activityben a kliens oldalról:
// val myIntegerToSend = 42
// connectedThread?.write(myIntegerToSend)
Néhány fontos megjegyzés:
ByteBuffer
ésByteOrder
: Ez a legjobb módszer az int byte[] átalakításra. Fontos aByteOrder
(bájtsorrend) beállítása. Leggyakrabban aLITTLE_ENDIAN
vagyBIG_ENDIAN
használatos. Győződj meg róla, hogy mindkét eszközön (küldőn és fogadón is) ugyanazt a bájtsorrendet használod, különben káosz lesz az értelmezésben! Képzeld el, hogy „1234”-et mondasz valakinek, de ő „4321”-nek érti! 😂flush()
: AzOutputStream.flush()
nagyon fontos! Ez kényszeríti a pufferek ürítését, vagyis azonnal elküldi az adatokat, ahelyett, hogy megvárná, amíg a puffer megtelik.- UI frissítés: Soha ne frissítsd a felhasználói felületet (UI) közvetlenül egy háttérszálból! Használj
Handler
-t,LiveData
-t,Coroutines
-t vagy más UI-barát mechanizmust az adatok fő szálra való továbbításához.
Hibakezelés és Jó Gyakorlatok 💪
A Bluetooth kommunikáció néha trükkös lehet. Íme néhány tipp és gondolat:
try-catch-finally
blokkok: Használd őket nagylelkűen! AzIOException
-ok gyakoriak, különösen, ha a kapcsolat megszakad, vagy az eszköz hatótávolságon kívül kerül.- Források lezárása: Mindig zárd be a
BluetoothSocket
-eket és azInputStream
/OutputStream
-eket, amikor már nincs rájuk szükség, vagy ha hiba lép fel. Afinally
blokk erre tökéletes. Ez megakadályozza az erőforrásszivárgást és a lehetséges összeomlásokat. - Szálkezelés: Minden hálózati műveletet külön háttérszálon végezz! A
Thread
osztály a legegyszerűbb, de komolyabb appokhoz érdemes megfontolni a Kotlin Coroutines-t vagy azExecutorService
-t. - Felhasználói visszajelzés: Mindig tájékoztasd a felhasználót, mi történik: „Bluetooth bekapcsolva”, „Eszköz felderítés…”, „Csatlakozva”, „Hiba történt”. Egy jó felhasználói felület aranyat ér. ✨
- Eszköz felfedezhetőség: Ne felejtsd el, hogy a szerver eszköznek felfedezhetőnek kell lennie ahhoz, hogy a kliens megtalálja! Ezt programból is be lehet állítani (
BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE
), de felhasználói beavatkozást igényel. - Párosítás (Pairing): A fenti példák feltételezik, hogy az eszközök már párosítva vannak, vagy automatikusan párosodnak. Ha nem, akkor a
BluetoothDevice.createBond()
metódussal lehet kezdeményezni a párosítást, de ez felhasználói megerősítést igényelhet.
Mire Jó Mindez? A Hasznos Alkalmazások Világa 💡
Miért érdemes ennyi energiát fektetni ebbe az egészbe? Nos, az integer típusú adatok Bluetooth-on keresztüli küldése rengeteg ajtót nyithat meg:
- IoT projektek: Képzeld el, hogy a házadban lévő hőmérséklet-érzékelő (pl. egy Arduino vagy ESP32) elküldi a hőmérséklet adatát a telefonodra, amit egy Android app jelenít meg! Vagy éppen Te küldesz egy „bekapcsolás” parancsot (mondjuk egy 1-es integert) a telefonodról, ami felkapcsolja a lámpát. 💡
- Robokontroll: Egy kis robot vezérlése a telefonról. Az előre-hátra, balra-jobbra parancsok mind kódolhatók integerekkel.
- Egyszerű chat alkalmazások: Karakterenként vagy üzenetenként küldheted az adatokat, és a kliens dekódolhatja őket. (Bár ehhez a stringek praktikusabbak, de az integer is egy alapja lehet.)
- Szenzoradatok gyűjtése: Egy okosóra vagy egy orvosi eszköz Bluetooth-on keresztül küldhet életjeleket, lépésszámot vagy pulzusszámot egy központi Android alkalmazásnak.
- Játékvezérlő: Egy Android telefon is lehet a Bluetooth alapú játékvezérlő, ami numerikus parancsokat küld egy másik eszköznek.
A lehetőségek szinte végtelenek, a képzelet szab határt! 😊
Személyes Vélemény és Záró Gondolatok 🥳
Bluetooth-on programozni Androidon… hát, bevallom őszintén, eleinte néha olyan érzésem volt, mintha egy sötét szobában keresgélném a fekete macskát, ami nincs is ott! 😅 Az engedélyek, a szálkezelés, a UUID
-k, a különböző Android verziók közötti eltérések – mindezek tudnak fejfájást okozni. De éppen ez a kihívás teszi olyan izgalmassá! Amikor végre létrejön a kapcsolat, és az első integer átugrik a levegőben, az a pillanat… az egyszerűen elmondhatatlan! Az a sikerélmény, amikor a „42” megjelenik a másik telefon kijelzőjén, az valami fantasztikus! 😎
Szerintem a Bluetooth ma is releváns technológia, különösen az IoT (Tárgyak Internete) területén. Nem kell mindig Wi-Fi-t vagy mobilhálózatot használni, ha egy rövid távolságú, kis energiafogyasztású kommunikáció is megteszi. És az a tény, hogy az integer típusú adatok küldése Bluetooth-on keresztül viszonylag egyszerűen megoldható Androidon, egy nagyszerű kiindulópontot jelent a komolyabb vezeték nélküli projektekhez.
Szóval, hajrá! Ne félj kísérletezni, változtatni, hibázni és újrapróbálni. Ez a programozás igazi szépsége! Remélem, ez az útmutató segített abban, hogy elindulj ezen a kalandos úton. Boldog kódolást és sikeres vezeték nélküli adatátvitelt kívánok! Legyen veled az erő… és a stabil Bluetooth kapcsolat! 😉