Untuk membuat koneksi antara dua perangkat, Anda harus mengimplementasikan kedua metode
mekanisme sisi server dan sisi klien
karena satu perangkat harus membuka server
dan satu lagi harus memulai koneksi menggunakan
Alamat MAC. Perangkat server dan perangkat klien masing-masing mendapatkan
BluetoothSocket
dalam
cara. Server menerima informasi soket
ketika koneksi masuk
diterima. Klien memberikan informasi soket saat membuka saluran RFCOMM
ke server.
Server dan klien dianggap terhubung
satu sama lain ketika mereka masing-masing memiliki
BluetoothSocket
yang terhubung di saluran RFCOMM yang sama. Pada tahap ini, masing-masing
perangkat dapat memperoleh aliran input dan {i>output<i}, dan transfer data dapat dimulai, yang
akan dibahas di bagian tentang mentransfer Bluetooth
data Anda. Bagian ini
menjelaskan cara memulai koneksi antara dua perangkat.
Pastikan Anda memiliki Izin Bluetooth dan menyiapkan aplikasi Anda untuk Bluetooth sebelum mencoba menemukan perangkat Bluetooth.
Teknik koneksi
Salah satu teknik implementasinya adalah dengan secara otomatis mempersiapkan setiap perangkat sebagai server sehingga setiap perangkat memiliki soket server yang terbuka dan mendengarkan koneksi. Di beberapa dalam hal ini, salah satu perangkat dapat memulai koneksi satu sama lain dan menjadi dengan klien besar. Atau, satu perangkat dapat secara eksplisit menghosting koneksi dan membuka soket server sesuai permintaan, dan perangkat lainnya memulai koneksi.
Gambar 1. Dialog penyambungan Bluetooth.
Menghubungkan sebagai server
Bila Anda ingin menghubungkan dua perangkat, salah satunya
harus bertindak sebagai server dengan memegang
{i>open<i}
BluetoothServerSocket
Tujuan dari soket server adalah untuk
mendengarkan permintaan koneksi yang masuk
dan memberikan BluetoothSocket
yang terhubung setelah permintaan diterima. Jika
BluetoothSocket
diperoleh dari BluetoothServerSocket
, yaitu
BluetoothServerSocket
dapat—dan harus—dihapus, kecuali jika Anda ingin
perangkat untuk menerima lebih banyak koneksi.
Untuk menyiapkan soket server dan menerima koneksi, selesaikan langkah-langkah berikut urutan langkah:
Dapatkan
BluetoothServerSocket
dengan memanggillistenUsingRfcommWithServiceRecord(String, UUID)
.String ini adalah nama layanan yang dapat diidentifikasi, yang kemudian secara otomatis menulis ke entri database Service Discovery Protocol (SDP) baru di perangkat. Nama ini bersifat tidak tentu dan dapat berupa nama aplikasi. ID Unik Universal (UUID) juga disertakan dalam entri SDP dan membentuk dasar untuk perjanjian koneksi dengan perangkat klien. Bahwa adalah, ketika klien mencoba terhubung dengan perangkat ini, ia menggunakan UUID yang secara unik mengidentifikasi layanan yang ingin terhubung dengannya. Ini UUID harus cocok agar koneksi dapat diterima.
UUID adalah format 128-bit standar untuk ID {i>string<i} yang digunakan untuk mengidentifikasi informasi. UUID digunakan untuk mengidentifikasi informasi yang perlu unik di dalam sistem atau jaringan karena probabilitas UUID yang berulang adalah nol. Kode ini dibuat secara independen, tanpa menggunakan otoritas terpusat. Dalam hal ini, ID digunakan untuk mengidentifikasi layanan Bluetooth aplikasi. Untuk mendapatkan UUID untuk digunakan dengan aplikasi, Anda dapat menggunakan salah satunya dari sekian banyak
UUID
generator di web, lalu inisialisasi UUID denganfromString(String)
.Mulai memproses permintaan koneksi dengan memanggil
accept()
Ini adalah panggilan pemblokir. Server kembali ketika salah satu koneksi telah diterima atau terjadi pengecualian. Koneksi hanya diterima ketika perangkat jarak jauh telah mengirim permintaan koneksi berisi UUID yang cocok yang terdaftar dengan soket server yang mendengarkannya ini. Jika berhasil,
accept()
menampilkanBluetoothSocket
yang terhubung.Kecuali Anda ingin menerima koneksi tambahan, panggil
close()
Panggilan metode ini melepaskan soket server dan semua sumber dayanya, tetapi tidak menutup
BluetoothSocket
yang terhubung yang ditampilkan olehaccept()
. Tidak seperti TCP/IP, RFCOMM hanya mengizinkan satu klien yang terhubung setiap saluran pada satu waktu, jadi dalam sebagian besar kasus, akan lebih masuk akal untuk memanggilclose()
diBluetoothServerSocket
segera setelah menerima soket yang terhubung.
Karena panggilan accept()
merupakan panggilan pemblokir, jangan jalankan di bagian utama
thread UI aktivitas. Mengeksekusinya di thread lain memastikan bahwa aplikasi Anda dapat
masih menanggapi interaksi pengguna lain. Melakukan semua pekerjaan biasanya masuk akal
yang melibatkan BluetoothServerSocket
atau BluetoothSocket
di thread baru
dikelola oleh aplikasi Anda. Untuk membatalkan panggilan yang diblokir seperti accept()
, panggil close()
di BluetoothServerSocket
atau BluetoothSocket
dari thread lain. Catatan
bahwa semua metode pada BluetoothServerSocket
atau BluetoothSocket
yang aman untuk thread.
Contoh
Berikut ini adalah thread yang disederhanakan untuk komponen server yang menerima koneksi masuk:
Kotlin
private inner class AcceptThread : Thread() { private val mmServerSocket: BluetoothServerSocket? by lazy(LazyThreadSafetyMode.NONE) { bluetoothAdapter?.listenUsingInsecureRfcommWithServiceRecord(NAME, MY_UUID) } override fun run() { // Keep listening until exception occurs or a socket is returned. var shouldLoop = true while (shouldLoop) { val socket: BluetoothSocket? = try { mmServerSocket?.accept() } catch (e: IOException) { Log.e(TAG, "Socket's accept() method failed", e) shouldLoop = false null } socket?.also { manageMyConnectedSocket(it) mmServerSocket?.close() shouldLoop = false } } } // Closes the connect socket and causes the thread to finish. fun cancel() { try { mmServerSocket?.close() } catch (e: IOException) { Log.e(TAG, "Could not close the connect socket", e) } } }
Java
private class AcceptThread extends Thread { private final BluetoothServerSocket mmServerSocket; public AcceptThread() { // Use a temporary object that is later assigned to mmServerSocket // because mmServerSocket is final. BluetoothServerSocket tmp = null; try { // MY_UUID is the app's UUID string, also used by the client code. tmp = bluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID); } catch (IOException e) { Log.e(TAG, "Socket's listen() method failed", e); } mmServerSocket = tmp; } public void run() { BluetoothSocket socket = null; // Keep listening until exception occurs or a socket is returned. while (true) { try { socket = mmServerSocket.accept(); } catch (IOException e) { Log.e(TAG, "Socket's accept() method failed", e); break; } if (socket != null) { // A connection was accepted. Perform work associated with // the connection in a separate thread. manageMyConnectedSocket(socket); mmServerSocket.close(); break; } } } // Closes the connect socket and causes the thread to finish. public void cancel() { try { mmServerSocket.close(); } catch (IOException e) { Log.e(TAG, "Could not close the connect socket", e); } } }
Dalam contoh ini, hanya satu koneksi masuk yang diinginkan, jadi segera setelah
koneksi diterima dan BluetoothSocket
didapatkan, aplikasi akan meneruskan
memperoleh BluetoothSocket
ke thread terpisah, menutup
BluetoothServerSocket
, dan keluar dari loop.
Perlu diketahui bahwa saat accept()
menampilkan BluetoothSocket
, soket sudah
terhubung. Oleh karena itu, Anda
tidak boleh memanggil
connect()
, seperti yang Anda lakukan
dari sisi klien.
Metode manageMyConnectedSocket()
khusus aplikasi didesain untuk memulai
untuk mentransfer data, yang akan dibahas dalam topik tentang
mentransfer Bluetooth
data.
Biasanya, Anda harus menutup BluetoothServerSocket
begitu Anda selesai
mendeteksi koneksi masuk. Dalam contoh ini, close()
segera dipanggil
setelah BluetoothSocket
diperoleh. Anda mungkin juga ingin menyediakan
di thread Anda yang dapat menutup BluetoothSocket
pribadi dalam peristiwa
Anda perlu berhenti mendengarkan
pada soket server itu.
Menghubungkan sebagai klien
Untuk memulai koneksi dengan perangkat jarak jauh yang menerima
pada soket server terbuka, Anda harus terlebih dahulu mendapatkan BluetoothDevice
yang mewakili perangkat jarak jauh. Untuk mempelajari cara membuat
BluetoothDevice
, lihat Menemukan Bluetooth
perangkat Anda. Anda harus
lalu gunakan BluetoothDevice
untuk mendapatkan BluetoothSocket
dan memulai
koneksi jarak jauh.
Prosedur dasarnya sebagai berikut:
Menggunakan
BluetoothDevice
, dapatkanBluetoothSocket
dengan memanggilcreateRfcommSocketToServiceRecord(UUID)
Metode ini melakukan inisialisasi objek
BluetoothSocket
yang memungkinkan klien untuk hubungkan keBluetoothDevice
. UUID yang diteruskan di sini harus cocok dengan UUID yang digunakan oleh perangkat server ketika memanggillistenUsingRfcommWithServiceRecord(String, UUID)
untuk membukaBluetoothServerSocket
-nya. Untuk menggunakan UUID yang sesuai, lakukan hard code pada string UUID ke aplikasi Anda, lalu referensikan dari kedua server dan kode klien.Mulai koneksi dengan memanggil
connect()
. Perhatikan bahwa metode ini adalah memblokir panggilan.Setelah klien memanggil metode ini, sistem melakukan pencarian SDP untuk menemukan perangkat jarak jauh dengan UUID yang sesuai. Jika pencarian berhasil dan perangkat jarak jauh menerima koneksi, perangkat tersebut berbagi saluran RFCOMM untuk digunakan selama koneksi, dan metode
connect()
akan ditampilkan. Jika koneksi gagal, atau jika waktu metodeconnect()
habis (setelah sekitar 12 detik), maka metode ini akan menampilkanIOException
.
Karena connect()
merupakan panggilan pemblokir, Anda harus selalu melakukan tindakan ini
prosedur koneksi dalam thread yang terpisah dari aktivitas utama (UI)
.
Contoh
Berikut adalah contoh dasar dari thread klien yang memulai Bluetooth koneksi:
Kotlin
private inner class ConnectThread(device: BluetoothDevice) : Thread() { private val mmSocket: BluetoothSocket? by lazy(LazyThreadSafetyMode.NONE) { device.createRfcommSocketToServiceRecord(MY_UUID) } public override fun run() { // Cancel discovery because it otherwise slows down the connection. bluetoothAdapter?.cancelDiscovery() mmSocket?.let { socket -> // Connect to the remote device through the socket. This call blocks // until it succeeds or throws an exception. socket.connect() // The connection attempt succeeded. Perform work associated with // the connection in a separate thread. manageMyConnectedSocket(socket) } } // Closes the client socket and causes the thread to finish. fun cancel() { try { mmSocket?.close() } catch (e: IOException) { Log.e(TAG, "Could not close the client socket", e) } } }
Java
private class ConnectThread extends Thread { private final BluetoothSocket mmSocket; private final BluetoothDevice mmDevice; public ConnectThread(BluetoothDevice device) { // Use a temporary object that is later assigned to mmSocket // because mmSocket is final. BluetoothSocket tmp = null; mmDevice = device; try { // Get a BluetoothSocket to connect with the given BluetoothDevice. // MY_UUID is the app's UUID string, also used in the server code. tmp = device.createRfcommSocketToServiceRecord(MY_UUID); } catch (IOException e) { Log.e(TAG, "Socket's create() method failed", e); } mmSocket = tmp; } public void run() { // Cancel discovery because it otherwise slows down the connection. bluetoothAdapter.cancelDiscovery(); try { // Connect to the remote device through the socket. This call blocks // until it succeeds or throws an exception. mmSocket.connect(); } catch (IOException connectException) { // Unable to connect; close the socket and return. try { mmSocket.close(); } catch (IOException closeException) { Log.e(TAG, "Could not close the client socket", closeException); } return; } // The connection attempt succeeded. Perform work associated with // the connection in a separate thread. manageMyConnectedSocket(mmSocket); } // Closes the client socket and causes the thread to finish. public void cancel() { try { mmSocket.close(); } catch (IOException e) { Log.e(TAG, "Could not close the client socket", e); } } }
Perhatikan bahwa dalam cuplikan ini, cancelDiscovery()
dipanggil sebelum koneksi
percobaan terjadi. Anda harus selalu memanggil cancelDiscovery()
sebelum connect()
,
terutama karena cancelDiscovery()
berhasil terlepas dari apakah perangkat
penemuan sedang berlangsung. Jika aplikasi Anda perlu menentukan apakah
penemuan perangkat sedang berlangsung, Anda
dapat memeriksanya menggunakan
isDiscovering()
Metode manageMyConnectedSocket()
khusus aplikasi didesain untuk memulai
untuk mentransfer data, yang akan dibahas di bagian tentang
mentransfer data Bluetooth.
Setelah selesai menggunakan BluetoothSocket
, selalu panggil close()
. Tindakan ini
segera menutup soket yang terhubung dan melepaskan semua
Google Cloud Platform.