lynn3653 发表于 2014-10-25 11:59:03

接《利用wifi实现android手机远程遥控》续---蓝牙版

本帖最后由 lynn3653 于 2014-10-25 11:59 编辑

       前篇帖子介绍了如何利用wifi实现android手机远程遥控,那假设wifi处于带宽紧张状态,导致命令丢失或延迟很大怎么办?鉴于一般目前的手机都配有蓝牙,我们可以使用蓝牙来实现此远程遥控,在已有wifi实现源码的状况下,只要将发送消息的Socket换成BluetoothSocket即可实现蓝牙版的android手机远程遥控哦~
下面具体看看有哪些修改即可实现吧~
按照Wifi实现远程遥控的技术要点,我们逐一替换成蓝牙实现,首先是搜索设备:
1)Wifi版本下Client端(android手机)Socket广播搜寻Server端(android开发板),获取Server端IP地址;蓝牙搜索则更简单,android已封装好相应的函数调用了,如下:

/* 取得默认的蓝牙适配器 */
    private BluetoothAdapter mBtAdapter = BluetoothAdapter.getDefaultAdapter();
/* 开始搜索 */
      mBtAdapter.startDiscovery();

两行代码Client端即开始搜索了。。。
那如何知道搜索到设备了呢?Wifi是需要自行完成Server端回应搜索,Client端进入循环在协定好的端口等待Server端回复,以获取到相应IP地址。蓝牙则还是更省事,Client端注册如下一个广播监听蓝牙搜索响应事件即可,Server端则需要确保蓝牙已打开并且能被其他设备搜索到,如下图:



Client端蓝牙搜索响应广播
// The BroadcastReceiver that listens for discovered devices and
    // changes the title when discovery is finished
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
      @Override
      public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Message msg = mHandler.obtainMessage();
            // When discovery finds a device
            if (BluetoothDevice.ACTION_FOUND.equals(action))
            {
                // Get the BluetoothDevice object from the Intent
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                String deviceName = new String(device.getName());
                Log.d(TAG, "BT found device name:"+ deviceName);
                // If it's already paired, skip it, because it's been listed already
                if (device.getBondState() != BluetoothDevice.BOND_BONDED)
                {
                  deviceNameList.add(device.getName());
                  deviceAddressList.add(device.getAddress());
                }

            }
            else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action))
            {
                Log.v(TAG, "Receive Bluetooth ACTION_DISCOVERY_FINISHED!");            
            }
            if(deviceNameList.size() > 0)
            {
                msg.what = HANDLER_FIND_DEVICES;   
            }
            else
            {
                msg.what = HANDLER_NODEVICES_CHECKNETWORK;
            }
            mHandler.sendMessage(msg);
      }
    };
   
实际以上方式是临时搜索到Server端,系统会自动弹出蓝牙配对窗口提示配对(如未在蓝牙设置界面手动配对成功过),此配对信息在app退出后是不被保存的!既然如此,那最好的做法是先到蓝牙设置界面手动将Client端与Server端进行配对!做法就不用笔者介绍了吧。。。。
如果配对成功了,那无需搜索我们也可以获取到Server端的信息,如下:
// Get a set of currently paired devices
      Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();

      /*将已配对的设备加入*/
      if (pairedDevices.size() > 0) {
            for (BluetoothDevice device : pairedDevices) {
                String deviceName = new String(device.getName());
                Log.d(TAG, "BT found device name:"+ deviceName);
                deviceNameList.add(device.getName());
                deviceAddressList.add(device.getAddress());   
            }            
      }

备注:这里完全由系统的蓝牙搜索协议搜索Server端,所以即使不是我们的Server端的蓝牙设备都会被搜索到,贸然去连接肯定失败,所以需要再想办法筛选出Server端!这个留待读者自行设计,欢迎回复讨论哦~

获取到Server端地址信息后,接下来就是收发消息转化成按键事件上报!
2)Wifi版本是将Client端的虚拟按键事件转化成简单字符串用Socket发送至Sever端,Server端解析字符串获得按键事件,并使用injectInputEvent方法向android上层上报按键事件;蓝牙版本只需将其中的Socket替换成BluetoothSocket,其他事与通信协议无关,自然无需修改。
Wifi下是用某个端口号(笔者使用的9999)在Client端与Server端建立TCP连接:
Client端:
socket_9999 = new Socket(serverAddress_s, 9999);//serverAddress_s为第一步Server端回复中取得

Server端:
try {
      mWifiServerSocket = new ServerSocket(9999, 3);
} catch (IOException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
}
Socket client = mWifiServerSocket.accept();


蓝牙版本类似:
Client端:
device = mBtAdapter.getRemoteDevice(BlueToothAddress);//BlueToothAddress为前面配对的或者临时搜索的蓝牙设备中取得
//创建一个Socket连接:只需要服务器在注册时的UUID号
                socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
                //连接
                socket.connect();

Server端:
try {
                  /* 创建一个蓝牙服务器
                     * 参数分别:服务器名称、UUID   */   
                  mBTServerSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(PROTOCOL_SCHEME_RFCOMM,
                            UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));   
                  break;               

                } catch (IOException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
                }   
BluetoothSocket socket = mBTServerSocket.accept();


至此蓝牙替换Wifi版本的android手机远程遥控即OK了!放上一张笔者成功运行的截面图


附源码!


金豌豆 发表于 2014-12-19 15:59:27

:handshake不错!!!!!

xiaofei 发表于 2016-7-8 16:29:58


谢谢分享

csworld 发表于 2016-10-29 16:37:53

多谢分享
页: [1]
查看完整版本: 接《利用wifi实现android手机远程遥控》续---蓝牙版