Dalam dokumen ini
- Dasar-Dasar
- Izin Bluetooth
- Menyiapkan Bluetooth
- Mencari Perangkat
- Menghubungkan Perangkat
- Mengelola Koneksi
- Bekerja dengan Profil
Kelas-kelas utama
Contoh-contoh terkait
Platform Android menyertakan dukungan untuk tumpukan jaringan Bluetooth, yang memungkinkan perangkat untuk secara nirkabel bertukar data dengan perangkat Bluetooth lainnya. Kerangka kerja aplikasi menyediakan akses ke fungsionalitas Bluetooth melalui Android Bluetooth API. API-API ini mengizinkan aplikasi secara nirkabel terhubung ke perangkat Bluetooth lainnya, memungkinkan fitur nirkabel point-to-point dan multipoint.
Menggunakan Bluetooth API, aplikasi Android bisa melakukan hal berikut:
- Memindai perangkat Bluetooth lain
- Melakukan kueri adaptor Bluetooth lokal untuk perangkat Bluetooth yang disandingkan
- Membangun saluran RFCOMM
- Terhubung ke perangkat lain melalui pencarian layanan
- Mentransfer data ke dan dari perangkat lain
- Mengelola beberapa koneksi
Dokumen ini menjelaskan cara menggunakan Bluetooth Klasik. Bluetooth Klasik adalah pilihan yang tepat untuk operasi yang menggunakan baterai lebih intensif seperti streaming dan komunikasi antar perangkat Android. Untuk perangkat Bluetooth dengan kebutuhan daya yang rendah, Android 4.3 (API Level 18) memperkenalkan dukungan API untuk Bluetooth Low Energy. Untuk mengetahui selengkapnya, lihat Bluetooth Low Energy.
Dasar-Dasar
Dokumen ini menjelaskan cara menggunakan Android Bluetooth API untuk menyelesaikan empat tugas utama yang diperlukan untuk berkomunikasi menggunakan Bluetooth: setelan Bluetooth, menemukan perangkat yang akan disandingkan atau tersedia dalam area lokal, menghubungkan perangkat, dan mentransfer data antar perangkat.
Semua Bluetooth API tersedia dalam paket android.bluetooth
. Berikut adalah ringkasan dari kelas dan antarmuka yang Anda perlukan untuk membuat koneksi
Bluetooth:
BluetoothAdapter- Merepresentasikan adaptor Bluetooth lokal (radio Bluetooth).
BluetoothAdapteradalah titik-masuk untuk semua interaksi Bluetooth. Dengan ini, Anda bisa menemukan perangkat Bluetooth lain, kueri daftar perangkat terikat (disandingkan), buat instanceBluetoothDevicemenggunakan alamat MAC yang dikenal, dan membuatBluetoothServerSocketuntuk mendengarkan komunikasi dari perangkat lain. BluetoothDevice- Merepresentasikan perangkat Bluetooth jarak jauh. Gunakan ini untuk meminta koneksi
dengan perangkat jarak jauh melalui
BluetoothSocketatau kueri informasi tentang perangkat seperti nama, alamat, kelas, dan status ikatan. BluetoothSocket- Merepresentasikan antarmuka untuk soket Bluetooth (mirip dengan TCP
Socket). Ini adalah titik koneksi yang memungkinkan sebuah aplikasi untuk bertukar data dengan perangkat Bluetooth lain melalui InputStream dan OutputStream. BluetoothServerSocket- Merepresentasikan soket server yang terbuka yang mendengarkan permintaan masuk
(mirip dengan TCP
ServerSocket). Agar bisa menghubungkan dua perangkat Android, satu perangkat harus membuka soket server dengan kelas ini. Ketika perangkat Bluetooth jarak jauh membuat permintaan koneksi ke perangkat ini,BluetoothServerSocketakan mengembalikanBluetoothSocketyang terhubung saat koneksi diterima. BluetoothClass- Menguraikan karakteristik umum dan kemampuan dari perangkat Bluetooth. Ini adalah set properti hanya-baca yang mendefinisikan kelas-kelas perangkat dan layanannya dari perangkat besar dan kecil. Akan tetapi, ini tidak Andal dalam menjelaskan semua profil dan layanan Bluetooth yang didukung perangkat, namun berguna sebagai petunjuk tipe perangkat.
BluetoothProfile- Antarmuka yang mewakili profil Bluetooth. Profil Bluetooth adalah spesifikasi antarmuka nirkabel untuk komunikasi berbasis-Bluetooth antar perangkat. Contohnya adalah profil Hands-Free. Untuk pembahasan lebih banyak tentang profil, lihat Bekerja dengan Profil
BluetoothHeadset- Menyediakan dukungan untuk headset Bluetooth yang akan digunakan pada ponsel. Ini termasuk profil Bluetooth Headset dan Hands-Free (v1.5).
BluetoothA2dp- Mendefinisikan bagaimana audio berkualitas tinggi bisa dialirkan dari satu perangkat ke perangkat lainnya melalui koneksi Bluetooth. "A2DP" adalah singkatan dari Advanced Audio Distribution Profile.
BluetoothHealth- Merepresentasikan proxy Health Device Profile yang mengontrol layanan Bluetooth.
BluetoothHealthCallback- Kelas abstrak yang Anda gunakan untuk mengimplementasikan callback
BluetoothHealth. Anda harus memperluas kelas ini dan mengimplementasikan metode callback untuk menerima pembaruan tentang perubahan dalam status registrasi aplikasi dan status saluran Bluetooth. BluetoothHealthAppConfiguration- Merepresentasikan konfigurasi aplikasi yang didaftar aplikasi Bluetooth Health pihak ketiga untuk berkomunikasi dengan perangkat kesehatan Bluetooth jarak jauh.
BluetoothProfile.ServiceListener- Antarmuka yang memberi tahu klien
BluetoothProfileIPC ketika mereka telah tersambung atau terputus dari layanan (yaitu , layanan internal yang menjalankan profil tertentu).
Izin Bluetooth
Untuk menggunakan fitur Bluetooth dalam aplikasi, Anda harus mendeklarasikan
izin Bluetooth BLUETOOTH.
Anda memerlukan izin ini untuk melakukan komunikasi Bluetooth,
seperti meminta koneksi, menerima koneksi, dan mentransfer data.
Jika Anda ingin aplikasi memulai pencarian perangkat atau memanipulasi setelan
Bluetooth, Anda juga harus mendeklarasikan izin BLUETOOTH_ADMIN
. Sebagian besar aplikasi membutuhkan izin ini agar memiliki
kemampuan untuk menemukan perangkat Bluetooth lokal. Kemampuan lain yang diberikan oleh izin
ini sebaiknya tidak digunakan, kecuali aplikasi tersebut adalah "power manager" yang
akan mengubah setelan Bluetooth atas permintaan pengguna. Catatan: Jika Anda
menggunakan izin BLUETOOTH_ADMIN, maka Anda juga
harus memiliki izin BLUETOOTH.
Mendeklarasikan izin Bluetooth dalam file manifes aplikasi Anda. Misalnya :
<manifest ... > <uses-permission android:name="android.permission.BLUETOOTH" /> ... </manifest>
Lihat referensi <uses-permission> untuk informasi selengkapnya tentang mendeklarasikan izin aplikasi.
Menyiapkan Bluetooth
Gambar 1: Mengaktifkan dialog Bluetooth.
Sebelum aplikasi Anda bisa berkomunikasi melalui Bluetooth, Anda harus memastikan bahwa Bluetooth didukung pada perangkat, dan jika memang demikian, pastikan bahwa itu diaktifkan.
Jika Bluetooth tidak didukung, maka Anda harus dengan lapang dada menonaktifkan semua
fitur Bluetooth. Jika Bluetooth didukung, tapi dinonaktifkan, maka Anda bisa meminta
pengguna untuk mengaktifkan Bluetooth tanpa harus menutup aplikasi. Penyiapan ini
dilakukan dalam dua langkah, menggunakan BluetoothAdapter.
- Dapatkan
BluetoothAdapterDiperlukan
BluetoothAdapteruntuk setiap dan semua aktivitas Bluetooth. Untuk mendapatkanBluetoothAdapter, panggil metode statisgetDefaultAdapter(). Ini akan mengembalikanBluetoothAdapteryang merepresentasikan adaptor Bluetooth milik perangkat (radio Bluetooth). Ada satu adaptor Bluetooth untuk seluruh sistem, dan aplikasi Anda bisa berinteraksi dengannya menggunakan objek ini. JikagetDefaultAdapter()mengembalikan null, maka perangkat tidak mendukung Bluetooth dan cerita berakhir di sini. Misalnya:BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (mBluetoothAdapter == null) { // Device does not support Bluetooth } - Mengaktifkan Bluetooth
Berikutnya, Anda harus memastikan bahwa Bluetooth diaktifkan. Panggil
isEnabled()untuk memeriksa apakah Bluetooth saat ini diaktifkan. Jika metode ini mengembalikan false, maka Bluetooth dinonaktifkan. Untuk meminta agar Bluetooth diaktifkan, panggilstartActivityForResult()dengan Maksud aksiACTION_REQUEST_ENABLE. Ini akan mengeluarkan permintaan untuk mengaktifkan Bluetooth melalui setelan sistem (tanpa menghentikan aplikasi Anda). Misalnya:if (!mBluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); }Sebuah dialog akan muncul meminta izin pengguna untuk mengaktifkan Bluetooth, seperti ditunjukkan pada Gambar 1. Jika pengguna menjawab "Yes," sistem akan mulai mengaktifkan Bluetooth dan fokus akan kembali ke aplikasi Anda setelah proses selesai (atau gagal).
Konstanta
REQUEST_ENABLE_BTyang diteruskan kestartActivityForResult()adalah integer yang didefinisikan secara lokal (harus lebih besar dari 0), yang dikembalikan sistem kepada Anda dalam implementasionActivityResult()sebagai parameterrequestCode.Jika berhasil mengaktifkan Bluetooth, aktivitas Anda akan menerima kode hasil
RESULT_OKdalam callbackonActivityResult(). Jika Bluetooth tidak diaktifkan karena kesalahan (atau karena pengguna menjawab "No") maka kode hasilnya adalahRESULT_CANCELED.
Atau, aplikasi Anda juga bisa mendengarkan maksud siaran
ACTION_STATE_CHANGED, yang
disiarkan sistem setiap kali status Bluetooth berubah. Siaran ini berisi
bidang tambahan EXTRA_STATE dan EXTRA_PREVIOUS_STATE, yang berisi status Bluetooth
baru dan lama. Kemungkinan nilai untuk bidang-bidang tambahan ini adalah
STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF, dan STATE_OFF. Mendengarkan siaran
ini bisa berguna untuk mendeteksi perubahan yang dibuat untuk status Bluetooth ketika aplikasi
Anda berjalan.
Tip: Mengaktifkan kemampuan untuk dapat ditemukan akan secara otomatis mengaktifkan Bluetooth. Jika Anda berencana untuk selalu mengaktifkan kemampuan untuk dapat ditemukan perangkat sebelum melakukan aktivitas Bluetooth, Anda bisa melewati langkah 2 di atas. Baca tentang mengaktifkan kemampuan untuk dapat ditemukan, di bawah ini.
Mencari Perangkat
Menggunakan BluetoothAdapter, Anda bisa menemukan perangkat
Bluetooth jarak jauh melalui pencarian perangkat atau dengan kueri daftar perangkat
yang disandingkan (diikat).
Pencarian perangkat adalah prosedur pemindaian yang menelusuri area lokal untuk perangkat yang mengaktifkan Bluetooth dan kemudian meminta beberapa informasi tentang setiap perangkat tersebut (ini kadang-kadang disebut dengan "menemukan", "menanyakan" atau "memindai"). Namun, perangkat Bluetooth dalam area lokal akan merespons permintaan penemuan hanya jika Bluetooth diaktifkan agar dapat ditemukan. Jika dapat ditemukan, perangkat tersebut akan merespons permintaan penemuan dengan berbagi beberapa informasi, seperti nama perangkat, kelas, dan alamat MAC yang unik. Menggunakan informasi ini, perangkat yang menjalankan pencarian bisa memilih untuk memulai koneksi ke perangkat yang ditemukan.
Setelah koneksi dibuat dengan perangkat jauh untuk pertama kalinya, permintaan penyandingan secara otomatis ditampilkan ke pengguna. Ketika perangkat disandingkan, informasi dasar tentang perangkat tersebut (seperti nama perangkat, kelas, dan alamat MAC) akan disimpan dan bisa dibaca dengan menggunakan Bluetooth API. Menggunakan alamat MAC yang dikenal untuk perangkat jauh, koneksi bisa dimulai dengan perangkat tersebut setiap saat tanpa menjalankan pencarian (dengan asumsi perangkat berada dalam jangkauan).
Ingat bahwa ada perbedaan antara yang disandingkan dan yang dihubungkan. Disandingkan artinya dua perangkat saling menyadari keberadaan masing-masing, memiliki kunci-tautan bersama yang bisa digunakan untuk autentikasi, dan dapat membangun koneksi terenkripsi satu sama lain. Dihubungkan artinya perangkat saat ini berbagi saluran RFCOMM dan bisa saling berkiriman data. Android Bluetooth API sekarang membutuhkan perangkat untuk disandingkan sebelum koneksi RFCOMM dapat dibuat. (Penyandingan secara otomatis dilakukan ketika Anda memulai koneksi terenkripsi dengan Bluetooth API.)
Bagian berikut menjelaskan cara menemukan perangkat yang telah disandingkan, atau menemukan perangkat baru menggunakan pencarian perangkat.
Catatan: Perangkat Android tidak dapat ditemukan secara default. Pengguna bisa membuat perangkat dapat ditemukan untuk jangka waktu terbatas melalui setelan sistem, atau aplikasi bisa meminta pengguna mengaktifkan kemampuan untuk dapat ditemukan tanpa meninggalkan aplikasi. Cara mengaktifkan kemampuan untuk dapat ditemukan dibahas di bawah ini.
Melakukan kueri perangkat yang disandingkan
Sebelum melakukan pencarian perangkat, ada baiknya melakukan kueri kumpulan
perangkat yang disandingkan untuk melihat jika perangkat yang diinginkan sudah dikenal. Untuk melakukannya,
panggil getBondedDevices(). Ini
akan mengembalikan Set BluetoothDevice yang mewakili
perangkat yang disandingkan. Misalnya, Anda bisa melakukan kueri semua perangkat yang disandingkan dan kemudian
menampilkan nama masing-masing perangkat kepada pengguna, menggunakan ArrayAdapter:
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
// If there are paired devices
if (pairedDevices.size() > 0) {
// Loop through paired devices
for (BluetoothDevice device : pairedDevices) {
// Add the name and address to an array adapter to show in a ListView
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
Semua yang dibutuhkan dari objek BluetoothDevice agar
bisa memulai koneksi adalah alamat MAC. Dalam contoh ini, itu disimpan
sebagai bagian dari ArrayAdapter yang ditampilkan kepada pengguna. Alamat MAC nantinya
bisa diambil agar dapat memulai koneksi. Anda bisa mempelajari selengkapnya tentang membuat
koneksi dalam bagian tentang Menghubungkan Perangkat.
Menemukan perangkat
Untuk mulai menemukan perangkat, cukup panggil startDiscovery(). Proses
ini asinkron dan metode ini akan langsung dikembalikan dengan boolean
yang menunjukkan apakah penemuan telah berhasil dimulai. Proses penemuan
biasanya melibatkan pemindaian pemeriksaan sekitar 12 detik, diikuti dengan pemindaian laman dari
setiap perangkat yang ditemukan untuk mengambil nama Bluetooth-nya.
Aplikasi Anda harus mendaftar BroadcastReceiver untuk Maksud
ACTION_FOUND agar
bisa menerima informasi tentang setiap
perangkat yang ditemukan. Untuk setiap perangkat, sistem akan menyiarkan Maksud
ACTION_FOUND. Maksud
ini membawa bidang tambahan
EXTRA_DEVICE dan
EXTRA_CLASS, berisi
BluetoothDevice dan BluetoothClass. Misalnya, berikut ini adalah cara
mendaftar untuk menangani siaran ketika perangkat ditemukan:
// Create a BroadcastReceiver for ACTION_FOUND
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Add the name and address to an array adapter to show in a ListView
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
};
// Register the BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
Semua yang dibutuhkan dari objek BluetoothDevice agar
bisa memulai
koneksi adalah alamat MAC. Dalam contoh ini, itu disimpan sebagai bagian dari
ArrayAdapter yang ditampilkan kepada pengguna. Alamat MAC nantinya bisa diambil agar
dapat memulai koneksi. Anda bisa mempelajari selengkapnya tentang membuat koneksi
dalam bagian tentang Menghubungkan Perangkat.
Perhatian: Melakukan pencarian perangkat adalah
prosedur yang berat bagi adaptor
Bluetooth dan mengonsumsi banyak sumber daya. Setelah menemukan perangkat yang akan
dihubungkan, pastikan Anda selalu menghentikan pencarian dengan
cancelDiscovery() sebelum
melakukan koneksi. Juga, jika Anda
sudah memiliki koneksi dengan suatu perangkat, maka melakukan pencarian bisa
secara signifikan mengurangi bandwidth yang tersedia untuk koneksi, sehingga Anda sebaiknya
tidak melakukan pencarian saat terhubung.
Mengaktifkan kemampuan untuk dapat ditemukan
Jika Anda menginginkan agar perangkat lokal dapat ditemukan oleh perangkat lain,
panggil startActivityForResult(Intent, int) dengan Maksud aksi
ACTION_REQUEST_DISCOVERABLE
. Ini akan mengeluarkan permintaan untuk mengaktifkan mode dapat ditemukan melalui setelan
sistem (tanpa menghentikan aplikasi Anda). Secara default, perangkat akan
dapat ditemukan selama 120 detik. Anda bisa menetapkan durasi yang berbeda dengan menambahkan tambahan Maksud
EXTRA_DISCOVERABLE_DURATION
. Durasi maksimum yang bisa disetel aplikasi adalah 3600 detik, dan nilai 0
berarti perangkat selalu dapat ditemukan. Setiap nilai di bawah 0 atau di atas 3600
secara otomatis disetel ke 120 detik). Misalnya, cuplikan ini menetapkan durasi
300:
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); startActivity(discoverableIntent);
Gambar 2: Mengaktifkan dialog kemampuan untuk dapat ditemukan.
Sebuah dialog akan ditampilkan, meminta izin pengguna agar perangkat
dapat ditemukan, seperti ditunjukkan pada Gambar 2. Jika pengguna menjawab "Yes," maka perangkat
menjadi dapat ditemukan untuk jangka waktu tertentu. Aktivitas Anda kemudian
akan menerima panggilan ke callback onActivityResult()), dengan kode hasil yang sama dengan durasi perangkat
dapat ditemukan. Jika pengguna menjawab "No" atau terjadi kesalahan, kode hasil akan
menjadi RESULT_CANCELED.
Catatan: Jika Bluetooth belum diaktifkan pada perangkat, maka mengaktifkan kemampuan untuk dapat ditemukan secara otomatis akan mengaktifkan Bluetooth.
Perangkat diam-diam akan tetap dalam mode dapat ditemukan untuk waktu yang telah ditentukan.
Jika Anda ingin diberi tahu ketika mode dapat ditemukan telah berubah, Anda bisa
mendaftarkan BroadcastReceiver ke Maksud ACTION_SCAN_MODE_CHANGED
. Ini akan berisi bidang tambahan EXTRA_SCAN_MODE dan
EXTRA_PREVIOUS_SCAN_MODE, yang memberi tahu Anda
mode pemindaian baru dan lama. Kemungkinan nilainya adalah
SCAN_MODE_CONNECTABLE_DISCOVERABLE,
SCAN_MODE_CONNECTABLE, atau SCAN_MODE_NONE,
menunjukkan bahwa perangkat dalam mode dapat ditemukan, tidak
dalam mode dapat ditemukan tapi masih bisa menerima koneksi, atau tidak dalam mode
dapat ditemukan dan tidak dapat menerima koneksi.
Anda tidak perlu mengaktifkan kemampuan untuk dapat ditemukan jika Anda akan memulai koneksi ke perangkat jauh. Mengaktifkan kemampuan untuk dapat ditemukan hanya diperlukan bila Anda menginginkan aplikasi Anda untuk menjadi host soket server yang akan menerima koneksi masuk, karena perangkat jauh harus dapat menemukan perangkat sebelum bisa memulai koneksi.
Menghubungkan Perangkat
Agar bisa membuat koneksi antar aplikasi pada dua perangkat, Anda
harus mengimplementasikan mekanisme sisi-server dan sisi-klien, karena salah satu
perangkat harus membuka soket server dan yang lainnya harus memulai koneksi
(menggunakan alamat MAC perangkat server untuk memulai koneksi). Server dan
klien dianggap terhubung satu sama lain ketika mereka masing-masing memiliki
BluetoothSocket yang telah terhubung pada saluran RFCOMM yang sama. Pada tahap
ini, setiap perangkat bisa memperoleh aliran masukan dan keluaran serta transfer data dapat
dimulai, yang dibahas dalam bagian mengenai Mengelola Koneksi. Bagian ini menjelaskan cara
memulai koneksi antara dua perangkat.
Perangkat server dan perangkat klien masing-masing memperoleh BluetoothSocket yang diperlukan dengan cara berbeda. Server akan menerimanya
ketika koneksi masuk diterima. Klien akan menerimanya ketika
membuka saluran RFCOMM ke server.
Gambar 3: Dialog penyandingan Bluetooth.
Salah satu teknik implementasi adalah dengan secara otomatis mempersiapkan setiap perangkat sebagai server, sehingga masing-masing memiliki soket server yang terbuka dan mendengarkan koneksi. Maka tiap-tiap perangkat bisa memulai koneksi dengan yang lainnya dan menjadi klien. Atau, salah satu perangkat bisa secara eksplisit "menjadi host" koneksi dan membuka soket server sesuai permintaan dan perangkat lain bisa dengan mudah memulai koneksi.
Catatan: Jika dua perangkat belum disandingkan sebelumnya, maka kerangka kerja Android secara otomatis akan menampilkan notifikasi permintaan penyandingan atau dialog ke pengguna selama prosedur koneksi, seperti yang ditunjukkan pada Gambar 3. Jadi ketika mencoba untuk menghubungkan perangkat, aplikasi Anda tidak perlu khawatir mengenai apakah perangkat disandingkan atau tidak. Percobaan koneksi RFCOMM Anda akan diblokir hingga pengguna telah berhasil disandingkan, atau akan gagal jika pengguna menolak penyandingan, atau jika penyandingan gagal atau waktu habis.
Menghubungkan sebagai server
Bila Anda ingin menghubungkan dua perangkat, salah satunya harus bertindak sebagai server dengan memegang
BluetoothServerSocket terbuka. Tujuan dari soket
server adalah untuk mendengarkan permintaan koneksi masuk dan ketika ada yang diterima,
menyediakan BluetoothSocket yang terhubung. Ketika BluetoothSocket diperoleh dari BluetoothServerSocket,
BluetoothServerSocket bisa (dan sebaiknya)
dibuang, kecuali jika Anda ingin menerima lebih banyak koneksi.
Tentang UUID
Universally Unique Identifier (UUID) adalah format 128-bit terstandardisasi untuk ID
string yang digunakan untuk mengidentifikasi informasi secara unik. Inti dari UUID adalah bahwa itu cukup
besar sehingga Anda bisa memilih secara acak dan tidak akan berbenturan. Dalam hal ini, itu
digunakan untuk mengidentifikasi secara unik layanan Bluetooth aplikasi Anda. Agar UUID bisa
digunakan dengan aplikasi, Anda dapat menggunakan salah satu dari banyak pembuat UUID acak di
web, kemudian melakukan inisialisasi UUID dengan fromString(String).
Berikut ini adalah prosedur dasar menyiapkan sebuah soket server dan menerima koneksi:
- Dapatkan
BluetoothServerSocketdengan memanggillistenUsingRfcommWithServiceRecord(String, UUID).String adalah nama yang bisa diidentifikasi layanan Anda, yang akan secara otomatis ditulis sistem ke entri database Service Discovery Protocol (SDP) baru pada perangkat (namanya bebas dan dapat berupa nama aplikasi Anda). UUID ini juga dimasukkan dalam entri SDP dan akan menjadi dasar untuk perjanjian koneksi dengan perangkat klien. Artinya, ketika klien mencoba untuk terhubung dengan perangkat ini, itu akan membawa UUID yang secara unik mengidentifikasi layanan dengan yang hendak dihubungkan olehnya. UUID ini harus cocok agar koneksi bisa diterima (pada langkah berikutnya).
- Mulai dengarkan permintaan koneksi dengan memanggil
accept().Ini adalah panggilan pemblokir. Itu akan dikembalikan bila koneksi sudah diterima atau telah terjadi sebuah pengecualian. Koneksi diterima hanya bila perangkat jauh telah mengirimkan permintaan koneksi dengan UUID yang cocok dengan yang terdaftar pada soket server pendengar. Bila berhasil,
accept()akan mengembalikanBluetoothSocketyang terhubung. - Kecuali Anda ingin menerima koneksi tambahan, panggil
close().Ini melepaskan soket server dan semua sumber daya, namun tidak menutup
BluetoothSocketterhubung yang telah dikembalikan olehaccept(). Tidak seperti TCP/IP, RFCOMM hanya mengizinkan satu klien terhubung per saluran pada satu waktu, sehingga dalam banyak kasus, hal yang wajar memanggilclose()padaBluetoothServerSocketlangsung setelah menerima soket yang terhubung.
Panggilan accept() sebaiknya tidak
dijalankan dalam thread UI aktivitas utama karena merupakan panggilan pemblokir dan
akan mencegah interaksi lain dengan aplikasi tersebut. Hal yang bisa
dimengerti untuk melakukan semua pekerjaan dengan BluetoothServerSocket atau BluetoothSocket di thread
baru yang dikelola oleh aplikasi Anda. Untuk membatalkan panggilan yang diblokir seperti accept(), panggil close() pada BluetoothServerSocket (atau BluetoothSocket) dari thread lain dan panggilan yang diblokir akan
segera kembali. Perhatikan bahwa semua metode pada BluetoothServerSocket atau BluetoothSocket
adalah thread-safe.
Contoh
Berikut adalah thread yang disederhanakan untuk komponen server yang menerima koneksi masuk:
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 = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
} catch (IOException 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) {
break;
}
// If a connection was accepted
if (socket != null) {
// Do work to manage the connection (in a separate thread)
manageConnectedSocket(socket);
mmServerSocket.close();
break;
}
}
}
/** Will cancel the listening socket, and cause the thread to finish */
public void cancel() {
try {
mmServerSocket.close();
} catch (IOException e) { }
}
}
Dalam contoh ini, hanya satu koneksi masuk yang dikehendaki, jadi segera setelah
koneksi diterima dan BluetoothSocket
diperoleh, aplikasi
mengirimkan BluetoothSocket yang diperoleh ke thread
terpisah, menutup
BluetoothServerSocket dan menghentikan loop.
Perhatikan bahwa ketika accept()
mengembalikan BluetoothSocket, soket sudah
terhubung, sehingga Anda sebaiknya tidak memanggil connect() (seperti yang Anda lakukan dari
sisi-klien).
manageConnectedSocket() adalah metode fiksi dalam aplikasi
yang akan
memulai thread untuk mentransfer data, yang dibahas pada bagian
tentang Mengelola Koneksi.
Anda biasanya harus segera menutup BluetoothServerSocket
setelah Anda selesai mendengarkan koneksi masuk. Dalam contoh ini, close() dipanggil segera
setelah BluetoothSocket diperoleh. Anda mungkin juga perlu
menyediakan metode publik dalam thread yang bisa menutup BluetoothSocket ketika Anda harus berhenti mendengarkan
soket server.
Menghubungkan sebagai klien
Agar bisa memulai koneksi dengan perangkat jauh (perangkat yang memegang
soket server
terbuka), Anda harus terlebih dahulu memperoleh objek BluetoothDevice yang merepresentasikan perangkat jauh.
(Memperoleh sebuah BluetoothDevice dibahas pada bagian
di atas tentang Mencari Perangkat.) Anda kemudian harus menggunakan
BluetoothDevice untuk memperoleh BluetoothSocket dan memulai koneksi.
Berikut adalah prosedur dasarnya:
- Dengan menggunakan
BluetoothDevice, dapatkanBluetoothSocketdengan memanggilcreateRfcommSocketToServiceRecord(UUID).Ini akan melakukan inisialiasi
BluetoothSocketyang akan terhubung keBluetoothDevice. UUID yang diberikan di sini harus cocok dengan UUID yang digunakan oleh perangkat server ketika membukaBluetoothServerSocket(denganlistenUsingRfcommWithServiceRecord(String, UUID)). Menggunakan UUID yang sama hanya merupakan masalah hard-coding string UUID ke dalam aplikasi Anda dan kemudian mereferensikannya dari kode server dan kode klien. - Memulai koneksi dengan memanggil
connect().Setelah panggilan ini, sistem akan melakukan pencarian SDP pada perangkat jauh untuk mencocokkan UUID. Jika pencarian tersebut berhasil dan perangkat jauh menerima koneksi, itu akan berbagi saluran RFCOMM yang akan digunakan selama koneksi dan
connect()akan kembali. Metode ini adalah panggilan pemblokir. Jika, karena suatu alasan, koneksi gagal atau metodeconnect()waktunya habis (setelah sekitar 12 detik), maka itu akan mengeluarkan pengecualian.Karena
connect()adalah panggilan pemblokir, prosedur koneksi ini harus selalu dilakukan dalam thread terpisah dari thread aktivitas utama.Catatan: Anda harus selalu memastikan bahwa perangkat tidak melakukan pencarian perangkat ketika Anda memanggil
connect(). Jika pencarian sedang berlangsung, maka upaya koneksi akan jauh lebih lambat dan kemungkinan besar gagal.
Contoh
Berikut ini adalah contoh dasar dari thread yang memulai koneksi Bluetooth:
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;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
// MY_UUID is the app's UUID string, also used by the server code
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) { }
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the connection
mBluetoothAdapter.cancelDiscovery();
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
try {
mmSocket.close();
} catch (IOException closeException) { }
return;
}
// Do work to manage the connection (in a separate thread)
manageConnectedSocket(mmSocket);
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
Perhatikan bahwa cancelDiscovery() dipanggil
sebelum koneksi dilakukan. Anda sebaiknya selalu melakukan hal ini sebelum menghubungkan dan aman
untuk memanggil tanpa benar-benar memeriksa apakah itu berjalan atau tidak (namun jika Anda ingin
memeriksa, panggil isDiscovering()).
manageConnectedSocket() adalah metode fiksi dalam aplikasi
yang akan memulai thread untuk mentransfer data, yang dibahas pada bagian
tentang Mengelola Koneksi.
Setelah Anda selesai dengan BluetoothSocket, selalu
panggil close() untuk membersihkannya.
Melakukan hal ini akan langsung menutup soket yang terhubung dan membersihkan semua sumber daya
internal.
Mengelola Koneksi
Ketika Anda berhasil menghubungkan dua perangkat (atau lebih), masing-masing akan
memiliki BluetoothSocket yang terhubung. Ini adalah awal
dari semua kesenangan karena Anda bisa berbagi data antar perangkat. Dengan menggunakan BluetoothSocket, prosedur umum untuk mentransfer data bebas cukup
sederhana:
- Dapatkan
InputStreamdanOutputStreamyang menangani transmisi lewat soket, masing-masing melaluigetInputStream()dangetOutputStream(). - Membaca dan menulis data ke aliran dengan
read(byte[])danwrite(byte[]).
Demikian saja.
Tentu saja, ada detail implementasi yang harus dipertimbangkan. Pertama dan terpenting,
Anda harus menggunakan thread khusus untuk semua aliran membaca dan menulis. Hal ini
penting karena kedua metode read(byte[]) dan write(byte[]) memblokir panggilan. read(byte[]) akan memblokir sampai ada sesuatu yang bisa dibaca
dari aliran. write(byte[]) biasanya tidak
memblokir, namun dapat memblokir untuk kontrol alur jika perangkat jauh tidak memanggil read(byte[]) dengan cukup cepat dan buffer perantara penuh.
Jadi, loop utama Anda dalam thread harus didedikasikan untuk membaca dari InputStream. Sebuah metode publik yang terpisah dalam thread bisa digunakan untuk memulai
penulisan ke OutputStream.
Contoh
Berikut adalah contoh bagaimana hal ini akan terlihat:
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI activity
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
break;
}
}
}
/* Call this from the main activity to send data to the remote device */
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
Konstruktor mendapatkan aliran yang diperlukan dan setelah dieksekusi, thread
akan menunggu data untuk datang melalui InputStream. Bila read(byte[]) dikembalikan dengan
byte dari aliran, data akan dikirim ke aktivitas utama menggunakan Penangan
anggota dari kelas induk. Kemudian itu kembali dan menunggu lebih banyak byte dari
aliran.
Mengirim data keluar adalah semudah seperti memanggil metode
write() thread dari aktivitas utama dan memberikan byte yang
akan dikirim. Metode ini cukup memanggil write(byte[]) untuk mengirim data ke perangkat jauh.
Metode cancel() thread ini penting sehingga koneksi
bisa
dihentikan setiap saat dengan menutup BluetoothSocket.
Ini harus selalu dipanggil bila Anda sudah selesai menggunakan koneksi
Bluetooth.
Untuk mendemonstrasikan penggunaan Bluetooth API, lihat aplikasi contoh Bluetooth Chat.
Bekerja dengan Profil
Mulai dari Android 3.0, Bluetooth API menyertakan dukungan untuk bekerja dengan profil Bluetooth. Profil Bluetooth adalah spesifikasi antarmuka nirkabel untuk komunikasi berbasis-Bluetooth antar perangkat. Contohnya adalah profil Hands-Free. Agar ponsel bisa terhubung ke headset nirkabel, kedua perangkat harus mendukung profil Hands-Free.
Anda bisa mengimplementasikan antarmuka BluetoothProfile untuk menulis
kelas Anda sendiri untuk mendukung profil Bluetooth tertentu. Android
Bluetooth API menyediakan implementasi untuk profil
Bluetooth berikut:
- Headset. Profil Headset menyediakan dukungan untuk
headset Bluetooth yang akan digunakan dengan ponsel. Android menyediakan kelas
BluetoothHeadset, yang merupakan proxy untuk mengontrol Layanan Bluetooth Headset melalui komunikasi antarproses (interprocess communication - IPC). Ini berisi profil Bluetooth Headset dan Hands-Free (v1.5). KelasBluetoothHeadsetmenyertakan dukungan untuk perintah AT. Untuk pembahasan selengkapnya tentang topik ini, lihat Perintah AT khusus-Vendor - A2DP. Profil
Advanced Audio Distribution Profile (A2DP) mendefinisikan bagaimana audio berkualitas tinggi bisa dialirkan dari satu perangkat ke
perangkat lainnya melalui koneksi Bluetooth. Android menyediakan kelas
BluetoothA2dp, yang merupakan proxy untuk mengontrol Layanan Bluetooth A2DP melalui IPC. - Health Device. Android 4.0 (API level 14) memperkenalkan dukungan untuk Bluetooth Health Device Profile (HDP). Ini memungkinkan Anda membuat aplikasi yang menggunakan Bluetooth untuk berkomunikasi dengan perangkat kesehatan yang mendukung Bluetooth, seperti pemantau denyut jantung, tekanan darah, termometer, timbangan, dan sebagainya. Untuk daftar perangkat yang didukung dan kode khusus data perangkat yang sesuai, silakan lihat Bluetooth Assigned Numbers pada www.bluetooth.org. Perhatikan bahwa nilai-nilai ini juga direferensikan pada spesifikasi ISO/IEEE 11073-20601 [7] seperti MDC_DEV_SPEC_PROFILE_* dalam Nomenclature Codes Annex. Untuk pembahasan lebih banyak tentang HDP, lihat Health Device Profile.
Berikut adalah langkah-langkah dasar untuk bekerja dengan profil:
- Dapatkan adaptor default, seperti yang dijelaskan dalam Menyiapkan Bluetooth.
- Gunakan
getProfileProxy()untuk membuat koneksi ke objek proxy profil yang terkait dengan profil. Pada contoh di bawah ini, objek proxy profil adalah instance dariBluetoothHeadset. - Menyiapkan
BluetoothProfile.ServiceListener. Listener ini memberi tahu klien IPCBluetoothProfileketika mereka telah terhubung atau terputus dari layanan. - Dalam
onServiceConnected(), dapatkan penangan untuk objek proxy profil. - Setelah Anda memiliki objek proxy profil, Anda bisa menggunakannya untuk memantau status koneksi dan melakukan operasi lain yang relevan dengan profil tersebut.
Misalnya, cuplikan kode ini menunjukkan cara melakukan koneksi ke objek proxy BluetoothHeadset sehingga Anda bisa mengontrol
profil Headset:
BluetoothHeadset mBluetoothHeadset;
// Get the default adapter
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// Establish connection to the proxy.
mBluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.HEADSET);
private BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (profile == BluetoothProfile.HEADSET) {
mBluetoothHeadset = (BluetoothHeadset) proxy;
}
}
public void onServiceDisconnected(int profile) {
if (profile == BluetoothProfile.HEADSET) {
mBluetoothHeadset = null;
}
}
};
// ... call functions on mBluetoothHeadset
// Close proxy connection after use.
mBluetoothAdapter.closeProfileProxy(mBluetoothHeadset);
Perintah AT khusus-vendor
Mulai Android 3.0, aplikasi bisa mendaftar untuk menerima siaran
sistem dari perintah AT khusus-vendor yang telah didefinisikan yang dikirimkan oleh headset (seperti
perintah Plantronics +XEVENT). Misalnya, sebuah aplikasi bisa menerima
siaran yang menunjukkan tingkat baterai perangkat yang terhubung dan dapat memberi tahu
pengguna atau melakukan aksi lain bila perlu. Membuat penerima siaran bagi maksud ACTION_VENDOR_SPECIFIC_HEADSET_EVENT untuk
menangani perintah AT khusus-vendor untuk headset.
Health Device Profile
Android 4.0 (API level 14) memperkenalkan dukungan untuk Bluetooth Health Device
Profile (HDP). Ini memungkinkan Anda membuat aplikasi yang menggunakan Bluetooth untuk
berkomunikasi dengan perangkat kesehatan yang mendukung Bluetooth, seperti pemantau
denyut-jantung, tekanan darah, termometer, dan timbangan. Bluetooth Health API
berisi kelas-kelas BluetoothHealth, BluetoothHealthCallback, dan BluetoothHealthAppConfiguration, yang dijelaskan dalam Dasar-Dasar.
Dalam menggunakan Bluetooth Health API, akan sangat membantu jika memahami konsep-konsep penting HDP:
| Konsep | Keterangan |
|---|---|
| Source | Peranan yang didefinisikan dalam HDP. Source adalah perangkat kesehatan yang mentransmisikan data medis (timbangan, pengukur glukosa, termometer, dll) ke perangkat cerdas seperti ponsel atau Tablet Android. |
| Sink | Peranan yang didefinisikan dalam HDP. Dalam HDP, sink adalah perangkat cerdas yang
menerima data medis. Dalam aplikasi HDP Android, sink
dinyatakan oleh objek BluetoothHealthAppConfiguration
. |
| Registration | Mengacu pada pendaftaran sink untuk perangkat kesehatan tertentu. |
| Connection | Mengacu pada pembukaan saluran antara perangkat kesehatan dan perangkat cerdas seperti ponsel atau Tablet Android. |
Membuat Aplikasi HDP
Berikut adalah langkah-langkah dasar yang harus dilakukan untuk membuat aplikasi HDP Android:
- Dapatkan referensi ke objek proxy
BluetoothHealth.Mirip dengan headset biasa dan perangkat profil A2DP, Anda harus memanggil
getProfileProxy()denganBluetoothProfile.ServiceListenerdan tipe profilHEALTHuntuk membangun koneksi dengan objek proxy profil. - Buat
BluetoothHealthCallbackdan daftarkan konfigurasi aplikasi (BluetoothHealthAppConfiguration) yang bertindak sebagai sink kesehatan. - Membuat koneksi ke perangkat kesehatan. Beberapa perangkat akan mengawali koneksi. Tidak diperlukan menjalankan langkah ini untuk perangkat tersebut.
- Ketika berhasil tersambung ke perangkat kesehatan, baca/tulis ke perangkat
kesehatan menggunakan deskriptor file.
Data yang diterima perlu diterjemahkan menggunakan pengelola kesehatan yang mengimplementasikan spesifikasi IEEE 11073-xxxxx.
- Setelah selesai, tutup saluran kesehatan dan mencabut pendaftaran aplikasi. Saluran ini juga ditutup ketika tidak ada aktivitas dalam waktu lama.
Untuk contoh kode lengkap yang memperlihatkan langkah-langkah ini, lihat Bluetooth HDP (Health Device Profile).