Membuat App Bluetooth di Android (3): Komunikasi Antar Devices

Bagian ini tingkat kesulitannya cukup tinggi. Sebelumnya diharapkan pembaca telah memahami prinsip-prinsip thread (lihat kembali tutorialnya). Penting: Tutorial ini akan menggunakan project dari tutorial tentang Bluetooth sebelumnya.

Bluetooth menggunakan prinsip master-slave atau client server, dan dapat bertukar posisi. Satu server dapat terhubung sampai dengan tujuh client. Dalam tutorial ini kita akan membuat satu app dapat berfungsi sebagai server maupun sebagai client. Sebaiknya gunakan dua HP dan hubungkan keduanya dengan laptop dalam mode USB debugging, sehingga bisa langsung dicoba. Setiap dicompile, deploy ke kedua device, lalu satu menjadi server dan satu menjadi client.

ui_bluetooth_client_server

Supaya lebih jelas, video eksekusi app dapat dilihat di:[youtube.com]

Tahapan di client adalah sebagai berikut:

  1. Aktifkan BT jika dalam kondisi off
  2. Tampilkan daftar device yang sudah dipair dalam listview
  3. Jika server belum ada (belum pernah dipair sebelumnya) tekan tombol “Start Discovery” → listview akan bertambah dengan device baru. Jika sudah ada, langsung ke langkah berikutnya.
  4. User men-tap device server yang dikehendaki di listview. Jika belum di-pair maka dialog untuk pairing akan otomatis muncul.
  5. Setelah terhubung, user menekan button untuk mengirim data.

Tahap 1 sampai 3 sudah dilakukan di tutorial sebelumnya.

Tahapan di server adalah sebagai berikut:

  1. Aktifkan BT jika dalam kondisi off
  2. Nyalakan mode discoverablity, ini wajib jika client-server belum di-pair sebelumnya. Karena kalau tidak, maka server tidak akan terlihat oleh client.
  3. Tunggu sampai ada client yang terhubung.
  4. Jika ada client yang terhubung, terima data dan tampilkan di user interface.

Akan ada tiga buah thread:

  1. Thread di server untuk menerima koneksi dari client
  2. Thread di client untuk menghubungi server.
  3. Thread di server dan client untuk berkomunikasi data.

 

 

Kita akan mulai dari sisi server. Buka kembali project pada tutorial sebelumnya. Project tersebut akan kita jadikan client dan server.

Pertama tambahkan button, untuk mengenable server. Jika user men-tap button ini, maka device akan masuk ke mode discoverable dan masuk ke loop untuk menerima koneksi.

Tambahkan aksi saat user mentap tombol enable server sebagai berikut:

public static final int REQUEST_ENABLE_DISCOVERY=998;//konstanta

//saat server di enable
public void klikServer(View v) {

   // nyalakan discoverable, agar client dapat melihat (jika belum pair sebelumnya)
   // otomatis akan menyalakan bluetooth
   // hanya untuk server, kalau sebagai client tidak perlu

   Intent discoverableIntent = new
           Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
   discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
   startActivityForResult(discoverableIntent, REQUEST_ENABLE_DISCOVERY);
   //hasil ankan ditangkap di onActivityResult
}

Akan muncul dialog seperti ini

dialog_ijin_phone_visible

Saat user selesai mengenable discoverable, maka onActivityResult akan dipanggil. Pada onActivityResult kita akan mulai menerima koneksi (tambahan code ditunjukkan dengan panah

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   if (requestCode == REQUEST_ENABLE_BT) {
       String pesan;
       if (resultCode == RESULT_OK) {
           //user menyalakan bluetooth
           pesan = "Bluetooth dinyalakan";
           tampilkanPaired();  
       } else {
           // user deny
           pesan = "Bluetooth tidak mau dinyalakan user!";
       }
       Toast toast = Toast.makeText(getApplicationContext(), pesan, Toast.LENGTH_LONG);
       toast.show();
   } else {
       // <----------------------  untuk server
       //service discovery sudah nyala, lanjutkan dengan menerima koneksi
       if (requestCode == REQUEST_ENABLE_DISCOVERY) {
           if (resultCode != RESULT_CANCELED) {
               //OK, nyala sekarang, panggil method server untuk menerima koneksi
               server();
           }
       }
   }
}

Sekarang untuk menerima koneksi dari client. Pertama siapkan UUID, UUID adalah id yang dianggap akan unik (karena random dan ukurannya yang besar). UUID berfungsi untuk menghubungkan app server dan client. Gunakan situs seperti www.uuidgenerator.net untuk mendapatkan UUID. Ganti UUID di contoh dibawah.

public static final String NAME ="COBASERVER"; //service name
//ganti UUID ini! gunakan generator spt www.uuidgenerator.net
public UUID MY_UUID=UUID.fromString("eb5a63b9-a32b-4ca9-896c-7204f3bfc55b");
 

Karena proses menerima koneksi dilakukan dalam loop, maka tidak mungkin diakukan di thread utama (akan menyebabkan “app not responsive”). Oleh karena itu kita perlu membuat thread terpisah. Buat kelas AcceptThread seperti berikut dan letakkan di kelas MainActivity. Method manageConnectedSocket akan dibuat kemudian.

/**
*    Untuk server.
*    Thread berisi loop sampai menerima hubungan dari client
*/
private  class AcceptThread extends Thread {

       private BluetoothServerSocket mmServerSocket=null;
       
       public AcceptThread() {
           //constructor
           //siapkan socket
           mmServerSocket = null;
           try {
               mmServerSocket = 
                     mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
           } catch (IOException e) {
               Log.e("ywlog",e.getMessage());
               e.printStackTrace();
           }
       }

       public void run() {
           BluetoothSocket socket = null;
           // loop sampai socket terisi (tidak null)
           while (true) {
               try {
                   socket = mmServerSocket.accept();
               } catch (IOException e) {
                   Log.e("ywlog",e.getMessage());
                   break;
               }
               // ada koneksi yang diterima dari client
               if (socket != null) {
                   //proses di thread terpisah
                   manageConnectedSocket(socket);

                   //karena bluetooth cuma menerima satu channel, close saja
                   try {
                       mmServerSocket.close();
                   } catch (IOException e) {
                       Log.e("ywlog",e.getMessage());
                       e.printStackTrace();
                   }
                   break;
               }
           }
       }

       /**  Untuk mematikan koneksi server */
       public void cancel() {
           try {
               mmServerSocket.close();
           } catch (IOException e) {
               Log.e("ywlog",e.getMessage());
               e.printStackTrace();
           }
       }

}


public void server()  {
   //mulai jalankan thread server
   (new AcceptThread()).start();
}

Jika socket sudah terhubung, maka akan dipanggil method manageConnecteSocket, dalam method ini akan dipanggil thread yang menangani komunikasi antara server dan client. Artinya thread ini juga nanti akan digunakan untuk bagian client. Buat thread bernama ConnectedThread dan letakkan di kelas MainActivity.

ConnectedThread ct;

/*
  saat server dan client sudah terhubung, thread yang menangani komunikasi data
*/

private class ConnectedThread extends Thread {
   private BluetoothSocket mmSocket;
   private InputStream mmInStream;
   private OutputStream mmOutStream;
   private String strData;

   public ConnectedThread(BluetoothSocket socket) {
       //siapkan input dan output stream
       mmSocket = socket;
       InputStream tmpIn = null;
       OutputStream tmpOut = null;

       //ambil input dan output stream
       try {
           mmInStream = socket.getInputStream();
           mmOutStream = socket.getOutputStream();
       } catch (IOException e) {
           Log.e("ywlog", e.getMessage());
           e.printStackTrace();
       }
   }

   public void run() {
       byte[] buffer = new byte[1024];  // buffer stream
       int bytes; // jumlah bytes yang dibaca read()

       // SERVER: mendengarkan InputStream
       while (true) {
           try {
               bytes = mmInStream.read(buffer);
               if (bytes>0) {
                   //ada data dari client!
                   
                   String tempS = new String(buffer);
                   strData = tempS;
                   //tampilkan ke textview, harus dengan post 
                   //karena ini thread yg terpisah dengan thread UI
     tvHasil.post(new Runnable() {
                       public void run() {
                           tvHasil.setText(strData);
                       }
                   });
               }
           } catch (IOException e) {
               Log.e("ywlog",e.getMessage());
               e.printStackTrace();
               break;
           }
       }
   }

   
   /* Menulis ke server (string) */
   public void write(String data) {
       //konversi string ke stream
       try {
           mmOutStream.write(data.getBytes());
       } catch (IOException e) {
          e.printStackTrace();
          Log.e("ywlog",e.getMessage());
       }
   }


   /* matikan connection */
   public void cancel() {
       try {
           mmSocket.close();
       } catch (IOException e) {
           Log.e("ywlog",e.getMessage());
           e.printStackTrace();
       }
   }
}


//digunakan baik oleh server maupun client
private void manageConnectedSocket(BluetoothSocket socket) {
   //socket terhubung, mulai terima bagi server dan kirim data bagi client
   ct = new ConnectedThread(socket);
   ct.start();
}

Sekarang kita akan membuat bagian client. Untuk client, user melakukan discovery jika server belum di-pair. Lalu memilih server dari ListView. Jika sudah terhubung. User mentap button untuk mengirim data.

Di onCreate tambahkan code untuk Listview. Jika ditap maka thread client akan dijalankan dengan parameter BlueTooth device server. Thread ini berfungsi menghubungi server.

//siapkan onclik pada listview
//artinya client menghubungi server
lvServer = (ListView) findViewById(R.id.listView);
lvServer.setClickable(true);
lvServer.setOnItemClickListener(new AdapterView.OnItemClickListener() {
   @Override
   public void onItemClick(AdapterView<?>; arg0, 
                           View arg1, int position, long arg3) {
       BluetoothDevice devicePilih = arrayPairedDevices.get(position);
        //devicePilih berisi server yang dipilih di listview
        client(devicePilih); 
   }
});

Code untuk client adalah sebagai berikut. Buat kelas ConnectThread yang juga diletakkan di kelas MainActivity.

/*
   thread untuk client

*/
private class ConnectThread extends Thread {
   private BluetoothSocket mmSocket;
   private BluetoothDevice mmDevice;

   //bluetoothdevice didapat dari proses device discovery atau dari daftar
   public ConnectThread(BluetoothDevice device) {
       mmDevice = device;
        //ambil socket
       try {
          mmSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
       } catch (IOException e) {
           Log.e("ywlog",e.getMessage());
       }
   }

   public void run() {
       //Jika discovery sedang jalan, batalkan karena memperlambat koneksi
       mBluetoothAdapter.cancelDiscovery();
       try {
           //terhubung ke server
           mmSocket.connect();
       } catch (IOException connectException) {
           try {
               mmSocket.close();
           } catch (IOException e) {
              Log.e("ywlog",e.getMessage());
              e.printStackTrace();
           }
           return;
       }

       //terhubung, tangani kirim data
       manageConnectedSocket(mmSocket);
   }

   /* batalkan koneksi  */
   public void cancel() {
       try {
           mmSocket.close();
       } catch (IOException e) {
           Log.e("ywlog",e.getMessage());
           e.printStackTrace();
       }
   }
}

//thread dipanggil saat user mengklik listview, passing device
public void client(BluetoothDevice device) {
   //start thread client
   (new ConnectThread(device)).start();
}

Terakhir, jika sudah terhubung, user akan mengirimkan data melalui ConnectThread , tambahkan button “kirim data”. Lalu berikut aksinya:

public void klikKirimData(View v) {
   ct.write("Halo dari client!");
}

Jika user menakan tombol ini, maka textview di server akan berisi “Halo dari client”. Di saat yang bersamaan, anda juga bisa menjadikan client menjadi server dengan menekan tombol “Enable Server”, lalu gantian tekan tombol kirim data di server.

Source code tutorial 1 sd 3 dapat diambil di: https://github.com/yudiwbs/CobaBluetooth

27 comments on “Membuat App Bluetooth di Android (3): Komunikasi Antar Devices

  1. maaf pak.
    mau tanya
    saya pingin membuat satu aplikasi android yang dapat terkoneksi dengan bluetooth modul HC-06
    apakah ada cara lain yang lebih simpel.?
    sedangkan untuk cara yang di atas kan terlalu sulit buat saya pak.
    terima kasih mohon balasanya..

  2. makasi pak balasanya.
    kalau pakai app inventor. kurang asik pak soalnya tidak tau lis secara detail programnya.
    🙂
    kalau boleh tau bapak admin seorang dosen ya.?

  3. hehe ia pak.
    tutorial bapak dari 1 sampai 2 saya sudah coba.
    tidak ada kendala. tapi
    pas saya coba lanjutkan
    ada masalah saat button client kirim data di pres aplikasi tiba tiba keluar dengan sendirinya.
    mohon bantuanya pak 🙂

  4. tutorial bapa bagus cepet di mengerti pak.
    public UUID MY_UUID=UUID.fromString(“eb5a63b9-a32b-4ca9-896c-7204f3bfc55b”);
    UUID ini diambil dari salah satu Hp ya pak..?

  5. Jujur saja pak
    saya sedang membuat aplikasi android yang dapat berkomunikasi dengan Bluetooth HC-06 pak.
    untuk tugas kuliah.. 🙂

  6. terimakasi pak tutorialnya
    sudah beberapa jam
    akirnya selesai.
    dan dapat terkoneksi dengan alat saya.

  7. Tutorialnya the best pak..
    Btw kalo mau bkin aplikasi berbasis client server jga tpi koneksinya pkek wifi (jaringan) itu gmna ya pak? Atw bpak ada referensi tutorialnya gtu? Mhon bngunny pak..

  8. untuk source code nya kalau digunakan di arduino butuh libraries apa ya pak ? mohon pencerahannya

    • belum pernah pake Arduino, kayaknya kalau OS di Arduinonnya bukan Android bakal susah. Tutorial ini paling bisa dipake untuk Android yg mengendalikan Arduinonya, sedangkan dari sisi Arduionya ya perlu cari yg lain.

  9. Selamat malam pak
    saya mau tanya
    bagai coding android studio untuk membuat
    suatu game dapat di mainkan dua device
    maksudnya game itu bisah di mainkan dua orang
    melalui bluetooth.
    dalam hal ini game catur

  10. permisi pak mau tanya..kalo untuk bluetooth versi 4.0 (Bluetooth Low Energy ) apa ada perubahan pada source code pak? terimakasih

      • ohhh begitu ya pak baik pak…
        Saya ada pertanyaan lagi pak…sampai sekarang saya masih kesulitan untuk melakukan getUUID dari devicenya pak…device yang saya gunakan ini genuino 101 (arduino) pak…

        tapi sudah bisa baca bluetooth dan mac addressnya pak..
        apa bapak ada saran mungkin pak?
        terimakasih pak

        • Sudah coba contoh code saya yg ada di github? (ada di bagian bawah posting), tapi mungkin karena arduino ya.

          • Contoh bapak sudah saya coba pak, saya tambahkan untuk menampilkan UUID dari devicenya tapi hasil outputnya jadi tetap null pak.

            kalo UUID dari smartphone lain terbaca pak, hanya saja dibaca sebagai ParcelUUID..

            mungkin bapak ada saran pak?
            terimakasih sebelumnya pak

  11. selamat malam pak… apakah bisa buat aplikasi android untuk memonitoring daata dari arduino .. misalnya monitorig arus tegangan aatupun data serial yang di compile di arduino?

    terimakasih pak

  12. pak nuwun sewu ada ndak tutorial njenengan untuk buat crud mysql sekalian print bluetooth nya
    terima kasih

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.