BtMonitor Kotlin | #5

ControlActivity

import android.bluetooth.BluetoothManager
import android.content.Context
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import com.neco_desarrollo.btmonitorkotlin.databinding.ActivityControlBinding

class ControlActivity : AppCompatActivity() {
private lateinit var binding: ActivityControlBinding
private lateinit var actListLauncher: ActivityResultLauncher<Intent>
lateinit var btConnection: BtConnection
private var listItem: ListItem? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityControlBinding.inflate(layoutInflater)
setContentView(binding.root)
onBtListResult()
init()
binding.apply {
bA.setOnClickListener {
btConnection.sendMessage("A")
}
bB.setOnClickListener {
btConnection.sendMessage("B")
}
}

}

private fun init(){
val btManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
val btAdapter = btManager.adapter
btConnection = BtConnection(btAdapter)
}

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.control_menu, menu)
return super.onCreateOptionsMenu(menu)
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
if(item.itemId == R.id.id_list){
actListLauncher.launch(Intent(this, BtListActivity::class.java))
} else if(item.itemId == R.id.id_connect){
listItem.let {
btConnection.connect(it?.mac!!)
}
}
return super.onOptionsItemSelected(item)
}

private fun onBtListResult(){
actListLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()){
if(it.resultCode == RESULT_OK){
listItem = it.data?.getSerializableExtra(BtListActivity.DEVICE_KEY) as ListItem
}
}
}
}

BtListActivity

import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothManager
import android.content.Context
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.recyclerview.widget.LinearLayoutManager
import com.neco_desarrollo.btmonitorkotlin.databinding.ActivityMainBinding

class BtListActivity : AppCompatActivity(), RcAdapter.Listener {
private var btAdapter: BluetoothAdapter? = null
private lateinit var binding: ActivityMainBinding
private lateinit var adapter: RcAdapter

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
init()
}

private fun init(){
val btManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
btAdapter = btManager.adapter
adapter = RcAdapter(this)
binding.rcView.layoutManager = LinearLayoutManager(this)
binding.rcView.adapter = adapter
getPairedDevises()
}

private fun getPairedDevises(){
val pairedDevices: Set<BluetoothDevice>? = btAdapter?.bondedDevices
val tempList = ArrayList<ListItem>()
pairedDevices?.forEach {
tempList.add(ListItem(it.name, it.address))
}
adapter.submitList(tempList)
}

companion object{
const val DEVICE_KEY = "device_key"
}

override fun onClick(item: ListItem) {
val i= Intent().apply {
putExtra(DEVICE_KEY, item)
}
setResult(RESULT_OK, i)
finish()
}
}

BtConnection

import android.bluetooth.BluetoothAdapter

class BtConnection(private val adapter: BluetoothAdapter) {
lateinit var cThread: ConnectThread
fun connect(mac: String) {
if (adapter.isEnabled && mac.isNotEmpty()) {
val device = adapter.getRemoteDevice(mac)
device.let {
cThread = ConnectThread(it)
cThread.start()
}
}
}
fun sendMessage(message: String){
cThread.rThread.sendMessage(message.toByteArray())
}

}

ConnectThread

import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothSocket
import android.util.Log
import java.io.IOException
import java.util.*

class ConnectThread(private val device: BluetoothDevice) : Thread() {
val uuid = "00001101-0000-1000-8000-00805F9B34FB"
var mSocket: BluetoothSocket? = null
lateinit var rThread: ReceiveThread

init {
try {
mSocket = device.createRfcommSocketToServiceRecord(UUID.fromString(uuid))
}catch (i: IOException){

}
}

override fun run() {
try {
Log.d("MyLog","Connecting...")
mSocket?.connect()
Log.d("MyLog","Connected")
rThread = ReceiveThread(mSocket!!)
rThread.start()
}catch (i: IOException){
Log.d("MyLog","Can not connect to device")
closeConnection()
}
}

fun closeConnection(){
try {
mSocket?.close()
}catch (i: IOException){

}
}
}

ListItem

import java.io.Serializable

data class ListItem(
var name: String,
var mac: String
): Serializable

RcAdapter

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.neco_desarrollo.btmonitorkotlin.databinding.ListItemBinding


class RcAdapter(private val listener: Listener) : ListAdapter<ListItem, RcAdapter.ItemHolder>(ItemComparator()) {

class ItemHolder(view: View) : RecyclerView.ViewHolder(view){
val binding = ListItemBinding.bind(view)

fun setData(item: ListItem, listener: Listener) = with(binding){
tvName.text = item.name
tvMac.text = item.mac
itemView.setOnClickListener {
listener.onClick(item)
}
}
companion object{
fun create(parent: ViewGroup): ItemHolder{
return ItemHolder(LayoutInflater.
from(parent.context).
inflate(R.layout.list_item, parent, false))
}
}
}

class ItemComparator : DiffUtil.ItemCallback<ListItem>(){
override fun areItemsTheSame(oldItem: ListItem, newItem: ListItem): Boolean {
return oldItem.mac == newItem.mac
}

override fun areContentsTheSame(oldItem: ListItem, newItem: ListItem): Boolean {
return oldItem == newItem
}

}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemHolder {
return ItemHolder.create(parent)
}

override fun onBindViewHolder(holder: ItemHolder, position: Int) {
holder.setData(getItem(position), listener)
}

interface Listener{
fun onClick(item: ListItem)
}
}

ReceiveThread

import android.bluetooth.BluetoothSocket
import android.util.Log
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream

class ReceiveThread(val bSocket: BluetoothSocket) : Thread() {
var inStream: InputStream? = null
var outStream: OutputStream? = null
init {
try {
inStream = bSocket.inputStream
} catch (i: IOException){

}
try {
outStream = bSocket.outputStream
} catch (i: IOException){

}
}

override fun run() {
val buf = ByteArray(2)
while (true){
try{
val size = inStream?.read(buf)
val message = String(buf, 0, size!!)
Log.d("MyLog","Message: $message")
} catch (i: IOException){
break
}
}
}
fun sendMessage(byteArray: ByteArray){
try {
outStream?.write(byteArray)
} catch (i: IOException){

}
}
}

activity_control.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ControlActivity">

<Button
android:id="@+id/bB"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Send B"
app:layout_constraintBottom_toTopOf="@+id/bA"
app:layout_constraintEnd_toEndOf="@+id/bA"
app:layout_constraintStart_toStartOf="@+id/bA" />

<Button
android:id="@+id/bA"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:text="Send A"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#C8C6C6"
tools:context=".BtListActivity">

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rcView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="wrap_content">

<androidx.cardview.widget.CardView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="3dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="3dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

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

<TextView
android:id="@+id/tvName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView"
android:textColor="@color/black"
android:textStyle="bold" />

<TextView
android:id="@+id/tvMac"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView"
android:textSize="12sp" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>

control_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/id_connect"
android:title="Connect"
android:orderInCategory="100"
app:showAsAction="ifRoom"
android:icon="@drawable/ic_connect"
/>
<item
android:id="@+id/id_list"
android:title="Bt List"
android:orderInCategory="200"
app:showAsAction="ifRoom"
android:icon="@drawable/ic_list"
/>
</menu>

3 комментария для “BtMonitor Kotlin | #5”

  1. Спасибо большое тебе Сергей! Жаль что этот курс был мене интересен публике, но оно очень помогло мне с научным проектом, которое нуждалось в таком приложении(на базе этого приложения). Нигде не мог найти нормальные обучающие видео по android+arduino на русском языке. Ещё раз благодарю за твой труд. Обязательно пересмотрю твои другие уроки.

Добавить комментарий

Ваш адрес email не будет опубликован.