Android 監聽框架開發教程 藍牙狀態監聽例子 kotlin

前言

有些時候,我們需要在某些Activity中監聽某些狀態。當然不可能在每個Activity中創建一個實例去查詢和綁定吧。這時候,就需要一個統一管理狀態的框架,下面就以藍牙狀態監聽爲例,描述如何開發一個監聽框架。

文件架構

在這裏插入圖片描述

代碼

監聽者註解

創建文件 RDBluetoothObserver ,註解類,用於描述監聽者的方法

/**
 * 藍牙狀態觀察者註解
 *
 * @author D10NG
 * @date on 2019-11-12 09:25
 */
@kotlin.annotation.Target(AnnotationTarget.FUNCTION)
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
annotation class RDBluetoothObserver

狀態值枚舉類

創建文件 RDBluetoothStatus

/**
 * 藍牙開關狀態
 *
 * @author D10NG
 * @date on 2019-11-12 09:27
 */
enum class RDBluetoothStatus(val msg: String) {

    NONE(msg = "當前設備不支持藍牙BLE"),
    STATE_TURNING_ON(msg = "正在打開藍牙"),
    STATE_ON(msg = "藍牙已打開"),
    STATE_TURNING_OFF(msg = "正在關閉藍牙"),
    STATE_OFF(msg = "藍牙已關閉"),
    CONNECTED(msg = "藍牙已連接"),
    DISCONNECTED(msg = "藍牙已斷開連接")

}

編寫接口

創建文件 IBluetoothCallBack

/**
 * 藍牙狀態接口
 *
 * @author D10NG
 * @date on 2019-11-12 09:30
 */
interface IBluetoothCallBack {

    /**
     * 註冊
     * @param obj
     */
    fun register(obj: Any)

    /**
     * 取消註冊
     * @param obj
     */
    fun unRegister(obj: Any)

    /**
     * 取消註冊
     */
    fun unRegisterAll()

    /**
     * 打開藍牙
     */
    fun openBluetooth()

    /**
     * 關閉藍牙
     */
    fun closeBluetooth()

    /**
     * 獲取藍牙狀態
     * @return
     */
    fun getBluetoothStatus() : RDBluetoothStatus
}

業務邏輯

創建文件 BluetoothCallBack

/**
 * 藍牙狀態監聽
 *
 * @author D10NG
 * @date on 2019-11-12 09:31
 */
class BluetoothCallBack constructor(
    application: Application
) : IBluetoothCallBack {

    // 觀察者,key=類、value=方法
    private val checkManMap = HashMap<Any, Method>()

    @Volatile
    private var bluetoothStatus: RDBluetoothStatus

    private val bluetoothReceiver = BluetoothReceiver()

    init {
        // 初始化廣播
        val intentFilter = IntentFilter()
        // 監視藍牙關閉和打開的狀態
        intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED)
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED)
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED)
        // 開始監聽
        application.registerReceiver(bluetoothReceiver, intentFilter)

        // 初始化藍牙狀態
        val bleManager = application.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
        val adapter = bleManager.adapter
        bluetoothStatus = when {
            adapter == null -> RDBluetoothStatus.NONE
            adapter.isEnabled -> RDBluetoothStatus.STATE_ON
            else -> RDBluetoothStatus.STATE_OFF
        }
    }

    override fun register(obj: Any) {
        val clz = obj.javaClass
        if (!checkManMap.containsKey(clz)) {
            val method = AnnotationUtils.findAnnotationMethod(
                clz, RDBluetoothObserver::class.java,
                RDBluetoothStatus::class.java) ?: return
            checkManMap[obj] = method
        }
    }

    override fun unRegister(obj: Any) {
        checkManMap.remove(obj)
    }

    override fun unRegisterAll() {
        checkManMap.clear()
    }

    override fun openBluetooth() {
        val ble = BluetoothAdapter.getDefaultAdapter()
        ble?.enable()
    }

    override fun closeBluetooth() {
        val ble = BluetoothAdapter.getDefaultAdapter()
        ble?.disable()
    }

    override fun getBluetoothStatus(): RDBluetoothStatus = bluetoothStatus

    // 執行
    private fun post(status: RDBluetoothStatus) {
        bluetoothStatus = status
        val set: Set<Any> = checkManMap.keys
        for (obj in set) {
            val method = checkManMap[obj] ?: continue
            method.invoke(obj, status)
        }
    }

    inner class BluetoothReceiver : BroadcastReceiver() {

        override fun onReceive(context: Context?, intent: Intent?) {
            val action = intent?.action ?: return
            when (action) {
                BluetoothAdapter.ACTION_STATE_CHANGED -> {
                    when(intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0)) {
                        BluetoothAdapter.STATE_TURNING_ON -> post(RDBluetoothStatus.STATE_TURNING_ON)
                        BluetoothAdapter.STATE_ON -> post(RDBluetoothStatus.STATE_ON)
                        BluetoothAdapter.STATE_TURNING_OFF -> post(RDBluetoothStatus.STATE_TURNING_OFF)
                        BluetoothAdapter.STATE_OFF -> post(RDBluetoothStatus.STATE_OFF)
                    }
                }
                BluetoothDevice.ACTION_ACL_CONNECTED -> {
                    post(RDBluetoothStatus.CONNECTED)
                }
                BluetoothDevice.ACTION_ACL_DISCONNECTED -> {
                    post(RDBluetoothStatus.DISCONNECTED)
                }
            }
        }
    }
}

暴露接口 單例

創建文件 RDBluetoothManager

/**
 * 藍牙管理器
 *
 * @author D10NG
 * @date on 2019-11-12 09:24
 */
class RDBluetoothManager constructor(
    application: Application
) : IBluetoothCallBack {

    private val bluetoothCallBack : IBluetoothCallBack

    companion object {

        @Volatile
        private var INSTANCE : RDBluetoothManager? = null

        @JvmStatic
        fun getInstance(application: Application) : RDBluetoothManager {
            val temp = INSTANCE
            if (null != temp) {
                return temp
            }
            synchronized(this) {
                val instance = RDBluetoothManager(application)
                INSTANCE = instance
                return instance
            }
        }
    }

    init {
        bluetoothCallBack = BluetoothCallBack(application)
    }

    override fun register(obj: Any) {
        bluetoothCallBack.register(obj)
    }

    override fun unRegister(obj: Any) {
        bluetoothCallBack.unRegister(obj)
    }

    override fun unRegisterAll() {
        bluetoothCallBack.unRegisterAll()
    }

    override fun openBluetooth() {
        bluetoothCallBack.openBluetooth()
    }

    override fun closeBluetooth() {
        bluetoothCallBack.closeBluetooth()
    }

    override fun getBluetoothStatus(): RDBluetoothStatus = bluetoothCallBack.getBluetoothStatus()

}

混淆封裝

如果你想打包成第三方庫的話,看我的另一篇文章:
Android 簡單開發sdk教程一 接口寫法和混淆規則

完事

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章