Я хочу, чтобы все устройства Bluetooth отображались в режиме переработчика. Поэтому я должен обновить свое представление программы перезапуска, если в onReceive было обнаружено соседнее устройство.
Я написал DeviceListAdapter и класс, чтобы определить мое устройство Bluetooth в одном файле.
class BluetoothItem internal constructor(_uuid:String, _macAddress: String){
internal var bluetoothUuid:String? = _uuid
internal var bluetoothMacAddress:String? = _macAddress
}
// Class to handle RecyclerView
class DeviceListAdapter internal constructor(_itemList:ArrayList<BluetoothItem>): RecyclerView.Adapter<RecyclerView.ViewHolder>(){
private var itemList:ArrayList<BluetoothItem> = _itemList
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view: View = LayoutInflater.from(parent.context).inflate(R.layout.item_devices, parent, false)
return ViewHolder(view)
}
override fun getItemCount(): Int {
return if(itemList == null) 0 else itemList!!.size
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
initLayout(holder as ViewHolder, position)
}
private fun initLayout(holder:ViewHolder, pos:Int){
holder.deviceName.text = itemList!![pos].bluetoothMacAddress
}
internal class ViewHolder(itemView:View):RecyclerView.ViewHolder(itemView){
var deviceName:TextView = itemView.device as TextView
}
}
My Деятельность выглядит следующим образом:
class PrinterActivity: AppCompatActivity() {
private val blueAdapter = BluetoothAdapter.getDefaultAdapter()
private var itemList = ArrayList<BluetoothItem>()
private var itemArrayAdapter = DeviceListAdapter(itemList)
private val layoutMng = LinearLayoutManager(this)
// ############################ Activity ################################
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_printer)
// prepare the recyclerview and assign the arrayAdapter to the recyclerview
device_list!!.layoutManager = layoutMng
device_list!!.itemAnimator = DefaultItemAnimator()
device_list!!.adapter = itemArrayAdapter
if (blueAdapter!!.isDiscovering) {
blueAdapter.cancelDiscovery()
blueAdapter.startDiscovery()
val deviceIntent = IntentFilter(BluetoothDevice.ACTION_FOUND)
registerReceiver(mBroadcastRec, deviceIntent)
}
if (!blueAdapter.isDiscovering) {
blueAdapter.startDiscovery()
val deviceIntent = IntentFilter(BluetoothDevice.ACTION_FOUND)
registerReceiver(mBroadcastRec, deviceIntent)
}
}
// ########################## Functions ##############################
override fun onDestroy() {
super.onDestroy()
//destroy receiver
unregisterReceiver(mBroadcastRec)
}
// ########################## Broadcaster ##############################
private val mBroadcastRec: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val action = intent.action
// When discovery finds a device
if (action == BluetoothDevice.ACTION_FOUND) {
val device: BluetoothDevice? = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
// update
if (device != null && device_list.adapter != null) {
itemList.add(BluetoothItem(device.name, device.address))
device_list.adapter!!.notifyDataSetChanged()
}
}
}
}
}
Мой 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">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/device_list"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Я видел в переполнении стека, что я должен уведомить свой адаптер с помощью notifyDataSetChanged ( ) Но я получаю исключение RuntimeException в приемнике.
Я не знаю, почему или что изменить. Ошибка возникает:
itemList.add(BluetoothItem(device.name, device.address))
со следующим исключением:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.driverapppro, PID: 10044
java.lang.RuntimeException: Error receiving broadcast Intent { act=android.bluetooth.device.action.FOUND flg=0x10 pkg=com.example.driverapppro (has extras) } in com.example.driverapppro.PrinterActivity$mBroadcastRec$1@f95681a
at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0$LoadedApk$ReceiverDispatcher$Args(LoadedApk.java:1566)
at android.app.-$$Lambda$LoadedApk$ReceiverDispatcher$Args$_BumDX2UKsnxLVrE6UJsJZkotuA.run(Unknown Source:2)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7520)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
Caused by: java.lang.IllegalStateException: device.name must not be null
at com.example.driverapppro.PrinterActivity$mBroadcastRec$1.onReceive(PrinterActivity.kt:62)
at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0$LoadedApk$ReceiverDispatcher$Args(LoadedApk.java:1556)
Спасибо за вашу помощь, ребята .. Я пытался найти ответ в разных темах при переполнении стека, но Я не могу это исправить. Может быть, у вас, ребята, есть идея.
Лучший