学习笔记_基于Kotlin的蓝牙通信工具类

学习笔记__基于Kotlin的蓝牙通信工具类

使用Kotlin简单实现蓝牙通信,不是很稳定

蓝牙通信步骤

  • 获取蓝牙适配器
方法一:
BluetoothAdapter.getDefaultAdapter()

方法二:
val mBluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
 if (mBluetoothManager != null)
            mBluetoothAdapter = mBluetoothManager.adapter //获取蓝牙适配器
  • 检查蓝牙是否可用
 if (BluetoothUtils.getBluetoothAdapter(context) == null)
            return false
        return BluetoothUtils.getBluetoothAdapter(context).isEnabled
  • 打开/关闭蓝牙
打开蓝牙:
BluetoothUtils.getBluetoothAdapter(context).enable()
        val enable = Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE)
        enable.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, time)//设置可见时间
        context.startActivity(enable)
关闭蓝牙:
BluetoothUtils.getBluetoothAdapter(context).disable()
  • 搜索附近可见蓝牙

需要提前注册广播监听 BluetoothDevice.ACTION_FOUND

BluetoothUtils.getBluetoothAdapter(context).startDiscovery()
  • 停止搜索
BluetoothUtils.getBluetoothAdapter(context).cancelDiscovery()
  • 配对蓝牙
 btDevice.createBond()//btDevice为目标蓝牙设备对象
  • 建立服务器/客户端,并尝试连接

注意提前关闭搜索蓝牙,否则会影响连接稳定

  • 发起通信,接收信息

基于Kotlin的蓝牙通信工具类

工具类中Bonde类参考自网络,通过反射获取系统蓝牙相关操作方法

package com.cai.bluetoothtest.utils

import android.annotation.TargetApi
import android.app.Activity
import android.bluetooth.*
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Build
import android.os.Handler
import android.os.Message
import android.os.ParcelUuid
import android.util.Log
import android.widget.Toast
import org.greenrobot.eventbus.EventBus
import java.io.IOException
import java.io.InputStream
import java.lang.reflect.Field
import java.lang.reflect.InvocationTargetException
import java.util.*


/*
 *  @项目名:  BluetoothTest 
 *  @创建者:   cai
 *  @创建时间:  2018/5/22 13:08
 *  @描述:    TODO
 */
object BluetoothUtils {


    private var mSocket: BluetoothSocket? = null
    private var mReadThread: ReadThread? = null
    private var mServerSocket: BluetoothServerSocket? = null
    private var mClientThread: ClientThread? = null
    private var mServerThread: ServerThread? = null

    const val HANDLER_RECEIVE_MESSAGE = 101

    /**
     * 获取蓝牙适配器
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
    fun getBluetoothAdapter(context: Context): BluetoothAdapter {
        var mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter()

        val mBluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager//获取蓝牙管理器
        if (mBluetoothManager != null)
            mBluetoothAdapter = mBluetoothManager.adapter //获取蓝牙适配器

        return mBluetoothAdapter
    }

    /**
     * 检查蓝牙是否打开(是否可用)
     */
    fun checkBleDevice(context: Context): Boolean {
        if (BluetoothUtils.getBluetoothAdapter(context) == null)
            return false
        return BluetoothUtils.getBluetoothAdapter(context).isEnabled
    }

    /**
     * 尝试打开蓝牙
     */
    fun openBluetooth(context: Context) {
        openBluetooth(context, 3600)//3600为蓝牙设备可见时间
    }

    /**
     * 尝试打开蓝牙
     */
    fun openBluetooth(context: Context, time: Int) {
        BluetoothUtils.getBluetoothAdapter(context).enable()
        val enable = Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE)
        enable.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, time)
        context.startActivity(enable)
    }

    /**
     * 关闭蓝牙
     */
    fun closeBluetooth(context: Context) {
        BluetoothUtils.getBluetoothAdapter(context).disable()
    }

    /**
     * 尝试搜索可见蓝牙设备
     */
    fun searchBluetooth(context: Context): Boolean {
        //如果当前发现了新的设备,则停止继续扫描,当前扫描到的新设备会通过广播推向新的逻辑
        if (BluetoothUtils.getBluetoothAdapter(context).isDiscovering()) {
            stopSearthBltDevice(context)
            return false
        }
        return BluetoothUtils.getBluetoothAdapter(context).startDiscovery()
    }

    /**
     * 尝试停止搜索
     */
    fun stopSearthBltDevice(context: Context): Boolean {
        return BluetoothUtils.getBluetoothAdapter(context).cancelDiscovery()
    }

    /**
     * 注册蓝牙广播
     */
    fun registerBluetoothReceiver(activity: Activity, receiver: BroadcastReceiver) {
        val intent = IntentFilter()
        intent.addAction(BluetoothDevice.ACTION_FOUND)//搜索发现设备
        intent.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED)//状态改变
        intent.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED)//行动扫描模式改变了
        intent.addAction(BluetoothAdapter.ACTION_STATE_CHANGED)//动作状态发生了变化
        intent.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST)
        activity.registerReceiver(receiver, intent)
    }

    /**
     * 反注册广播
     */
    fun unregisterReceiver(context: Context, receiver: BroadcastReceiver) {
        context.unregisterReceiver(receiver)
        if (BluetoothUtils.getBluetoothAdapter(context) != null)
            BluetoothUtils.getBluetoothAdapter(context).cancelDiscovery()
    }


    /**
     *打开客户端线程
     */
    fun startClientThread(device: BluetoothDevice) {
        if (mClientThread == null) {
            synchronized(this) {
                if (mClientThread == null) {
                    mClientThread = ClientThread(device, getUUID())
                    mClientThread?.start()
                }
            }
        }
    }

    /**
     * 打开服务端线程
     */
    fun startServerThread(context: Context) {
        if (mServerThread == null) {
            synchronized(this) {
                if (mServerThread == null) {
                    mServerThread = ServerThread(context, getUUID())
                    mServerThread?.start()
                }
            }
        }

    }

    /**
     * 发送数据
     */
    fun sendMessageHandle(context: Context, msg: String) {
        LogUtils.e(msg)
        if (mSocket == null) {
            Toast.makeText(context, "没有连接", Toast.LENGTH_SHORT).show()
            return
        }
        try {
            val os = mSocket?.getOutputStream()
            os?.write(msg.toByteArray())
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

    /**
     * 停止客户端连接
     */
    fun shutdownClient() {
        object : Thread() {
            override fun run() {
                if (mClientThread != null) {
                    mClientThread?.interrupt()
                }
                if (mReadThread != null) {
                    mReadThread?.interrupt()
                }
                if (mSocket != null) {
                    try {
                        mSocket?.close()
                    } catch (e: IOException) {
                        e.printStackTrace()
                    }
                }
            }
        }.start()
    }

    /**
     * 停止服务器
     */
    fun shutdownServer() {
        object : Thread() {
            override fun run() {
                if (mServerThread != null) {
                    mServerThread?.interrupt()
                }
                if (mReadThread != null) {
                    mReadThread?.interrupt()
                }
                try {
                    if (mSocket != null) {
                        mSocket?.close()
                    }
                    if (mServerSocket != null) {
                        mServerSocket?.close()
                    }
                } catch (e: IOException) {
                    e.printStackTrace()
                }

            }
        }.start()
    }

    /**
     * 反射获取本地蓝牙地址
     */
    fun getBtAddressByReflection(): String? {
        val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
        var field: Field?
        try {
            field = BluetoothAdapter::class.java.getDeclaredField("mService")
            field!!.setAccessible(true)
            val bluetoothManagerService = field!!.get(bluetoothAdapter) ?: return null
            val method = bluetoothManagerService.javaClass.getMethod("getAddress")
            if (method != null) {
                val obj = method.invoke(bluetoothManagerService)
                if (obj != null) {
                    return obj.toString()
                }
            }
        } catch (e: NoSuchFieldException) {
            e.printStackTrace()
        } catch (e: IllegalAccessException) {
            e.printStackTrace()
        } catch (e: NoSuchMethodException) {
            e.printStackTrace()
        } catch (e: InvocationTargetException) {
            e.printStackTrace()
        }
        return null
    }

    /**
     * 获取UUID
     */
    fun getUUID(): UUID {
        var uuid: UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")
        try {
            val getUuidsMethod = BluetoothAdapter::class.java.getDeclaredMethod("getUuids")
            val uuids = getUuidsMethod.invoke(BluetoothAdapter.getDefaultAdapter(), null) as Array<ParcelUuid>
            for (uuid in uuids) {
                LogUtils.e(uuid.uuid)
            }
            uuid = uuids[0].uuid
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return uuid
    }

    /**
     * 客户端线程
     */
    class ClientThread(device: BluetoothDevice, uuid: UUID) : Thread() {
        private lateinit var uuid: UUID

        init {
            this.uuid = uuid
            mSocket = device.createRfcommSocketToServiceRecord(uuid)
        }

        override fun run() {
            try {
                mSocket?.connect()
                LogUtils.e(1)
            } catch (e: IOException) {
                e.printStackTrace()
            }

        }
    }

    /**
     * 服务器线程
     */
    class ServerThread : Thread {
        private lateinit var context: Context
        private lateinit var uuid: UUID
        private var serverName = "defServerName"

        constructor(context: Context, uuid: UUID) {
            ServerThread(context,uuid,serverName)
        }

        constructor(context: Context, uuid: UUID, name: String) {
            this.context = context
            this.uuid = uuid
            this.serverName = name

            mServerSocket = getBluetoothAdapter(context).listenUsingRfcommWithServiceRecord(serverName,
                    uuid)
        }

        override fun run() {
            try {
                LogUtils.e(1)
                /* 接受客户端的连接请求 */
                mSocket = mServerSocket?.accept()
                mReadThread = ReadThread()
                mReadThread?.start()
            } catch (e: IOException) {
                e.printStackTrace()
                LogUtils.e(1)
            }
        }
    }

    /**
     * 读取数据线程.
     * 空参构造使用EventBus传递收到的消息.
     * 有参构造使用Handler传递收到的消息.
     */
    class ReadThread : Thread {
        private var handler: Handler? = null

        constructor() {
        }

        constructor(handler: Handler) {
            this.handler = handler
        }

        override fun run() {
            var input: InputStream? = null
            try {
                LogUtils.e(1)
                val buffer = ByteArray(1024)
                input = (mSocket as BluetoothSocket).getInputStream()
                while (true) {
                    var bytes = input.read(buffer)
                    if (bytes > 0) {
                        val buf_data = ByteArray(bytes)
                        for (i in 0..bytes - 1) {
                            buf_data[i] = buffer[i]
                        }
                        val s = String(buf_data)

                        if (handler != null) {
                            val msg: Message = Message()
                            msg.what = HANDLER_RECEIVE_MESSAGE
                            msg.obj = s
                            handler!!.sendMessage(msg)
                        }
                        EventBus.getDefault().post(s)
                    }
                }
            } catch (e1: IOException) {
                e1.printStackTrace()
            } finally {
                try {
                    if (input != null)
                        input.close()
                } catch (e1: IOException) {
                    e1.printStackTrace()
                }
            }

        }
    }

    /**
     * 绑定蓝牙
     */
    object Bonde {

        /**
         * 开始匹配
         */
        fun createBond(btDevice: BluetoothDevice): Boolean {
            return btDevice.createBond()
        }

        /**
         * 与设备解除配对
         */
        @Throws(Exception::class)
        fun removeBond(btClass: Class<*>, btDevice: BluetoothDevice): Boolean {
            val removeBondMethod = btClass.getMethod("removeBond")
            val returnValue = removeBondMethod.invoke(btDevice) as Boolean
            return returnValue
        }


        @Throws(Exception::class)
        fun setPin(btClass: Class<out BluetoothDevice>, btDevice: BluetoothDevice,
                   str: String): Boolean {
            try {
                val removeBondMethod = btClass.getDeclaredMethod("setPin",
                        *arrayOf<Class<*>>(ByteArray::class.java))
                val returnValue = removeBondMethod.invoke(btDevice,
                        arrayOf<Any>(str.toByteArray())) as Boolean
                Log.e("returnValue", "" + returnValue)
            } catch (e: SecurityException) {
                e.printStackTrace()
            } catch (e: IllegalArgumentException) {
                e.printStackTrace()
            } catch (e: Exception) {
                e.printStackTrace()
            }

            return true

        }

        /**
         * 取消用户输入
         */
        @Throws(Exception::class)
        fun cancelPairingUserInput(btClass: Class<*>,
                                   device: BluetoothDevice): Boolean {
            val createBondMethod = btClass.getMethod("cancelPairingUserInput")
            //        cancelBondProcess(btClass, device);
            val returnValue = createBondMethod.invoke(device) as Boolean
            return returnValue
        }

        /**
         * 取消配对
         */
        @Throws(Exception::class)
        fun cancelBondProcess(btClass: Class<*>,
                              device: BluetoothDevice): Boolean {
            val createBondMethod = btClass.getMethod("cancelBondProcess")
            val returnValue = createBondMethod.invoke(device) as Boolean
            return returnValue
        }

        /**
         * 确认配对
         */
        @Throws(Exception::class)
        fun setPairingConfirmation(btClass: Class<*>, device: BluetoothDevice, isConfirm: Boolean) {
            val setPairingConfirmation = btClass.getDeclaredMethod("setPairingConfirmation", Boolean::class.java)
            setPairingConfirmation.invoke(device, isConfirm)
        }


        /**
         * 取得所有方法
         * @param clsShow
         */
        fun printAllInform(clsShow: Class<*>) {
            try {
                // 取得所有方法
                val hideMethod = clsShow.methods
                var i = 0
                while (i < hideMethod.size) {
                    Log.e("method name", hideMethod[i].name + ";and the i is:"
                            + i)
                    i++
                }
                // 取得所有常量
                val allFields = clsShow.fields
                i = 0
                while (i < allFields.size) {
                    Log.e("Field name", allFields[i].name)
                    i++
                }
            } catch (e: SecurityException) {
                e.printStackTrace()
            } catch (e: IllegalArgumentException) {
                e.printStackTrace()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    class BluetoothBroadcastReceiver : BroadcastReceiver() {
        //接收
        override fun onReceive(context: Context, intent: Intent) {
            val action = intent.getAction()
            val b = intent.getExtras()
            val lstName = b.keySet()
            // 显示所有收到的消息及其细节
            for (i in lstName) {
                val keyName = i.toString()
                Log.e("bluetooth", keyName + ">>>" + b.get(keyName))
            }

            var device: BluetoothDevice
            // 搜索发现设备时,取得设备的信息;注意,这里有可能重复搜索同一设备
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
                
            } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
                device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
                when (device.bondState) {
                    BluetoothDevice.BOND_BONDING//正在配对
                    -> {
                        LogUtils.e("正在配对......")
                    }
                    BluetoothDevice.BOND_BONDED//配对结束
                    -> {
                        LogUtils.e("完成配对")
                        //startMessageTest(device)
                    }
                    BluetoothDevice.BOND_NONE//取消配对/未配对
                    -> {
                        LogUtils.e("取消配对")
                    }
                }
                
            }
        }
    }
}
  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值