Android基于wifi的无线HID设备实现

    本文地址:http://www.tongxinmao.com/Article/Detail/id/402

    偶然间突发奇想,想到能不能让我们的在我们的手机设备上滑动触摸屏进而控制pc上的鼠标移动,也就说把我们的android设备当成是pc设备的触摸板呢?要想实现这个目标,首先要想一想android设备和pc设备之间的通讯基础是什么?这个通讯技术必须是android和pc同时支持的,目前看来也就是wifi,蓝牙。首先说一下蓝牙,蓝牙是一个提供个人局域网的安全无线电通讯技术,相对于wifi而言,蓝牙的功耗相对较低,尤其是BLE技术使得蓝牙的功耗可以和zigbee媲美了,并且android也支持了基于蓝牙的socket操作。但是pc上的java部分对于蓝牙的socket支持就不是很好了,实现起来比较麻烦。但是wifi虽然功耗相对蓝牙而言比较高了点,但是实现起来非常容易,就是socket就好了!所以在第一版本中,可以先使用wifi作为传输技术。
    解决了传输技术之后,还需要解决的是都有哪些数据类型,怎么传递数据,使用什么样的协议的问题。这些问题很关键,这涉及到以后的程序可扩展性问题,如果这部分欠缺考虑的话,那么后期的修改和扩展将是一个灾难。进过仔细考量之后,决定采用google的protobuf来封装所有的数据,因为protobuf灵活,小巧,高效,正好就是我要的。
    进过了几天的业余时间开发,终于出来了一个可以运行展示的初级版本,这个版本可以满足基本的需求。目前我已经将这个代码开源出来了,项目地址是github:https://github.com/CreateChance/WirelessHid

    UI的设计

    我要做的就是使用手机实现一个touchpad和keyboard,这就决定了UI的设计必须符合我们日常见到的实体touchpad和keyboard的样式。进过设计之后,touchpad部分设计为一个fragment,它的布局如下:

    ?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    <code class="hljs xml"><linearlayout android:layout_height="match_parent" android:layout_width="match_parent" android:orientation="vertical" xmlns:android="https://schemas.android.com/apk/res/android" xmlns:tools="https://schemas.android.com/tools">
     
        <linearlayout android:layout_height="0dp" android:layout_weight="1" android:layout_width="match_parent" android:orientation="horizontal">
     
            <linearlayout android:id="@+id/speed_control" android:layout_height="match_parent" android:layout_width="65dip" android:orientation="vertical">
     
                <togglebutton android:layout_height="0dp" android:layout_weight="1" android:layout_width="match_parent" android:tag="1" android:textoff="@string/speed_slow" android:texton="@string/speed_slow">
     
                <togglebutton android:layout_height="0dp" android:layout_weight="1" android:layout_width="match_parent" android:tag="3" android:textoff="@string/speed_medium" android:texton="@string/speed_medium">
     
                <togglebutton android:layout_height="0dp" android:layout_weight="1" android:layout_width="match_parent" android:tag="5" android:textoff="@string/speed_fast" android:texton="@string/speed_fast">
     
            </togglebutton></togglebutton></togglebutton></linearlayout>
     
            <view android:id="@+id/touchpad" android:layout_height="match_parent" android:layout_weight="1" android:layout_width="0dp">
     
            <view android:background="#2b2b2b" android:id="@+id/scrollzone" android:layout_height="match_parent" android:layout_width="65dip">
     
            <linearlayout android:id="@+id/scroll_speed_control" android:layout_height="match_parent" android:layout_width="65dip" android:orientation="vertical">
     
                <togglebutton android:layout_height="0dp" android:layout_weight="1" android:layout_width="match_parent" android:tag="1" android:textoff="@string/speed_slow" android:texton="@string/speed_slow">
     
                <togglebutton android:layout_height="0dp" android:layout_weight="1" android:layout_width="match_parent" android:tag="3" android:textoff="@string/speed_medium" android:texton="@string/speed_medium">
     
                <togglebutton android:layout_height="0dp" android:layout_weight="1" android:layout_width="match_parent" android:tag="5" android:textoff="@string/speed_fast" android:texton="@string/speed_fast">
     
            </togglebutton></togglebutton></togglebutton></linearlayout>
     
        </view></view></linearlayout>
     
        <linearlayout android:id="@+id/buttons" android:layout_height="65dip" android:layout_width="match_parent" android:orientation="horizontal"><button android:id="@+id/left_button" android:layout_height="match_parent" android:layout_weight="1" android:layout_width="0dp" android:tag="0" android:text="left"></button><button android:layout_height="match_parent" android:layout_weight="1" android:layout_width="0dp" android:tag="1"></button></linearlayout></linearlayout></code><button android:id="@+id/right_button" android:layout_height="match_parent" android:layout_weight="1" android:layout_width="0dp" android:tag="2" android:text="right"><code class="hljs xml">
     
         
     
    </code></button>

    运行时的效果如下:
    <img alt="这里写图片描述" src="https://www.2cto.com/uploadfile/Collfiles/20160614/20160614140910113.png" title="" kf="" ware="" vc="" "="" target="_blank" class="keylink" style="border-width: 0px; padding: 0px; margin: 0px auto; list-style: none; display: block; max-width: 630px; cursor: pointer; width: 630px; height: 354.375px;">vc+4tNTTwcujrNXisr+31tKyysfSu7j2ZnJhZ21lbnSjrNX7zOWyvL7WyOfPwqO6PC9wPg0KPHByZSBjbGFzcz0="brush:java;">

    这个布局中首先放上3个textview在一个LinearLayout这三个textview充当真实键盘上的3个led灯:num lock, caps lock, scroll lock。然后就是一个存放实际keyboard布局的LinearLayout容器,这么做的目的是这样的:因为手机的屏幕很小,想要放下一个标准键盘上的所有的按键肯定是不行的,因此需要将键盘分区,然后分别展示,这里的这个容器就是用来存放不同分区,不同布局的键盘部分。目前我把键盘分成了2个部分:主键盘部分,导航部分加上数字部分。其中主键盘部分是我们最常使用的部分,这部分包含了26个字母,0~9数字(字母上排),12个功能键等,导航部分就是上下左右键盘,上页下页部分等,数字部分就是数字小键盘和一些控制按键,我把导航键和数字键合并在一起了,这两部分的布局如下:
    主键盘部分:

    ?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    <code class="hljs xml"><keyboard>
        <layout>
            <key keycode="27" keylabel="Esc">
            <key keycode="112" keylabel="F1">
            <key keycode="113" keylabel="F2">
            <key keycode="114" keylabel="F3">
            <key keycode="115" keylabel="F4">
            <key keycode="116" keylabel="F5">
            <key keycode="117" keylabel="F6">
            <key keycode="118" keylabel="F7">
            <key keycode="119" keylabel="F8">
            <key keycode="120" keylabel="F9">
            <key keycode="121" keylabel="F10">
            <key keycode="122" keylabel="F11">
            <key keycode="123" keylabel="F12">
            <key keycode="127" keylabel="Del">
        </key></key></key></key></key></key></key></key></key></key></key></key></key></key></layout>
        <layout>
            <key keycode="192" keylabel="'" shiftlabel="~">
            <key keycode="49" keylabel="1" shiftlabel="!">
            <key keycode="50" keylabel="2" shiftlabel="\@">
            <key keycode="51" keylabel="3" shiftlabel="\#">
            <key keycode="52" keylabel="4" shiftlabel="$">
            <key keycode="53" keylabel="5" shiftlabel="%">
            <key keycode="54" keylabel="6" shiftlabel="^">
            <key keycode="55" keylabel="7" shiftlabel="&">
            <key keycode="56" keylabel="8" shiftlabel="*">
            <key keycode="57" keylabel="9" shiftlabel="(">
            <key keycode="48" keylabel="0" shiftlabel=")">
            <key keycode="45" keylabel="-" shiftlabel="_">
            <key keycode="61" keylabel="=" shiftlabel="+">
            <key keycode="8" keylabel="Backspace ←" weight="1.5">
        </key></key></key></key></key></key></key></key></key></key></key></key></key></key></layout>
        <layout>
            <key keycode="9" keylabel="Tab ↹" weight="1.5">
            <key keycode="81" keylabel="Q">
            <key keycode="87" keylabel="W">
            <key keycode="69" keylabel="E">
            <key keycode="82" keylabel="R">
            <key keycode="84" keylabel="T">
            <key keycode="89" keylabel="Y">
            <key keycode="85" keylabel="U">
            <key keycode="73" keylabel="I">
            <key keycode="79" keylabel="O">
            <key keycode="80" keylabel="P">
            <key keycode="91" keylabel="[" shiftlabel="{">
            <key keycode="93" keylabel="]" shiftlabel="}">
            <key keycode="92" keylabel="\\" shiftlabel="|">
        </key></key></key></key></key></key></key></key></key></key></key></key></key></key></layout>
        <layout>
            <key keycode="20" keylabel="Caps Lock" weight="1.5">
            <key keycode="65" keylabel="A">
            <key keycode="83" keylabel="S">
            <key keycode="68" keylabel="D">
            <key keycode="70" keylabel="F">
            <key keycode="71" keylabel="G">
            <key keycode="72" keylabel="H">
            <key keycode="74" keylabel="J">
            <key keycode="75" keylabel="K">
            <key keycode="76" keylabel="L">
            <key keycode="59" keylabel=";" shiftlabel=":">
            <key keycode="44" keylabel="'" shiftlabel=""">
            <key keycode="10" keylabel="Enter ↵" weight="3.0">
        </key></key></key></key></key></key></key></key></key></key></key></key></key></layout>
        <layout>
            <key keycode="16" keyfunc="Shift" keylabel="Shift ⇧" weight="1.5">
            <key keycode="90" keylabel="Z">
            <key keycode="88" keylabel="X">
            <key keycode="67" keylabel="C">
            <key keycode="86" keylabel="V">
            <key keycode="66" keylabel="B">
            <key keycode="78" keylabel="N">
            <key keycode="77" keylabel="M">
            <key keycode="44" keylabel="," shiftlabel="<">
            <key keycode="46" keylabel="." shiftlabel=">">
            <key keycode="47" keylabel="/" shiftlabel="\?">
            <key keycode="16" keyfunc="Shift" keylabel="Shift ⇧" weight="1.5">
        </key></key></key></key></key></key></key></key></key></key></key></key></layout>
        <layout>
            <key keycode="17" keylabel="Ctrl" weight="1.5">
            <key keycode="524" keylabel="Win">
            <key keycode="18" keylabel="Alt">
            <key keycode="32" keylabel=" " weight="10.0">
            <key keycode="18" keylabel="Alt">
            <key keycode="524" keylabel="Win">
            <key keycode="93" keylabel="Menu">
            <key keycode="17" keylabel="Ctrl" weight="1.5">
        </key></key></key></key></key></key></key></key></layout>
    </keyboard></code>

    导航键部分:

    ?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <code class="hljs xml"><keyboard>
        <layout>
            <key keycode="154" keylabel="Print\nScreen">
            <key keycode="145" keylabel="Scroll\nLock">
            <key keycode="19" keylabel="Pause\nBreak">
        </key></key></key></layout>
        <layout>
            <key keycode="155" keylabel="Insert">
            <key keycode="36" keylabel="Home">
            <key keycode="33" keylabel="Page Up">
        </key></key></key></layout>
        <layout>
            <key keycode="127" keylabel="Delete">
            <key keycode="35" keylabel="End">
            <key keycode="34" keylabel="Page Down">
        </key></key></key></layout>
        <layout>
            <key visible="false">
            <key keycode="38" keylabel="↑">
            <key visible="false">
        </key></key></key></layout>
        <layout>
            <key keycode="37" keylabel="←">
            <key keycode="40" keylabel="↓">
            <key keycode="39" keylabel="→">
        </key></key></key></layout>
    </keyboard></code>

    数字键部分:

    ?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    <code class="hljs xml"><keyboard>