Android Bluetooth HID实现详解

来源:互联网 发布:js控制视频播放暂停 编辑:程序博客网 时间:2024/05/21 11:10

分类: Android2011-06-24 15:46 7648人阅读 评论(18) 收藏 举报
androidjnipathnullkeyboardfunction

目录(?)[+]

Android Bluetooth HID实现详解

Android 关于蓝牙的部分使用的是BlueZ协议栈。但是直到目前2.3.3都没有扩展HID的profile,只是实现了最基本的Handset和d2dp的profile,所以我们的工作涉及到从应用到jni三层的修改,具体修改文件如图所示,绿色表示新建的类,橙色表示修改的类。

 

一. 本地层

路径:framework/base/core/jni/

参照android_server_BluetoothA2dpService.cpp新建android_server_bluetoothHidServer.cpp。该类中主要是通过dbus对bluez协议栈的访问,dbus 的通用方法都在android_bluetooth_common.cpp中实现,我们做的仅仅是通过dbus_func_args_async调用到bluez提供的input接口。

主要实现以下两个方法函数:

[cpp] view plaincopy
  1. static jboolean connectSinkNative(JNIEnv *env, jobject object, jstring path) {  
  2.   
  3. #ifdef HAVE_BLUETOOTH  
  4.   
  5.     LOGV(__FUNCTION__);  
  6.   
  7.     if (nat) {  
  8.   
  9.         const char *c_path = env->GetStringUTFChars(path, NULL);  
  10.   
  11.    
  12.   
  13.         bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,  
  14.   
  15.                                     c_path, "org.bluez.Input""Connect",  
  16.   
  17.                                     DBUS_TYPE_INVALID);  
  18.   
  19.    
  20.   
  21.         env->ReleaseStringUTFChars(path, c_path);  
  22.   
  23.         return ret ? JNI_TRUE : JNI_FALSE;  
  24.   
  25.     }  
  26.   
  27. #endif  
  28.   
  29.     return JNI_FALSE;  
  30.   
  31. }  
  32.   
  33.    
  34.   
  35. static jboolean disconnectSinkNative(JNIEnv *env, jobject object,  
  36.   
  37.                                      jstring path) {  
  38.   
  39. #ifdef HAVE_BLUETOOTH  
  40.   
  41.     LOGV(__FUNCTION__);  
  42.   
  43.     if (nat) {  
  44.   
  45.         const char *c_path = env->GetStringUTFChars(path, NULL);  
  46.   
  47.    
  48.   
  49.         bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,  
  50.   
  51.                                     c_path, "org.bluez.Input""Disconnect",  
  52.   
  53.                                     DBUS_TYPE_INVALID);  
  54.   
  55.    
  56.   
  57.         env->ReleaseStringUTFChars(path, c_path);  
  58.   
  59.         return ret ? JNI_TRUE : JNI_FALSE;  
  60.   
  61.     }  
  62.   
  63. #endif  
  64.   
  65.     return JNI_FALSE;  
  66.   
  67. }  
  

这里要注意将该文件添加到AndroidRuntime.cpp和Android.mk中,否则不会编译到动态库中。

此部分编译后最终生成libandroid_runtime.so并替换到system/libs下

二.Framework的java部分

路径framework/base/java/android/server/中添加BluetoothHidService.java文件

路径framework/base/java/android/bluetooth/中添加BluetoothHid.java和IBluetoothHid.aidl文件。

[java] view plaincopy
  1. interface IBluetoothHid {  
  2.   
  3.     boolean connect(in BluetoothDevice device);  
  4.   
  5.     boolean disconnect(in BluetoothDevice device);  
  6.   
  7.     int getState(in BluetoothDevice device);  
  8.   
  9.     boolean setPriority(in BluetoothDevice device, int priority);  
  10.   
  11.     int getPriority(in BluetoothDevice device);  
  12.   
  13. }  

BluetoothHid.java中主要的两个方法connect和disconnect间接地通过aidl访问BluetoothHidService。这里主要是实现跨进程并为上层提供可直接访问的方法。

由此framework的主要部分打包生成framework.Jar并最终部署到system/framework里。

三.应用(Settings.apk)

最后需要修改应用部分,应用部分的修改点比较分散,不想框架层那样整块模仿A2DP的样子那么方便,但也不是说jni部分有多么容易。反而对于我这种对C语言不熟悉的人来说,修改jni是最头疼得事了。好在蓝牙HID 这部分框架层的修改都是整块进行的,理解上还算比价容易。

总的来说在Settings.apk中要修改的文件主要是这么几个:

LocalBluetoothProfileManager.java 这里主要提供一个HID的profile以便应用层访问。建一个HIDProfile的class调用framework中的BluetoothHID。实际上就是通过bender机制调用了BluetoothHidService

CashedBluetoothDevice中添加显示蓝牙键盘的图标,BluetoothPairingDialog中则需要添加一段蓝牙配对验证处理的代码,我是参照i9000中先弹出一个随机数,然后在键盘中敲入相同的随机数即配对成功,具体实现如下:

[java] view plaincopy
  1. Private view createView(){  
  2.   
  3. if (mType == BluetoothDevice.PAIRING_VARIANT_PIN) {  
  4.   
  5. ……  
  6.   
  7.                  // HID  
  8.   
  9.                             if (isDeviceKeyboard(mDevice)) {  
  10.   
  11.                                      String pin = String.format("%06d", Long.valueOf(Math  
  12.   
  13.                                                         .abs(new Random().nextLong() % 1000000L)));  
  14.   
  15.                                      mPairingView.setVisibility(View.GONE);  
  16.   
  17.                                      messageView.setText(getString(  
  18.   
  19.                                                         R.string.bluetooth_enter_keyboard_pin_msg, pin, name));  
  20.   
  21.    
  22.   
  23.                                      byte[] bytePin = BluetoothDevice.convertPinToBytes(pin);  
  24.   
  25.                                      if (bytePin != null) {  
  26.   
  27.                                                mDevice.setPin(bytePin);  
  28.   
  29.                                      }  
  30.   
  31.                             }  
  32.   
  33. ……  
  34.   
  35. }  
  

以上为android中实现蓝牙键盘的具体步骤。

 

参考博客:Android 上实现蓝牙的一些Profilehttp://blog.163.com/hancker_31/blog/static/3558736120113271253306/

0 0