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>
Сергей привет, спасибо за работу. Как можно тебе или где задать вопросы по данной серии уроков?
Спасибо большое тебе Сергей! Жаль что этот курс был мене интересен публике, но оно очень помогло мне с научным проектом, которое нуждалось в таком приложении(на базе этого приложения). Нигде не мог найти нормальные обучающие видео по android+arduino на русском языке. Ещё раз благодарю за твой труд. Обязательно пересмотрю твои другие уроки.