2013-06-02 241 views
3

我試圖將wiimote連接到我的OUYA(運行Android 4.1.2)。我已經成功地得到的wiimote使用像Bluez-IME其他應用程序連接起來,所以我知道這是可能的,但我希望能夠做我自己Android wiimote套接字無法連接

這是我到目前爲止有:

private void bloothoothConnect(final BluetoothAdapter mBluetoothAdapter){ 

    // Register the BroadcastReceiver 
    IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); 
    filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); 
    filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); 
    registerReceiver(new BroadcastReceiver() { 
     public void onReceive(Context context, Intent intent) { 
      String action = intent.getAction(); 
      // 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);    
       if(isWiiMote(device)){ 
        mBluetoothAdapter.cancelDiscovery(); 
        connectWiiMote(device);      
       } 
      } 
     } 
    }, filter); 

    mBluetoothAdapter.startDiscovery(); 
} 

private boolean isWiiMote(BluetoothDevice device){ 
    String name = device.getName();     
    return name.equalsIgnoreCase("Nintendo RVL-CNT-01");   
} 

private void connectWiiMote(final BluetoothDevice device){ 
    final int tickInterval = 30; 
    WiimoteRunnable nWiiMote = new WiimoteRunnable(device, tickInterval){ 

     @Override 
     protected void onButtonDown() { // TODO       
     }}; 

    Thread nThread = new Thread(nWiiMote); 
    nThread.start();  
} 

private abstract class WiimoteRunnable implements Runnable{ 

    private BluetoothSocket socket; 
    private long tickInterval; 
    private byte[] buffer = new byte[1024]; 

    WiimoteRunnable(BluetoothDevice device, long tickInterval) { 
     socket = createL2CAPBluetoothSocket(device); 
     this.tickInterval = tickInterval;   
    } 

    @SuppressLint("NewApi") 
    @Override 
    public void run() { 

     try { 
      if(!socket.isConnected()){ 
       // blocks here! 
       socket.connect(); 
      } 
      InputStream iStream = socket.getInputStream(); 

      while(socket.isConnected()){ 

       iStream.read(buffer); 

       // do stuff with byte buffer here 

       Thread.sleep(tickInterval);         
      } 

     } catch (IOException e2) { 
      closeSocket(); 
     } catch (InterruptedException e) { 
      closeSocket(); 
      return; 
     } 

    } 

    private void closeSocket(){   
     try { 
      socket.close(); 
     } catch (IOException e) { 
      return; 
     } 
    } 

    // to be implemented later 
    protected abstract void onButtonDown(); 

} 


// see https://stackoverflow.com/questions/14761570/connecting-to-a-bluetooth-hid-device-mouse-using-l2cap 

private static final int TYPE_L2CAP = 3; 

/** 
* Create a BluetoothSocket using L2CAP protocol 
* Useful for HID Bluetooth devices 
* @param BluetoothDevice 
* @return BluetoothSocket 
*/ 
@SuppressLint("NewApi") 
private static BluetoothSocket createL2CAPBluetoothSocket(BluetoothDevice device){ 
    int type  = TYPE_L2CAP; // L2CAP protocol 
    int fd   = -1;   // Create a new socket 
    boolean auth = false;  // No authentication 
    boolean encrypt = false;  // Not encrypted 
    int port  = 0;   // port to use (useless if UUID is given) 

    ParcelUuid[] uuid = device.getUuids(); // Bluetooth UUID service 
    if(uuid==null){ 
     if(!device.fetchUuidsWithSdp()){ 
      return null; 
     } else { 
      uuid = device.getUuids(); 
     } 
    } 


    try { 
    Constructor<BluetoothSocket> constructor = BluetoothSocket.class.getDeclaredConstructor(
     int.class, int.class, boolean.class, boolean.class, 
     BluetoothDevice.class, int.class, ParcelUuid.class); 
    constructor.setAccessible(true); 
    BluetoothSocket clientSocket = (BluetoothSocket) constructor.newInstance(
     type, fd, auth, encrypt, device, port, uuid[0]); 
    return clientSocket; 
    } catch (Exception e) { 
    e.printStackTrace(); 
    return null; 
    } 
} 

問題是,當我到達socket.connect()它阻止並從不返回。套接字對象在那裏,在調試器中,我可以看到它的所有數據。

我得到的插座,每Connecting to a bluetooth HID device (mouse) using L2CAP

回答

2

而不是使用你需要使用(在你的代碼或端口號)的頻道號碼的L2CAP插座的UUID。要連接到wiimote,您需要分別打開套接字來控制(從您的應用程序到wiimote的命令)和數據(從您的應用程序輸入wiimote)頻道。

private static final int CONTROL_CHANNEL = 0x11; 
private static final int DATA_CHANNEL = 0x13; 

private BluetoothSocket controlSocket; 
private BluetoothSocket dataSocket; 

private OutputStream os; 
private InputStream is; 

private static BluetoothSocket createL2CAPBluetoothSocket(BluetoothDevice device, final int channel) { 
    int type = TYPE_L2CAP; // L2CAP protocol 
    int fd = -1; // Create a new socket 
    boolean auth = false; // No authentication 
    boolean encrypt = false; // Not encrypted 

    try { 
     Constructor<BluetoothSocket> constructor = BluetoothSocket.class.getDeclaredConstructor(int.class, 
       int.class, boolean.class, boolean.class, BluetoothDevice.class, int.class, ParcelUuid.class); 
     constructor.setAccessible(true); 
     BluetoothSocket clientSocket = (BluetoothSocket) constructor.newInstance(type, fd, auth, encrypt, device, 
       channel, null); 
     return clientSocket; 
    } catch (Exception e) { 
     e.printStackTrace(); 
     return null; 
    } 
} 

void connect(BluetoothDevice device) { 
    try { 
     controlSocket = createL2CAPBluetoothSocket(device, CONTROL_CHANNEL);   
     controlSocket.connect(); 
     os = controlSocket.getOutputStream(); 

     dataSocket = createL2CAPBluetoothSocket(device, DATA_CHANNEL); 
     dataSocket.connect(); 
     is = dataSocket.getInputStream();  

     // open transmit & receive threads for input and output streams appropriately 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 
+0

謝謝!完美按鈕按下!試圖獲得加速度計數據以及la:http://wiibrew.org/wiki/Wiimote –

+0

有誰知道如果l2cap回聲請求(如l2ping如何工作)在Android中支持和如何?這個示例代碼期望一個頻道,但我相信回聲請求將沒有頻道。感謝幫助! –