Connecting to Smart Gloves Using Bluetooth in Navigation Glove IoT application Using Kotlin - Part 5
Tags: android, kotlin, hms, huawei
Published: 2022-04-15 06:23:49

## Introduction

In this article, we will learn how to connect smart gloves from the **paired devices**. The process is in the smart gloves application. Smart glove application shows all the paired **Bluetooth devices**. User has to select the gloves and connect to Bluetooth device.

If you are new to the series of articles, follow articles.

[Beginner: Integration of Huawei Account kit in Navigation Glove IoT application Using Kotlin - Part 1](https://forums.developer.huawei.com/forumPortal/en/topic/0202805462085750190)

[Beginner: Integration of Huawei Map kit in Navigation Glove IoT application Using Kotlin - Part 2](https://forums.developer.huawei.com/forumPortal/en/topic/0202805594751950193?fid=0101187876626530001)

[Beginner: Integration of Huawei Site kit in Navigation Glove IoT application Using Kotlin - Part 3](https://forums.developer.huawei.com/forumPortal/en/topic/0202811614337950015)

[Beginner: Integration of Huawei Direction API in Navigation Glove IoT application Using Kotlin - Part 4](https://forums.developer.huawei.com/forumPortal/en/topic/0201811666900720021)

In this article, we learn how to display all the paired device in the application. We will also learn how to integrate the Recyclerview in android. Make sure device is already paired to phone.

Note: Application is built in androidx if you are developing application in the older than androidx you need to add the recyclerview dependencies.

Add the following permission in **AndroidManifest.xml**


```
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
```

Follow the steps

Step 1: Add the recyclerview in the **activity_connect_smart_gloves.xml**

```
<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_above="@+id/pairedDeviceBtn"
    android:layout_below="@id/messageTv"
    tools:listitem="@layout/paired_device_list_item"/>
```

Step 2: If you want to display items let us create one xml file.

**paired_device_list_item.xml**


```
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="80dp"
    android:layout_margin="10dp"
    app:cardElevation="6dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:gravity="center|start"
        android:orientation="horizontal"
        android:padding="5dp"
        android:id="@+id/rootLayout">

        <ImageView
            android:id="@+id/imageview"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_marginStart="5dp"
            android:src="@drawable/gloves_ic"
            android:visibility="visible" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginStart="5dp"
            android:orientation="vertical">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_weight="1"
                android:gravity="center|start"
                android:orientation="horizontal">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="10dp"
                    android:layout_marginLeft="15dp"
                    android:text="@string/name"
                    android:textSize="16sp"
                    android:textStyle="bold" />

                <TextView
                    android:id="@+id/deviceName"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="10dp"
                    android:layout_marginLeft="15dp"
                    android:textSize="16sp"
                    android:textStyle="bold" />
            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_weight="1"
                android:gravity="center|start"
                android:orientation="horizontal">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="10dp"
                    android:layout_marginLeft="15dp"
                    android:text="@string/mac_address"
                    android:textSize="16sp"
                    android:textStyle="bold" />

                <TextView
                    android:id="@+id/macAddress"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="10dp"
                    android:layout_marginLeft="15dp"
                    android:textSize="16sp"
                    android:textStyle="bold" />
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>

</androidx.cardview.widget.CardView>
```

Step 3: Create data class for device model (DeviceModel.kt)

```
package com.huawei.navigationglove.model

data class DeviceModel(val name: String, val macAddress: String)
```

Step 4: declare layout manager in activity.


```
private lateinit var linearLayoutManager: LinearLayoutManager
```

Step 5: Declare the device model variable and the paired device list.

```
private var pairedDeviceList = ArrayList<DeviceModel>()
var deviceModel: DeviceModel? = null
```

Step 6: Initialize the layout manager and set it to recyclerview in onCreate().

```
linearLayoutManager = LinearLayoutManager(this)
recyclerView.layoutManager = linearLayoutManager
```

Step 7: Now create **PairedDeviceListAdapter.kt** for recycler view.

```
package com.huawei.navigationglove.ui.adapters

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.huawei.navigationglove.R
import com.huawei.navigationglove.callbacks.OnDeviceClickCallback
import com.huawei.navigationglove.model.DeviceModel

class PairedDevicesAdapter(
    private val mList: List<DeviceModel>,
    private val onDeviceClickCallback: OnDeviceClickCallback
) :
    RecyclerView.Adapter<PairedDevicesAdapter.ViewHolder>() {

    // create new views
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.paired_device_list_item, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val deviceModel = mList[position]
        holder.deviceName.text = deviceModel.name
        holder.macAddress.text = deviceModel.macAddress
        holder.rootLayout.setOnClickListener { onDeviceClickCallback.onDeviceClick(deviceModel) }
    }

    // return the number of the items in the list
    override fun getItemCount(): Int {
        return mList.size
    }

    // Holds the views for adding it to image and text
    class ViewHolder(ItemView: View) : RecyclerView.ViewHolder(ItemView) {
        val deviceName: TextView = itemView.findViewById(R.id.deviceName)
        val macAddress: TextView = itemView.findViewById(R.id.macAddress)
        val rootLayout: LinearLayout = itemView.findViewById(R.id.rootLayout)
    }
}
```

Step 8: Now get all the paired devices, and set the list of devices to adapter.

```
private fun pairedDevicesList() {
    pairedDeviceList = ArrayList<DeviceModel>()
    pairedDevices = myBluetooth!!.bondedDevices
    val list: ArrayList<String> = ArrayList<String>()
    if ((pairedDevices as MutableSet<BluetoothDevice>?)!!.size > 0) {
        for (bt in (pairedDevices as MutableSet<BluetoothDevice>?)!!) {
            Log.e(TAG, bt.name + "\n" + bt.address)
            list.add(bt.name + "\n" + bt.address) //Get the device's name and the address
            deviceModel = DeviceModel(bt.name, bt.address)
            pairedDeviceList.add(deviceModel!!)
        }
        val adapter = PairedDevicesAdapter(pairedDeviceList, this)
        recyclerView.adapter = adapter
    } else {
        Toast.makeText(
            applicationContext,
            "No Paired Bluetooth Devices Found.",
            Toast.LENGTH_LONG
        ).show()
    }
}
```

Step 9: By now recyclerview will show the list of paired devices. Now when user clicks on the device it has to connect. So now lets create onclick for recyclerview. To do that we will do it using interface callback.

```
Create OnDeviceClickCallback.kt interface.


package com.huawei.navigationglove.callbacks

import com.huawei.navigationglove.model.DeviceModel
interface OnDeviceClickCallback {
fun onDeviceClick(deviceModel: DeviceModel)
}
```

Step 9: Implement this interface in activity.

```
class ConnectSmartGlovesActivity : AppCompatActivity(), OnDeviceClickCallback {
```
Now override the function.

```
override fun onDeviceClick(deviceModel: DeviceModel) {
address = deviceModel.macAddress
ConnectBT(this).execute()
}
```

Step 10: Now create following variables.

```
private var progress: ProgressDialog? =null //This progress dialog box while connecting to bluetooth
private var isBtConnected = false
var btSocket: BluetoothSocket? = null //Bridge which sends data to bluetooth from Android app
var myBluetooth: BluetoothAdapter? = null
val myUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB") //Unique
var address: String? = null
```

Step: 11: Create Async class for connecting.

//This class contains functions that need to be done to connect to the HC-05 module

```
open class ConnectBT(val context: Context) : AsyncTask<Void?, Void?, Void?>() // UI thread
{
    private var ConnectSuccess = true //if it's here, it's almost connected
    override fun onPreExecute() {
        progress = ProgressDialog.show(
            context,
            "Connecting...",
            "Please wait!!!"
        ) //show a progress dialog
    }


    @SuppressLint("MissingPermission")
    override fun doInBackground(vararg devices: Void?): Void? //while the progress dialog is shown, the connection is done in background
    {
        try {
            if (btSocket == null || !isBtConnected) {
                myBluetooth =
                    BluetoothAdapter.getDefaultAdapter() //get the mobile bluetooth device
                val dispositivo: BluetoothDevice = myBluetooth!!.getRemoteDevice(address) //connects to the device's address and checks if it's available
                Log.e(TAG,"Device: "+Gson().toJson(dispositivo))
                btSocket = dispositivo.createInsecureRfcommSocketToServiceRecord(myUUID) //create a RFCOMM (SPP) connection
                Log.e(TAG,"Device: "+Gson().toJson(btSocket))
                BluetoothAdapter.getDefaultAdapter().cancelDiscovery()
                btSocket!!.connect() //start connection
            }
        } catch (e: IOException) {
            ConnectSuccess = false //if the try failed, you can check the exception here
            Log.e("MapsActivity","Device not connected" +e.message)
        }
        return null
    }

    override fun onPostExecute(result: Void?) //after the doInBackground, it checks if everything went fine
    {
        super.onPostExecute(result)
        if (!ConnectSuccess) {
            val toast =
                Toast.makeText(context, "Failure", Toast.LENGTH_LONG)
            toast.show()
            val handler = Handler()
            handler.postDelayed({ toast.cancel() }, 300)
            //TODO need to check this
            //finish()
        } else {
            val toast = Toast.makeText(context, "Success.", Toast.LENGTH_LONG)
            toast.show()
            val handler = Handler()
            handler.postDelayed({ toast.cancel() }, 300)

            //msg("Connected.");
            SystemClock.sleep(1000)
            isBtConnected = true
        }
        progress!!.dismiss()
    }
}
```

Step 12: To get the connection and disconnection state create register broadcast receiver in onCreate().

```
val filter = IntentFilter()
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED)
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED)
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED)
this.registerReceiver(nReceiver, filter)
```

Step 13: Create broadcast receiver.

```
//This BroadcastReceiver finds listens the status of bluetooth
private val nReceiver: BroadcastReceiver? = object : BroadcastReceiver() {
    @RequiresApi(Build.VERSION_CODES.M)
    override fun onReceive(context: Context, intent: Intent) {
        val action = intent.action
        val device = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)
        if (BluetoothDevice.ACTION_FOUND == action) {
        } else if (BluetoothDevice.ACTION_ACL_CONNECTED == action) {
            co = true
            Log.e("mode:", "Connected")
            requestLocationUpdatesWithCallback()
        } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED == action) {
        } else if (BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED == action) {
            Log.e("mode:", "disConnected")
        } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED == action) {
            co = false
            Log.e("mode:", "disConnected1")
            val vib = context.getSystemService(Vibrator::class.java)
            Log.e("Vibe", "" + vib.hasVibrator())
            //t1.speak("Your Bluetooth Has Been Disconnected", TextToSpeech.QUEUE_FLUSH, null);
            for (i in 0..4) {
                vib.vibrate(700)
                SystemClock.sleep(1000)
            }
            i = 0
        }
    }
}
```

## Result

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ezy7q8zzx2qyn2c00xid.png)
 

## Tips and Tricks

1. Make sure you have added Bluetooth permission in **AndroidManifest.xml**

2. Make sure you phone **Bluetooth is enabled**.

3. If you are building application below androidx, Make sure you have added the recyclerview dependency in build.gradle file.

## Conclusion

In this article, we have learnt how to use recyclerview in the android application along with that we have displayed the list of paired devices in the smart gloves application. And also we have learnt how to connect device from the smart gloves application.

## Reference

[Bluetooth Official document](https://developer.android.com/guide/topics/connectivity/bluetooth/connect-bluetooth-devices)

[Recyclerview Document](https://developer.android.com/guide/topics/ui/layout/recyclerview)