H5+APP 之 蓝牙连接

初始化一些参数

const BluetoothAdapter = plus.android.importClass('android.bluetooth.BluetoothAdapter') as any
const Intent = plus.android.importClass('android.content.Intent') as any
const IntentFilter = plus.android.importClass('android.content.IntentFilter') as any
const BluetoothDevice = plus.android.importClass('android.bluetooth.BluetoothDevice') as any
const UUID = plus.android.importClass('java.util.UUID') as any
const Toast = plus.android.importClass('android.widget.Toast') as any
//连接串口设备的 UUID
const MY_UUID = UUID.fromString('00001101-0000-1000-8000-00805F9B34FB')

const invoke = plus.android.invoke
const btAdapter = BluetoothAdapter.getDefaultAdapter()
const activity = plus.android.runtimeMainActivity() as any

let btSocket: any = null
let btInStream: any = null
let btOutStream: any = null
let setIntervalId = 0

let btFindReceiver: any = null //蓝牙搜索广播接收器
let btStatusReceiver: any = null //蓝牙状态监听广播
interface BlueToothToolStateType {
    bluetoothEnable: boolean
    bluetoothState: string
    discoveryDeviceState: boolean
    readThreadState: boolean
}
interface BlueToothTooloptionsType {
    listenBTStatusCallback: (arg?: any) => void
    discoveryDeviceCallback: (arg?: any) => void
    discoveryFinishedCallback: () => void
    readDataCallback: (arg?: any) => void
    connExceptionCallback: (arg?: any) => void
}

构建构造函数

export class BlueToothTool {
    private state: BlueToothToolStateType = {
        bluetoothEnable: false, //蓝牙是否开启
        bluetoothState: '', //当前蓝牙状态
        discoveryDeviceState: false, //是否正在搜索蓝牙设备
        readThreadState: false, //蓝牙设备名称
    }
    private options: BlueToothTooloptionsType = {
        /**
         * 监听蓝牙状态回调
         * @param {String} state
         */
        listenBTStatusCallback: function () {},
        /**
         * 搜索到新的蓝牙设备回调
         * @param {Device} newDevice
         */
        discoveryDeviceCallback: function () {},
        /**
         * 蓝牙搜索完成回调
         */
        discoveryFinishedCallback: function () {},
        /**
         * 接收到数据回调
         * @param {Array} dataByteArr
         */
        readDataCallback: function () {},
        /**
         * 蓝牙连接中断回调
         * @param {Exception} e
         */
        connExceptionCallback: function () {},
    }

    constructor() {}

    Init(setOptions: any) {
        Object.assign(this.options, setOptions)
        this.state.bluetoothEnable = this.GetBluetoothStatus()
        this.ListenBluetoothStatus()
    }
    ShortToast(msg: string) {
        Toast.makeText(activity, msg, Toast.LENGTH_SHORT).show()
    }
    /**
     * 是否支持蓝牙
     * @return {boolean}
     */
    IsSupportBluetooth() {
        if (btAdapter != null) {
            return true
        }
        return false
    }
    /**
     * 获取蓝牙的状态
     * @return {boolean} 是否已开启
     */
    GetBluetoothStatus() {
        if (btAdapter != null) {
            return btAdapter.isEnabled()
        }
        return false
    }
    /**
     * 断开连接设备
     * @param {Object} address
     * @return {Boolean}
     */
    CloseBtSocket() {
        this.state.readThreadState = false
        if (!btSocket) {
            return
        }
        try {
            btSocket.close()
        } catch (e) {
            console.error(e)
            btSocket = null
        }
    }
    /**
     * 取消发现
     */
    CancelDiscovery() {
        if (btAdapter.isDiscovering()) {
            btAdapter.cancelDiscovery()
        }
        if (btFindReceiver != null) {
            activity.unregisterReceiver(btFindReceiver)
            btFindReceiver = null
        }
        this.state.discoveryDeviceState = false
    }
    /**
     * 打开蓝牙
     * @param activity
     * @param requestCode
     */
    TurnOnBluetooth() {
        if (btAdapter == null) {
            this.ShortToast('没有蓝牙')
            return
        }
        if (!btAdapter.isEnabled()) {
            if (activity == null) {
                this.ShortToast('未获取到activity')
                return
            } else {
                const intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
                const requestCode = 1
                activity.startActivityForResult(intent, requestCode)
                return
            }
        } else {
            this.ShortToast('蓝牙已经打开')
        }
    }
    /**
     * 关闭蓝牙
     */
    TurnOffBluetooth() {
        if (btAdapter != null && btAdapter.isEnabled()) {
            btAdapter.disable()
        }
        if (btFindReceiver != null) {
            try {
                activity.unregisterReceiver(btFindReceiver)
            } catch (e) {
                console.log('TurnOffBluetooth - Err', e)
            }
            btFindReceiver = null
        }
        this.state.bluetoothEnable = false
        this.CancelDiscovery()
        this.CloseBtSocket()

        if (btAdapter != null && btAdapter.isEnabled()) {
            btAdapter.disable()
            this.ShortToast('蓝牙关闭成功')
        } else {
            this.ShortToast('蓝牙已经关闭')
        }
    }
    /**
     * 获取已经配对的设备
     * @return {Array} connetedDevices
     */
    GetPairedDevices() {
        const pairedDevices: any[] = []

        //蓝牙连接android原生对象,是一个set集合
        let pairedDevicesAndroid = null
        if (btAdapter != null && btAdapter.isEnabled()) {
            pairedDevicesAndroid = btAdapter.getBondedDevices()
        } else {
            this.ShortToast('蓝牙未开启')
        }

        if (!pairedDevicesAndroid) {
            return pairedDevices
        }

        //遍历连接设备的set集合,转换为js数组
        const it = invoke(pairedDevicesAndroid, 'iterator')
        while (invoke(it, 'hasNext')) {
            const device = invoke(it, 'next')
            pairedDevices.push({
                name: invoke(device, 'getName'),
                address: invoke(device, 'getAddress'),
            })
        }
        return pairedDevices
    }
    /**
     * 发现设备
     */
    DiscoveryNewDevice() {
        if (btFindReceiver != null) {
            try {
                activity.unregisterReceiver(btFindReceiver)
            } catch (e) {
                console.error(e)
            }
            btFindReceiver = null
            this.CancelDiscovery()
        }
        const Build = plus.android.importClass('android.os.Build') as any

        //6.0以后的如果需要利用本机查找周围的wifi和蓝牙设备, 申请权限
        if (Build.VERSION.SDK_INT >= 6.0) {
            console.log('6.0以后的如果需要利用本机查找周围的wifi和蓝牙设备, 申请权限')
        }
        const options = this.options
        btFindReceiver = plus.android.implements('io.dcloud.android.content.BroadcastReceiver', {
            onReceive: function (context: any, intent: any) {
                plus.android.importClass(context)
                plus.android.importClass(intent)
                const action = intent.getAction()

                if (BluetoothDevice.ACTION_FOUND == action) {
                    // 找到设备
                    const device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
                    const newDevice = {
                        name: plus.android.invoke(device, 'getName'),
                        address: plus.android.invoke(device, 'getAddress'),
                    }
                    options.discoveryDeviceCallback && options.discoveryDeviceCallback(newDevice)
                }
                if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED == action) {
                    // 搜索完成
                    this.CancelDiscovery()
                    options.discoveryFinishedCallback && options.discoveryFinishedCallback()
                }
            },
        })
        const filter = new IntentFilter()
        filter.addAction(BluetoothDevice.ACTION_FOUND)
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)
        activity.registerReceiver(btFindReceiver, filter)
        btAdapter.startDiscovery() //开启搜索
        this.state.discoveryDeviceState = true
    }
    /**
     * 蓝牙状态监听
     * @param {Activity} activity
     */
    ListenBluetoothStatus() {
        if (btStatusReceiver != null) {
            try {
                activity.unregisterReceiver(btStatusReceiver)
            } catch (e) {
                console.error(e)
            }
            btStatusReceiver = null
        }
        btStatusReceiver = plus.android.implements('io.dcloud.android.content.BroadcastReceiver', {
            onReceive: (context: any, intent: any) => {
                plus.android.importClass(context)
                plus.android.importClass(intent)

                const action = intent.getAction()
                const blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0)
                let stateStr = ''
                switch (action) {
                    case BluetoothAdapter.ACTION_STATE_CHANGED:
                        switch (blueState) {
                            case BluetoothAdapter.STATE_TURNING_ON:
                                stateStr = 'STATE_TURNING_ON'
                                break
                            case BluetoothAdapter.STATE_ON:
                                this.state.bluetoothEnable = true
                                stateStr = 'STATE_ON'
                                break
                            case BluetoothAdapter.STATE_TURNING_OFF:
                                stateStr = 'STATE_TURNING_OFF'
                                break
                            case BluetoothAdapter.STATE_OFF:
                                stateStr = 'STATE_OFF'
                                this.state.bluetoothEnable = false
                                break
                        }
                        this.state.bluetoothState = stateStr
                        this.options.listenBTStatusCallback && this.options.listenBTStatusCallback(stateStr)
                        break
                }
            },
        })
        const filter = new IntentFilter()
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED)
        activity.registerReceiver(btStatusReceiver, filter)
        // 首次连接 状态回调
        if (this.state.bluetoothEnable) {
            this.options.listenBTStatusCallback && this.options.listenBTStatusCallback('STATE_ON')
        }
    }
    /**
     * 根据蓝牙地址,连接设备
     * @param {Stirng} address
     * @return {Boolean}
     */
    ConnDevice(address: any, callback: (arg: boolean) => void) {
        plus.android.importClass('java.io.InputStream')
        plus.android.importClass('java.io.OutputStream')
        plus.android.importClass('android.bluetooth.BluetoothSocket')

        this.CancelDiscovery()
        if (btSocket != null) {
            this.CloseBtSocket()
        }
        this.state.readThreadState = false

        try {
            const device = invoke(btAdapter, 'getRemoteDevice', address)
            btSocket = invoke(device, 'createRfcommSocketToServiceRecord', MY_UUID)
        } catch (e) {
            console.error(e)
            this.ShortToast('连接失败,获取Socket失败!')
            callback(false)
            return false
        }
        try {
            invoke(btSocket, 'connect')
            this.ReadData() //读数据
            this.ShortToast('连接成功')
            callback(true)
        } catch (e) {
            console.error(e)
            this.ShortToast('连接失败')
            callback(false)
            try {
                btSocket.close()
                btSocket = null
            } catch (e1) {
                console.error(e1)
            }
            return false
        }
        return true
    }
    /**
     * 读取数据
     * @param {Object} activity
     * @param {Function} callback
     * @return {Boolean}
     */
    ReadData() {
        if (!btSocket) {
            this.ShortToast('请先连接蓝牙设备!')
            return false
        }
        try {
            btInStream = invoke(btSocket, 'getInputStream')
            btOutStream = invoke(btSocket, 'getOutputStream')
            console.log('ReadData - invoke', btSocket)
        } catch (e) {
            console.error(e)
            this.ShortToast('创建输入输出流失败!')
            this.CloseBtSocket()
            return false
        }
        this.Read()
        this.state.readThreadState = true
        return true
    }
    /**
     * 模拟java多线程读取数据
     */
    Read() {
        // console.log('Read - 模拟java多线程读取数据', btOutStream)
        let setTimeCount = 0
        clearInterval(setIntervalId)
        setIntervalId = setInterval(() => {
            setTimeCount++
            if (this.state.readThreadState) {
                const t = new Date().getTime()
                //心跳检测
                if (setTimeCount % 20 == 0) {
                    try {
                        btOutStream.write([0b00]) //这里报错
                    } catch (e) {
                        this.state.readThreadState = false
                        this.options.connExceptionCallback && this.options.connExceptionCallback(e)
                    }
                }
                const dataArr = []
                while (invoke(btInStream, 'available') !== 0) {
                    const data = invoke(btInStream, 'read')
                    dataArr.push(data)
                    const ct = new Date().getTime()
                    if (ct - t > 20) {
                        break
                    }
                }
                if (dataArr.length > 0) {
                    this.options.readDataCallback && this.options.readDataCallback(dataArr)
                }
            }
        }, 40)
    }
    /**
     * 断开连接设备
     * @param {Object} address
     * @return {Boolean}
     */
    DisConnDevice() {
        if (btSocket != null) {
            this.CloseBtSocket()
        }
        this.state.readThreadState = false
        this.ShortToast('断开连接成功')
    }
    /**
     * 发送数据
     * @param {String} dataStr
     * @return {Boolean}
     */
    SendData(dataStr: string): boolean {
        if (!btOutStream) {
            this.ShortToast('创建输出流失败!')
            return false
        }
        const bytes = invoke(dataStr as any, 'getBytes', 'gbk')
        try {
            btOutStream.write(bytes)
        } catch (e) {
            return false
        }
        return true
    }
    SendByteData(byteData: any) {
        if (!btOutStream) {
            this.ShortToast('创建输出流失败!')
            return
        }
        try {
            btOutStream.write(byteData)
        } catch (e) {
            return false
        }
        return true
    }
}

使用嘛,就直接引入实例化就可以啦,不过由于蓝牙一直开着会很耗电,影响性能,如果连接上了,记得关闭蓝牙搜索功能

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在 H5+App 中调用手机悬浮窗权限,你需要使用 H5+ 的原生 API 来完成。H5+ 是一套基于 HTML5 的移动应用开发框架,它提供了一些与原生功能交互的接口,包括调用手机悬浮窗权限。 首先,你需要确保你的 H5+App 已经集成了 H5+ 的开发环境和相应的 SDK。然后,你可以按照以下步骤来调用手机悬浮窗权限: 1. 在你的 H5+App 的配置文件(manifest.json)中添加悬浮窗权限的声明。示例代码如下: ```json { "permissions": { "floaty": { "description": "使用悬浮窗权限" } } } ``` 2. 在你的 H5+App 的 HTML 页面中添加 JavaScript 代码来请求悬浮窗权限。示例代码如下: ```javascript document.addEventListener("plusready", function() { // 请求悬浮窗权限 plus.navigator.requestFloatPermission(function(result) { if (result) { console.log("悬浮窗权限已授权"); // 在这里可以进行悬浮窗相关的操作 } else { console.log("悬浮窗权限被拒绝"); // 在这里处理悬浮窗权限被拒绝的情况 } }); }); ``` 在上述代码中,我们使用了 `plus.navigator.requestFloatPermission` 方法来请求悬浮窗权限。该方法会弹出一个系统对话框,询问用户是否授权悬浮窗权限。当用户做出选择后,回调函数中的 `result` 参数将返回授权状态。 3. 根据悬浮窗权限的授权状态,你可以在回调函数中编写相应的逻辑来处理授权成功或被拒绝的情况。 需要注意的是,具体的 API 调用方式可能会因平台和 H5+ 版本的不同而有所差异。你可以参考 H5+ 的官方文档和示例代码来了解更多关于悬浮窗权限的详细信息和使用方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值