Android 蓝牙Hid开发

Android 蓝牙Hid开发Demo 下载 http www demodashi com demo 13891 html 最近客户需求 android 系统的一个设备 想连接一个扫描枪 类似蓝牙键盘 只支持 hid 协议 并且可以收到其数据 填写到输入框中 我这里借了一个蓝牙鼠标 用来与 android 设备连接 1Hid 简介 HID 设备 HunmanInterf 即人机交互设备 常见的有鼠标 键盘 游戏手柄 等等 一般有线方式都是通过 USB 连线连接到机器设备 作为用户输入设备 在蓝牙技术中 HI

原文地址: https://blog.csdn.net/VNanyesheshou/article/details/

1 Hid简介

HID设备(Hunman Interface Device Profile),即人机交互设备,常见的有鼠标,键盘,游戏手柄,等等。一般有线方式都是通过USB连线连接到机器设备,作为用户输入设备。在蓝牙技术中,HID设备的接入就是无线的了。

网上查资料说hid从android4.0开始支持(可能是usb hid),不过蓝牙hid应该从android4.2开始支持的,如下图所示:在这里插入图片描述
android4.1.2中的Bluetooth应用中没有hid的相关代码,而android4.2源码中Bluetooth应用中才有hid的代码。
在这里插入图片描述




2 主要代码

连接hid设备步骤:

  1. 开启蓝牙
  2. 获得inputDevice profile
  3. 扫描
  4. 配对
  5. 连接

2.1 开启蓝牙,通过广播接收者监听蓝牙相关状态。

mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (mBluetoothAdapter == null) { 
    Toast.makeText(this, "不支持蓝牙功能", 0).show(); // 不支持蓝牙 return; } // 如果没有打开蓝牙 if (!mBluetoothAdapter.isEnabled()) { 
    mBluetoothAdapter.enable(); } // 初始化广播接收者 mBroadcastReceiver = new BlueBroadcastReceiver(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(BluetoothDevice.ACTION_FOUND); intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); intentFilter.addAction("android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED"); this.registerReceiver(mBroadcastReceiver, intentFilter); 

2.2 获得inputDevice profile

// 4.2以上才支持HID模式

if (Build.VERSION.SDK_INT >= 17) { 
    mHidUtil = HidUtil.getInstance(this); } 
public static HidUtil getInstance(Context context){ 
    if(null == instance){ 
    instance = new HidUtil(context); } return instance; } private HidUtil(Context context) { 
    this.context = context; mBtAdapter = BluetoothAdapter.getDefaultAdapter(); try { 
    mBtAdapter.getProfileProxy(context, mListener, INPUT_DEVICE); } catch (Exception e) { 
    e.printStackTrace(); } } 

通过BluetoothAdapter对象调用getProfileProxy()函数获取代理蓝牙输入设备代理对象。

其中参数mListener必须实现BluetoothProfile.ServiceListener()。获取代理对象成功或失败都会回调该Listener。

private BluetoothProfile.ServiceListener mListener = new BluetoothProfile.ServiceListener() { 
    @Override public void onServiceConnected(int profile, BluetoothProfile proxy) { 
    Log.i(TAG, "mConnectListener onServiceConnected"); //BluetoothProfile proxy这个已经是BluetoothInputDevice类型了 try { 
    if (profile == INPUT_DEVICE) { 
    mBluetoothProfile = proxy; } } catch (Exception e) { 
    e.printStackTrace(); } } @Override public void onServiceDisconnected(int profile) { 
    Log.i(TAG, "mConnectListener onServiceConnected"); } }; 

获取到输入设备的代理对象,之后就可以进行连接操作了。

2.3 扫描(点击连接按钮开始扫描蓝牙设备)

mBluetoothAdapter.startDiscovery(); 

2.4 配对

广播接收者监听扫描到蓝牙设备,过滤出所需蓝牙设备进行配对,如果之前配对过则直接连接。

if(action.equals(BluetoothDevice.ACTION_FOUND)){ 
    // 通过广播接收到了BluetoothDevice final BluetoothDevice device = (BluetoothDevice) intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); if (device == null) return; String btname = device.getName(); String address = device.getAddress(); Log.i(TAG, "bluetooth name:"+btname+",address:"+address); if((address != null&& address.equals(HID_ADDR))||(btname != null && btname.equals(HID_NAME))){ 
    mConnectDevice = device; mBluetoothAdapter.cancelDiscovery(); if(!mHidUtil.isBonded(device)){ 
    //先配对 mHidUtil.pair(device); }else { 
    //已经配对则直接连接 mHidUtil.connect(device); } } } 

HidUtil类中的配对方法:

 / * 配对 * @param BluetoothDevice */ public void pair(BluetoothDevice device) { 
    Log.i(TAG, "pair device:"+device); Method createBondMethod; try { 
    createBondMethod = BluetoothDevice.class.getMethod("createBond"); createBondMethod.invoke(device); } catch (Exception e) { 
    e.printStackTrace(); } } 

2.5 连接(配对成功后)

if(action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)){ 
    BluetoothDevice device = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); String name = device.getName(); String address = device.getAddress(); Log.i(TAG,"name:"+name+",address:"+address+",bondstate:"+device.getBondState()); if((address != null&& address.equals(HID_ADDR))||(name != null && name.equals(HID_NAME))){ 
    if(device.getBondState() == BluetoothDevice.BOND_BONDED) mHidUtil.connect(device); } } 

判断是否是要连接的输入设备,如果符合条件则进行连接。

HidUtil中connect 方法

/ * 连接设备 * @param bluetoothDevice */ public void connect(final BluetoothDevice device) { 
    Log.i(TAG, "connect device:"+device); try { 
    //得到BluetoothInputDevice然后反射connect连接设备 Method method = mBluetoothProfile.getClass().getMethod("connect", new Class[] { 
    BluetoothDevice.class }); method.invoke(mBluetoothProfile, device); } catch (Exception e) { 
    e.printStackTrace(); } } 

BluetoothInputDevice中的connect方法是隐藏的,所以需要通过反射机制获取该方法进行调用。

2.6 监听连接状态

通过广播接收者监听连接状态。

if(action.equals("android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED")){ 
    int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,0); BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); Log.i(TAG,"state="+state+",device="+device); if(state == BluetoothProfile.STATE_CONNECTED){ 
   //连接成功 Toast.makeText(MainActivity.this, R.string.connnect_success, Toast.LENGTH_SHORT).show(); } else if(state == BluetoothProfile.STATE_DISCONNECTED){ 
   //连接失败 Toast.makeText(MainActivity.this, R.string.disconnected, Toast.LENGTH_SHORT).show(); } } 

2.7 断开连接

if(mConnectDevice != null) mHidUtil.disConnect(mConnectDevice); 

HidUtil中disconnect方法

/ * 断开连接 * @param BluetoothDevice */ public void disConnect(BluetoothDevice device) { 
    Log.i(TAG, "disConnect device:"+device); try { 
    if (device != null) { 
    Method method = mBluetoothProfile.getClass().getMethod("disconnect", new Class[] { 
    BluetoothDevice.class }); method.invoke(mBluetoothProfile, device); } } catch (Exception e) { 
    e.printStackTrace(); } } 

手机端断开连接后,重新连接会提示“只能有鼠标发起重新连接请求,请使用鼠标重新连接”。

3 接收数据

adb shell

getevent -l

当连接成功后,会看到如下内容:

这表示蓝牙鼠标成为一个输入设备

左击鼠标:

我们应用中打印

表示在屏幕中某位置处点击了一下。

右击鼠标:

表示点击了一下返回键,程序退出。

移动鼠标会发现屏幕上小光标在移动,滑动鼠标也会触发相应事件。

4 其他

现在大部分手机是支持hid的,并且也将该功能打开状态。

如果是做系统开发,就需要注意将Bluetooth中的hid开关打开。

将源码中的packages/apps/Bluetooth/res/values/config.xml的profile_supported_hid 修改为true。

<bool name="profile_supported_hid">true</bool> 

demo下载地址:http://www.demodashi.com/demo/13891.html

5 Demo测试

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/212175.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午8:38
下一篇 2026年3月18日 下午8:39


相关推荐

  • windows环境下用c++实现socket编程

    windows环境下用c++实现socket编程一、什么是Socketsocket即套接字,用于描述地址和端口,是一个通信链的句柄。应用程序通过socket向网络发出请求或者回应。sockets(套接字)编程有三种,流式套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始套接字(SOCK_RAW);前两种较常用。基于TCP的socket编程是采用的流式套接字。(1)SOCK_STREAM表示面向连接的

    2022年7月13日
    31
  • javascript中一个字符占几个字节

    javascript中一个字符占几个字节一般来说英文是1个,中文是两个。但是会根据编码方式不同而不同。以下是搬运:英文字母和中文汉字在不同字符集编码下的字节数英文字母:字节数:1;编码:GB2312字节数:1;编码:GBK字节数:1;编码:GB18030字节数:1;编码:ISO-8859-1字节数:1;编码:UTF-8字节数:4;编码:UTF-16字节数:2;编码:UTF-16BE字节数…

    2025年5月31日
    3
  • springboot Jpa多数据源(不同库)配置

    springboot Jpa多数据源(不同库)配置一、前言springboot版本不同对多数据源配置代码有一定影响,部分方法和配置略有不同。本文采用的springboot版本为2.3.12,数据源为mysql和postgresql二、配置实战2.1基础pom<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</ar

    2022年10月20日
    4
  • Gemini与GPT联动(保姆级顶会绘图教程)

    Gemini与GPT联动(保姆级顶会绘图教程)

    2026年3月16日
    22
  • SE01(理解重要)

    SE01(理解重要)仅供学习者观看 大佬们勿喷

    2026年3月17日
    3
  • linux查看本机ip地址

    linux查看本机ip地址linux 中哪个命令可以查看自己的 IP 地址 nbsp 50 我的主机是通过宽带联网的 主机的 IP 通过那个本地连接可以看到 但在虚拟机 Debianlinux5 0 终端下输入 route n 显示的是 destination 的 IP 怎么查看属于虚拟机 linux 的 IP 呢 linux 通过桥接的 再问哥们一个问题 我在 linux 终端键入 telnet 主机 IP 可以进入 WIN 展开哥们 在 DOS 下 telnetip

    2026年3月19日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号