2017-10-17 29 views
1

Je suis en train de créer une application qui scanne et se connecte aux périphériques Bluetooth. J'affiche les périphériques dans un RecyclerView et indique l'état de liaison en coloriant le ViewHolder pour ce périphérique. mon problème est que la couleur du ViewHolder est seulement changé après la recherche de nouveaux périphériques et je veux qu'il mette immédiatement à jour la couleur sur la paire ou l'unpair. J'essaye de faire ceci en employant un récepteur de diffusion mais je suis incapable d'obtenir une référence au ViewHolder correct. Comment puis-je atteindre cet objectif? J'inclus mon code ci-dessous pour mon RecyclerView.Adapter et mon fichier BluetoothUtils contenant le récepteur de diffusion. Merci d'avance. mon adaptateur:comment définir la couleur de RecyclerView.ViewHolder dans BroadcastReceiver.onReceive?

class DeviceAdapter(val mContext : Context) : RecyclerView.Adapter<DeviceAdapter.DeviceHolder>() { 

companion object { 
    val TAG = "Device Adapter" 

    fun DeviceHolder.setColor(bonded: Boolean):Unit{ 
     val background = if (bonded)Color.CYAN else Color.TRANSPARENT 
     this.itemView.setBackgroundColor(background) 
    } 

} 

val mDevices = ArrayList<BluetoothDevice>() 

fun updateItems(list: ArrayList<BluetoothDevice>) { 
    mDevices.clear() 
    mDevices.addAll(list) 
    Log.d(TAG, "updating items : $mDevices") 
    notifyDataSetChanged() 
} 

fun ViewGroup.inflate(@LayoutRes res: Int, attachToRoot: Boolean = false): View { 
    return LayoutInflater.from(mContext).inflate(res, this, attachToRoot) 
} 

override fun onBindViewHolder(holder: DeviceHolder, position: Int) { 
    Log.d(TAG, "onBindViewHolder called!") 
    holder.bindItems(mDevices.get(position)) 
    if (mDevices.get(position).bondState==BluetoothDevice.BOND_BONDED) { 
     holder.itemView.setBackgroundColor(CYAN) 
    } else { 
     holder.itemView.setBackgroundColor(Color.TRANSPARENT) 
    } 
} 

override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): DeviceAdapter.DeviceHolder { 
    Log.d(TAG, "onCreateViewHolder called!") 
    val v = parent!!.inflate(R.layout.device_item, false) 
    return DeviceHolder(v) 
} 

override fun getItemCount(): Int { 
    return mDevices.size 
} 

inner class DeviceHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { 

    val nameView = itemView.findViewById(R.id.nameView) as TextView 
    val addrView = itemView.findViewById(R.id.addressView) as TextView 
    var dialog: AlertDialog? = null; 

    fun bindItems(btDevice: BluetoothDevice) { 
     Log.d(TAG, "holder created!") 
     nameView.text = btDevice.name ?: "Unknown" 
     addrView.text = btDevice.address 
     itemView.setOnClickListener { 
      dialog = AlertDialog.Builder(it.context) 
        .setTitle("Options") 
        .setView(R.layout.options_dialog_layout) 
        .setNegativeButton("Cancel", DialogInterface.OnClickListener { _, which -> }) 
        .create() 
      dialog!!.show() 
      val ops = listOf(
        dialog!!.findViewById(R.id.statOp), 
        dialog!!.findViewById(R.id.pairOp), 
        dialog!!.findViewById(R.id.connectOp), 
        dialog!!.findViewById(R.id.sendOp), 
        dialog!!.findViewById(R.id.unPairOp) 
      ) 
      ops.forEach { it.setOnClickListener { 
       Toast.makeText(it.context, it.id.toString(), Toast.LENGTH_SHORT).show() 
       when(it.id){ 
        R.id.statOp -> {} 
        R.id.connectOp -> { 
         Log.d(TAG, "connectOp reached") 
         BluetoothReflection.connectDevice(btDevice) 
         dialog!!.dismiss() 
        }// BluetoothUtils.connect(BluetoothAdapter.getDefaultAdapter(), btDevice) 
        R.id.pairOp -> { 
         Log.d(TAG, "pairOp reached") 
         BluetoothUtils.startPair(BluetoothAdapter.getDefaultAdapter(), btDevice) 
         if (btDevice.bondState==BluetoothDevice.BOND_BONDED){ 
          [email protected](CYAN) //doesn't work 
         } 
         Log.d(TAG, "start pair complete") 
         dialog!!.dismiss() 
        }// 
        R.id.unPairOp -> {//no executable code found here 
         Log.d(TAG, "unPairOp reached") 
         BluetoothUtils.unPair(btDevice) 
         if (btDevice.bondState==BluetoothDevice.BOND_NONE){ 
          [email protected](Color.TRANSPARENT) //doesn't work 
         } 
         Log.d(TAG, "unpair complete") 
         dialog!!.dismiss() 
        } 
        R.id.sendOp -> {} 
       } 
      } } 
     } 

    } 
} 
} 

et mes BluetoothUtils:

class BluetoothUtils { 

companion object { 

    var listener: ListenThread? = null 

    val _UUID = UUID.fromString("a0e7e4c7-0e4e-43b7-9d18-659192512164") 
    val TAG = "BluetoothUtils" 

    val receiver = MainBTStatusReceiver() 

    fun initPairingServer(adapter: BluetoothAdapter){ 
     var mmServerSocket: BluetoothServerSocket? 
     try { 
      var tmp = adapter.listenUsingRfcommWithServiceRecord(TAG, _UUID) 
      mmServerSocket = tmp 
      listener = ListenThread(mmServerSocket) 
      listener!!.start() 
     }catch (ioe: IOException){ 
      Log.e(TAG, "Error initializing Bluetooth", ioe) 
     } 
    } 

    fun cancelListener() = listener!!.cancel() 

    fun connect(adapter: BluetoothAdapter, device: BluetoothDevice){ 
     var btSocket: BluetoothSocket? 

     try { 
      adapter.cancelDiscovery() 
      btSocket = device.createRfcommSocketToServiceRecord(_UUID) 
      PairingThread(btSocket).start() 
     }catch (ioe: IOException){ 
      Log.e(TAG, "error connecting", ioe) 
     } 
    } 

    fun startPair(adapter: BluetoothAdapter, device: BluetoothDevice): Unit{ 
     adapter.cancelDiscovery() 
     Log.d(TAG, device.bondState.toString()) 
     device.createBond() 
    } 

    fun unPair(device: BluetoothDevice): Any = device::class.java.getMethod("removeBond").invoke(device) 

} 
} 

class ListenThread(val btServSock: BluetoothServerSocket) : Thread(){ 

companion object { 
    val TAG = "ListenThread" 
} 

var btSocket: BluetoothSocket? = null 

override fun run() { 
    super.run() 
    while (true){ 
     try { 
      Log.d(TAG, "listening . . . ") 
      btSocket = btServSock.accept() 
     }catch (ioe: IOException){ 
      Log.e(TAG, "Error", ioe) // SHOULD HANDLE FAILURE OF LISTENER INSTANTIATION 
      break 
     } 

     //manage connection here 
     //with either BluetoothUtils function 
     //or BluetoothSocket extension 
    } 
} 

fun cancel() = btServSock.close() 
} 

class PairingThread(val btSocket: BluetoothSocket) : Thread(){ 

companion object { 
    val TAG = "Pairing Thread" 
} 

override fun run() { 
    super.run() 

    try { 
     Log.d(TAG, "attempting to connect") 
     btSocket.connect() 
    }catch (ioe: IOException){ 
     Log.e(TAG, "error connecting", ioe) 
     btSocket.close() 
    } 
} 
} 


class MainBTStatusReceiver(): BroadcastReceiver(){ 

val TAG = "MainBTStatusReceiver" 
var mAdapter: DeviceAdapter? = null 

fun setAdapter(adapter: DeviceAdapter){ 
    mAdapter = adapter 
} 

override fun onReceive(context: Context?, intent: Intent) { 
    val action = intent.action 
    val devExtra = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE) as BluetoothDevice 
    when(action){ 
     BluetoothDevice.ACTION_BOND_STATE_CHANGED -> { 
      val device = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE) 
      when(device.bondState){ 
       BluetoothDevice.BOND_BONDED -> { 

        Log.d(TAG, "BONDED") 
       } 
       BluetoothDevice.BOND_BONDING -> {Log.d(TAG, "BONDING")} 
       BluetoothDevice.BOND_NONE -> {Log.d(TAG, "NONE")} 
      } 
     } 
    } 
} 

Répondre

1

Ajouter boolean ou int à BluetoothDevice modèle de gestion de vue.

Par exemple,

BluetoothDevice: ajouté isOn état. (Désolé, il est Java)

class BluetoothDevice { 
    boolean isOn; 

    public boolean isOn() { 
     return isOn; 
    } 

    public void setOn(boolean isOn) { 
     this.isOn = isOn; 
    } 
} 

DeviceHolder: changé de couleur de vue

fun bindItems(btDevice: BluetoothDevice) { 
    stateView.textColor = btDevice.isOn() ? Color.RED : Color.GREEN 
} 

DeviceAdapter: ajouté getItems

fun getItems() { 
    return mDevices 
} 

Si vous voulez changer isOn état, modèle de changement et notifier .

adapter.getItems().get(i).setOn(true); 
adapter.notifyDataSetChanged(); 
0

J'aime la réponse ci-dessus aussi bien, mais la façon dont je suis arrivé ce fait était de passer le BroadcastReceiver dans le DeviceAdapter:

class DeviceAdapter(val mContext:Context, val mReceiver:MainBTStatusReceiver) : RecyclerView.Adapter<DeviceAdapter.DeviceHolder>() 

et a ensuite fait un ViewHolder membre du BroadcastReceiver et fonction setter pour le ViewHolder nommé setFocus. Avant d'appeler des fonctions de la classe BluetoothUtils, j'ai appelé la fonction setFocus, puis le récepteur de diffusion modifie la couleur de la vue qui est actuellement définie. Je crains que cela ne soit pas la méthode la plus précise pour modifier le ViewHolder correct à chaque fois. Si vous voyez un problème avec ceci, merci de me le faire savoir.

mon BroadcastReceiver mise à jour:

class MainBTStatusReceiver(): BroadcastReceiver() { 

val TAG = "MainBTStatusReceiver" 
var holder: DeviceAdapter.DeviceHolder? = null 

fun setFocus(holder: DeviceAdapter.DeviceHolder) { 
    this.holder = holder 
} 

override fun onReceive(context: Context?, intent: Intent) { 
    val action = intent.action 
    when (action) { 
     BluetoothDevice.ACTION_BOND_STATE_CHANGED -> { 
      val device = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE) 
      when (device.bondState) { 
       BluetoothDevice.BOND_BONDED -> { 
        holder!!.itemView.setBackgroundColor(Color.CYAN) 
        Log.d(TAG, "BONDED") 
       } 
       BluetoothDevice.BOND_BONDING -> { 
        Log.d(TAG, "BONDING") 
       } 
       BluetoothDevice.BOND_NONE -> { 
        holder!!.itemView.setBackgroundColor(Color.TRANSPARENT) 
        Log.d(TAG, "NONE") 
       } 
      } 
     } 
    } 
} 
} 

et les deux déclarations dans mon expression qui appellent quand setFocus():

   R.id.pairOp -> { 
         Log.d(TAG, "pairOp reached") 
         mReceiver.setFocus([email protected]) 
         BluetoothUtils.startPair(BluetoothAdapter.getDefaultAdapter(), btDevice) 
         Log.d(TAG, "start pair complete") 
         dialog!!.dismiss() 
        } 
        R.id.unPairOp -> { 
         Log.d(TAG, "unPairOp reached") 
         mReceiver.setFocus([email protected]) 
         BluetoothUtils.unPair(btDevice) 
         Log.d(TAG, "unpair complete") 
         dialog!!.dismiss() 
        }