2012-04-26 22 views
4

私には発見できないデバイスがたくさんありますが、それらのMACアドレスはわかっています。現時点では私は私のConnectThreadでこれを使用して複数のデバイスに接続することができます。私は2.3以前のデバイスのために安全ではないRFCOMMをサポートしたいということでAndroid - ペアリングせずに複数のBluetoothデバイスに接続する

Method m = device.getClass().getMethod("createRfcommSocket",new Class[] { int.class }); 

tmp = (BluetoothSocket) m.invoke(device, 1); 

問題。 Iその後、found this私が代わりにこれを行うことができます別の答えに:

tmp = InsecureBluetooth.createRfcommSocketToServiceRecord(device,MY_UUID, true); 

ペアリングを必要とせずに、単一のデバイスに接続するには完璧に動作します。

私の質問は、どのようにしてInsecureBluetoothクラスでも両方の世界を最大限に活用してリフレクションを使用することができますか?それともInsecureBluetoothクラス内で行う必要がありますか?あなたが安全でないbluetoothのソケット接続を作成するには、次のクラスを使用することができ

private static BluetoothSocket createRfcommSocketToServiceRecord(
     BluetoothDevice device, int port, UUID uuid, boolean encrypt) 
     throws IOException { 
    try { 
     BluetoothSocket socket = null; 
     Constructor<BluetoothSocket> constructor = BluetoothSocket.class 
       .getDeclaredConstructor(int.class, int.class, boolean.class, 
         boolean.class, BluetoothDevice.class, int.class, ParcelUuid.class); 
     if (constructor == null) 
      throw new RuntimeException("can't find the constructor for socket"); 

     constructor.setAccessible(true); 
     Field f_rfcomm_type = BluetoothSocket.class 
       .getDeclaredField("TYPE_RFCOMM"); 
     f_rfcomm_type.setAccessible(true); 
     int rfcomm_type = (Integer) f_rfcomm_type.get(null); 
     socket = constructor.newInstance(new Object[] { rfcomm_type, -1, false, 
       true, device, port, uuid != null ? new ParcelUuid(uuid) : null }); 
     return socket; 
    } catch (NoSuchMethodException e) { 
     throw new RuntimeException(e); 
    } catch (NoSuchFieldException e) { 
     throw new RuntimeException(e); 
    } catch (IllegalAccessException e) { 
     throw new RuntimeException(e); 
    } catch (InstantiationException e) { 
     throw new RuntimeException(e); 
    } catch (InvocationTargetException e) { 
     if (e.getCause() instanceof IOException) { 
      throw (IOException) e.getCause(); 
     } 
     throw new RuntimeException(e.getCause()); 
    } 
} 

public static BluetoothSocket createRfcommSocketToServiceRecord(
     BluetoothDevice device, UUID uuid, boolean encrypt) throws IOException { 
    return createRfcommSocketToServiceRecord(device, -1, uuid, encrypt); 
} 

public static BluetoothSocket createRfcommSocket(BluetoothDevice device, 
     int port, boolean encrypt) throws IOException { 
    return createRfcommSocketToServiceRecord(device, port, null, encrypt); 
} 

答えて

0

:ここInsecureBluetoothクラスの関連する部分があります。それは自動的にthisリンクを参照して、詳細情報については2.3.3

import java.io.IOException; 
import java.lang.reflect.Constructor; 
import java.lang.reflect.Field; 
import java.lang.reflect.InvocationTargetException; 
import java.lang.reflect.Method; 
import java.util.UUID; 

import android.bluetooth.BluetoothAdapter; 
import android.bluetooth.BluetoothDevice; 
import android.bluetooth.BluetoothServerSocket; 
import android.bluetooth.BluetoothSocket; 
import android.os.Binder; 
import android.os.Handler; 
import android.os.IBinder; 
import android.os.ParcelUuid; 
import android.util.Log; 

/** 
* Class to offer unsecure bluetooth socket connection.<br /> 
* It was intended to be used when building the app with API version below 10 (API < Android2.3.3) 
* @author waa 
* 
*/ 
@SuppressWarnings("all") 
public class UnpairedBluetooth { 
    static private class InUse extends RuntimeException { 
    } 

    public static BluetoothServerSocket listenUsingRfcommWithServiceRecord(BluetoothAdapter adapter, String name, UUID uuid, boolean encrypt) throws IOException { 
     try { 
      Class c_rfcomm_channel_picker = null; 
      Class[] children = BluetoothAdapter.class.getDeclaredClasses(); 
      for(Class c : children) { 
       Log.e("TO", "class " + c.getCanonicalName()); 
       if(c.getCanonicalName().equals(BluetoothAdapter.class.getName() + ".RfcommChannelPicker")) { 
        c_rfcomm_channel_picker = c; 
        break; 
       } 
      } 
      if(c_rfcomm_channel_picker == null) 
       throw new RuntimeException("can't find the rfcomm channel picker class"); 

      Constructor constructor = c_rfcomm_channel_picker.getDeclaredConstructor(UUID.class); 
      if(constructor == null) 
       throw new RuntimeException("can't find the constructor for rfcomm channel picker"); 
      Object rfcomm_channel_picker = constructor.newInstance(new Object[] {uuid}); 
      Method m_next_channel = c_rfcomm_channel_picker.getDeclaredMethod("nextChannel", new Class[] {}); 
      m_next_channel.setAccessible(true); 

      BluetoothServerSocket socket = null; 

      int channel; 
      int errno; 
      while (true) { 
       channel = (Integer)m_next_channel.invoke(rfcomm_channel_picker, new Object[] {}); 

       if (channel == -1) { 
        throw new IOException("No available channels"); 
       } 

       try { 
        socket = listenUsingRfcomm(channel, encrypt); 
        break; 
       } catch(InUse e) { 
        continue; 
       } 
      } 

      Field f_internal_service = adapter.getClass().getDeclaredField("mService"); 
      f_internal_service.setAccessible(true); 
      Object internal_service = f_internal_service.get(adapter); 

      Method m_add_rfcomm_service_record = internal_service.getClass().getDeclaredMethod("addRfcommServiceRecord", new Class[] {String.class, ParcelUuid.class, int.class, IBinder.class}); 
      m_add_rfcomm_service_record.setAccessible(true); 

      int handle = (Integer)m_add_rfcomm_service_record.invoke(internal_service, new Object[] { name, new ParcelUuid(uuid), channel, new Binder() }); 

      if (handle == -1) { 
       try { 
        socket.close(); 
       } catch (IOException e) {} 
       throw new IOException("Not able to register SDP record for " + name); 
      } 
      Field f_internal_handler = adapter.getClass().getDeclaredField("mHandler"); 
      f_internal_handler.setAccessible(true); 
      Object internal_handler = f_internal_handler.get(adapter); 

      Method m_set_close_handler = socket.getClass().getDeclaredMethod("setCloseHandler", new Class[] {Handler.class, int.class}); 
      m_set_close_handler.setAccessible(true); 

      m_set_close_handler.invoke(socket, new Object[] { internal_handler, handle}); 
      return socket; 
     } catch (NoSuchMethodException e) { 
      throw new RuntimeException(e); 
     } catch (NoSuchFieldException e) { 
      throw new RuntimeException(e); 
     } catch(IllegalAccessException e) { 
      throw new RuntimeException(e); 
     } catch(InstantiationException e) { 
      throw new RuntimeException(e); 
     } catch(InvocationTargetException e) { 
      if(e.getCause() instanceof IOException) { 
       throw (IOException)e.getCause(); 
      } 
      throw new RuntimeException(e.getCause()); 
     } 
    } 
    private static BluetoothServerSocket listenUsingRfcomm(/*BluetoothAdapter adapter, */ int port, boolean encrypt, boolean reuse) throws IOException, InUse { 
     BluetoothServerSocket socket = null; 
     try { 
      Constructor<BluetoothServerSocket> constructor = BluetoothServerSocket.class.getDeclaredConstructor(int.class, boolean.class, boolean.class, int.class); 
      if(constructor == null) 
       throw new RuntimeException("can't find the constructor"); 
      constructor.setAccessible(true); 
      Field f_rfcomm_type = BluetoothSocket.class.getDeclaredField("TYPE_RFCOMM"); 
      f_rfcomm_type.setAccessible(true); 
      int rfcomm_type = (Integer)f_rfcomm_type.get(null); 

      Field f_e_addr_in_use = BluetoothSocket.class.getDeclaredField("EADDRINUSE"); 
      f_e_addr_in_use.setAccessible(true); 
      int e_addr_in_use = (Integer)f_e_addr_in_use.get(null); 

      socket = constructor.newInstance(new Object[] { rfcomm_type, false, encrypt, port }); 

      Field f_internal_socket = socket.getClass().getDeclaredField("mSocket"); 
      f_internal_socket.setAccessible(true); 
      Object internal_socket = f_internal_socket.get(socket); 
      Method m_bind_listen = internal_socket.getClass().getDeclaredMethod("bindListen", new Class[] {}); 
      m_bind_listen.setAccessible(true); 
      Object result = m_bind_listen.invoke(internal_socket, new Object[] {}); 

      int errno = (Integer)result; 
      if(reuse && errno == e_addr_in_use) { 
       throw new InUse(); 
      } else if (errno != 0) { 
       try { 
        socket.close(); 
       } catch (IOException e) {} 
       internal_socket.getClass().getMethod("throwErrnoNative", new Class[] {int.class}).invoke(internal_socket, new Object[] { errno }); 
      } 
      return socket; 
     } catch (NoSuchMethodException e) { 
      throw new RuntimeException(e); 
     } catch (NoSuchFieldException e) { 
      throw new RuntimeException(e); 
     } catch(IllegalAccessException e) { 
      throw new RuntimeException(e); 
     } catch(InstantiationException e) { 
      throw new RuntimeException(e); 
     } catch(InvocationTargetException e) { 
      if(e.getCause() instanceof IOException) { 
       throw (IOException)e.getCause(); 
      } 
      throw new RuntimeException(e.getCause()); 
     } 
    } 
    public static BluetoothServerSocket listenUsingRfcomm(int port, boolean encrypt) throws IOException { 
     return listenUsingRfcomm(port, encrypt, false); 
    } 
    private static BluetoothSocket createRfcommSocketToServiceRecord(BluetoothDevice device, int port, UUID uuid, boolean encrypt) throws IOException { 
     try { 
      BluetoothSocket socket = null; 
      Constructor<BluetoothSocket> constructor = BluetoothSocket.class.getDeclaredConstructor(
        int.class, int.class, boolean.class, boolean.class, BluetoothDevice.class, int.class, ParcelUuid.class); 
      if(constructor == null) 
       throw new RuntimeException("can't find the constructor for socket"); 

      constructor.setAccessible(true); 
      Field f_rfcomm_type = BluetoothSocket.class.getDeclaredField("TYPE_RFCOMM"); 
      f_rfcomm_type.setAccessible(true); 
      int rfcomm_type = (Integer)f_rfcomm_type.get(null); 
//   socket = constructor.newInstance(new Object[] { rfcomm_type, -1, false, true, device, port, uuid != null ? new ParcelUuid(uuid) : null}); 
      socket = constructor.newInstance(new Object[] { rfcomm_type, -1, false, encrypt, device, port, uuid != null ? new ParcelUuid(uuid) : null}); 
      return socket; 
     } catch (NoSuchMethodException e) { 
      throw new RuntimeException(e); 
     } catch (NoSuchFieldException e) { 
      throw new RuntimeException(e); 
     } catch(IllegalAccessException e) { 
      throw new RuntimeException(e); 
     } catch(InstantiationException e) { 
      throw new RuntimeException(e); 
     } catch(InvocationTargetException e) { 
      if(e.getCause() instanceof IOException) { 
       throw (IOException)e.getCause(); 
      } 
      throw new RuntimeException(e.getCause()); 
     } 
    } 
    public static BluetoothSocket createRfcommSocketToServiceRecord(BluetoothDevice device, UUID uuid, boolean encrypt) throws IOException{ 
     return createRfcommSocketToServiceRecord(device, -1, uuid, encrypt); 
    } 
    public static BluetoothSocket createRfcommSocket(BluetoothDevice device, int port, boolean encrypt) throws IOException { 
     return createRfcommSocketToServiceRecord(device, port, null, encrypt); 
    } 
} 

の下にSDKのために、この機能を提供するために反射を処理します。

+0

はい、私の質問に含まれているのと同じクラスとリンクです。問題は、各デバイスでwhileループを実行すると、このメソッドを使用しているときに既に接続しているデバイスをオーバーライドするということです。私は私の質問を更新して、私が何を意味するのかをさらに説明します。 – 7wonders

+0

私はあなたが同じブルートゥースプロファイルのために一度に1つのデバイスに接続できると思います。ではない? – waqaslam

+0

はい、私は同時に複数のデバイスに接続し、それぞれのバックグラウンドでデータ検索を実行したいと考えています。 – 7wonders

関連する問題