【问题标题】:Connect multiple devices to one device via Bluetooth通过蓝牙将多台设备连接到一台设备
【发布时间】:2013-10-06 08:45:39
【问题描述】:

我想创建一个游戏,您必须通过蓝牙将多个设备 (4+) 连接到一个主设备(例如平板电脑)。将有两个应用程序,一个主要的应用程序,所有数据将从手机发送到手机,然后发送到手机。 这可能吗?

【问题讨论】:

标签: android bluetooth android-bluetooth


【解决方案1】:

是的,这是可能的。在最低级别的蓝牙允许您将多达 7 个设备连接到一个主设备。我已经这样做了,它对我来说效果很好,但只在我有很多手动控制的其他平台(linux)上 - 我从来没有在 Android 上尝试过,并且有一些可能的并发症,所以你需要做一些测试确定。

其中一个问题是您需要将平板电脑控制在主机上,而 Android 并没有给您任何明确的控制权。这很可能不会成为问题,因为 * 当您尝试将第二台设备连接到平板电脑时,平板电脑将自动成为主机,或者 * 您将能够通过设置套接字连接的方式来控制主/从角色

我会提醒您,尽管大多数在移动设备上使用蓝牙的应用都不会尝试许多同时连接,而且蓝牙可能有点脆弱,例如如果两台设备已经为其他应用建立了蓝牙连接怎么办?这会如何影响角色?

【讨论】:

    【解决方案2】:

    蓝牙 4.0 允许您在一个蓝牙微微网中,一个主设备最多可以与 7 个活动从设备通信,其他设备最多可以有 248 个处于休眠状态的设备。

    您还可以使用一些从站作为桥接器来参与更多设备。

    【讨论】:

      【解决方案3】:

      是的,您可以这样做,我已经为此创建了 a library
      这允许您将最多四个设备连接到主服务器设备,为每个客户端创建不同的通道并在不同的线程上运行交互。
      要使用这个库,只需在 build.gradle 的依赖部分添加 compile com.mdg.androble:library:0.1.2

      【讨论】:

      • 我已经下载了你的库,但是在网络包中有一些编译问题
      【解决方案4】:

      这是建立连接和接收消息的类。 确保在运行应用程序之前配对设备。 如果你想有一个slave/master连接,每个slave只能向master发送消息,而master可以向所有slave广播消息。 您应该只将 master 与每个 slave 配对,但不应该将 slave 配对。

          package com.example.gaby.coordinatorv1;
          import java.io.DataInputStream;
          import java.io.IOException;
          import java.io.InputStream;
          import java.io.OutputStream;
          import java.util.ArrayList;
          import java.util.HashMap;
          import java.util.Set;
          import java.util.UUID;
          import android.bluetooth.BluetoothAdapter;
          import android.bluetooth.BluetoothDevice;
          import android.bluetooth.BluetoothServerSocket;
          import android.bluetooth.BluetoothSocket;
          import android.content.Context;
          import android.os.Bundle;
          import android.os.Handler;
          import android.os.Message;
          import android.util.Log;
          import android.widget.Toast;
      
          public class Piconet {
      
      
              private final static String TAG = Piconet.class.getSimpleName();
      
              // Name for the SDP record when creating server socket
              private static final String PICONET = "ANDROID_PICONET_BLUETOOTH";
      
              private final BluetoothAdapter mBluetoothAdapter;
      
              // String: device address
              // BluetoothSocket: socket that represent a bluetooth connection
              private HashMap<String, BluetoothSocket> mBtSockets;
      
              // String: device address
              // Thread: thread for connection
              private HashMap<String, Thread> mBtConnectionThreads;
      
              private ArrayList<UUID> mUuidList;
      
              private ArrayList<String> mBtDeviceAddresses;
      
              private Context context;
      
      
              private Handler handler = new Handler() {
                  public void handleMessage(Message msg) {
                      switch (msg.what) {
                          case 1:
                              Toast.makeText(context, msg.getData().getString("msg"), Toast.LENGTH_SHORT).show();
                              break;
                          default:
                              break;
                      }
                  };
              };
      
              public Piconet(Context context) {
                  this.context = context;
      
                  mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
      
                  mBtSockets = new HashMap<String, BluetoothSocket>();
                  mBtConnectionThreads = new HashMap<String, Thread>();
                  mUuidList = new ArrayList<UUID>();
                  mBtDeviceAddresses = new ArrayList<String>();
      
                  // Allow up to 7 devices to connect to the server
                  mUuidList.add(UUID.fromString("a60f35f0-b93a-11de-8a39-08002009c666"));
                  mUuidList.add(UUID.fromString("54d1cc90-1169-11e2-892e-0800200c9a66"));
                  mUuidList.add(UUID.fromString("6acffcb0-1169-11e2-892e-0800200c9a66"));
                  mUuidList.add(UUID.fromString("7b977d20-1169-11e2-892e-0800200c9a66"));
                  mUuidList.add(UUID.fromString("815473d0-1169-11e2-892e-0800200c9a66"));
                  mUuidList.add(UUID.fromString("503c7434-bc23-11de-8a39-0800200c9a66"));
                  mUuidList.add(UUID.fromString("503c7435-bc23-11de-8a39-0800200c9a66"));
      
                  Thread connectionProvider = new Thread(new ConnectionProvider());
                  connectionProvider.start();
      
              }
      
      
      
              public void startPiconet() {
                  Log.d(TAG, " -- Looking devices -- ");
                  // The devices must be already paired
                  Set<BluetoothDevice> pairedDevices = mBluetoothAdapter
                          .getBondedDevices();
                  if (pairedDevices.size() > 0) {
                      for (BluetoothDevice device : pairedDevices) {
                          // X , Y and Z are the Bluetooth name (ID) for each device you want to connect to
                          if (device != null && (device.getName().equalsIgnoreCase("X") || device.getName().equalsIgnoreCase("Y")
                                  || device.getName().equalsIgnoreCase("Z") || device.getName().equalsIgnoreCase("M"))) {
                              Log.d(TAG, " -- Device " + device.getName() + " found --");
                              BluetoothDevice remoteDevice = mBluetoothAdapter
                                      .getRemoteDevice(device.getAddress());
                              connect(remoteDevice);
                          }
                      }
                  } else {
                      Toast.makeText(context, "No paired devices", Toast.LENGTH_SHORT).show();
                  }
              }
      
              private class ConnectionProvider implements Runnable {
                  @Override
                  public void run() {
                      try {
                          for (int i=0; i<mUuidList.size(); i++) {
                              BluetoothServerSocket myServerSocket = mBluetoothAdapter
                                      .listenUsingRfcommWithServiceRecord(PICONET, mUuidList.get(i));
                              Log.d(TAG, " ** Opened connection for uuid " + i + " ** ");
      
                              // This is a blocking call and will only return on a
                              // successful connection or an exception
                              Log.d(TAG, " ** Waiting connection for socket " + i + " ** ");
                              BluetoothSocket myBTsocket = myServerSocket.accept();
                              Log.d(TAG, " ** Socket accept for uuid " + i + " ** ");
                              try {
                                  // Close the socket now that the
                                  // connection has been made.
                                  myServerSocket.close();
                              } catch (IOException e) {
                                  Log.e(TAG, " ** IOException when trying to close serverSocket ** ");
                              }
      
                              if (myBTsocket != null) {
                                  String address = myBTsocket.getRemoteDevice().getAddress();
      
                                  mBtSockets.put(address, myBTsocket);
                                  mBtDeviceAddresses.add(address);
      
                                  Thread mBtConnectionThread = new Thread(new BluetoohConnection(myBTsocket));
                                  mBtConnectionThread.start();
      
                                  Log.i(TAG," ** Adding " + address + " in mBtDeviceAddresses ** ");
                                  mBtConnectionThreads.put(address, mBtConnectionThread);
                              } else {
                                  Log.e(TAG, " ** Can't establish connection ** ");
                              }
                          }
                      } catch (IOException e) {
                          Log.e(TAG, " ** IOException in ConnectionService:ConnectionProvider ** ", e);
                      }
                  }
              }
      
              private class BluetoohConnection implements Runnable {
                  private String address;
      
                  private final InputStream mmInStream;
      
                  public BluetoohConnection(BluetoothSocket btSocket) {
      
                      InputStream tmpIn = null;
      
                      try {
                          tmpIn = new DataInputStream(btSocket.getInputStream());
                      } catch (IOException e) {
                          Log.e(TAG, " ** IOException on create InputStream object ** ", e);
                      }
                      mmInStream = tmpIn;
                  }
                  @Override
                  public void run() {
                      byte[] buffer = new byte[1];
                      String message = "";
                      while (true) {
      
                          try {
                              int readByte = mmInStream.read();
                              if (readByte == -1) {
                                  Log.e(TAG, "Discarting message: " + message);
                                  message = "";
                                  continue;
                              }
                              buffer[0] = (byte) readByte;
      
                              if (readByte == 0) { // see terminateFlag on write method
                                  onReceive(message);
                                  message = "";
                              } else { // a message has been recieved
                                  message += new String(buffer, 0, 1);
                              }
                          } catch (IOException e) {
                              Log.e(TAG, " ** disconnected ** ", e);
                          }
      
                          mBtDeviceAddresses.remove(address);
                          mBtSockets.remove(address);
                          mBtConnectionThreads.remove(address);
                      }
                  }
              }
      
              /**
               * @param receiveMessage
               */
              private void onReceive(String receiveMessage) {
                  if (receiveMessage != null && receiveMessage.length() > 0) {
                      Log.i(TAG, " $$$$ " + receiveMessage + " $$$$ ");
                      Bundle bundle = new Bundle();
                      bundle.putString("msg", receiveMessage);
                      Message message = new Message();
                      message.what = 1;
                      message.setData(bundle);
                      handler.sendMessage(message);
                  }
              }
      
              /**
               * @param device
               * @param uuidToTry
               * @return
               */
              private BluetoothSocket getConnectedSocket(BluetoothDevice device, UUID uuidToTry) {
                  BluetoothSocket myBtSocket;
                  try {
                      myBtSocket = device.createRfcommSocketToServiceRecord(uuidToTry);
                      myBtSocket.connect();
                      return myBtSocket;
                  } catch (IOException e) {
                      Log.e(TAG, "IOException in getConnectedSocket", e);
                  }
                  return null;
              }
      
              private void connect(BluetoothDevice device) {
                  BluetoothSocket myBtSocket = null;
                  String address = device.getAddress();
                  BluetoothDevice remoteDevice = mBluetoothAdapter.getRemoteDevice(address);
                  // Try to get connection through all uuids available
                  for (int i = 0; i < mUuidList.size() && myBtSocket == null; i++) {
                      // Try to get the socket 2 times for each uuid of the list
                      for (int j = 0; j < 2 && myBtSocket == null; j++) {
                          Log.d(TAG, " ** Trying connection..." + j + " with " + device.getName() + ", uuid " + i + "...** ");
                          myBtSocket = getConnectedSocket(remoteDevice, mUuidList.get(i));
                          if (myBtSocket == null) {
                              try {
                                  Thread.sleep(200);
                              } catch (InterruptedException e) {
                                  Log.e(TAG, "InterruptedException in connect", e);
                              }
                          }
                      }
                  }
                  if (myBtSocket == null) {
                      Log.e(TAG, " ** Could not connect ** ");
                      return;
                  }
                  Log.d(TAG, " ** Connection established with " + device.getName() +"! ** ");
                  mBtSockets.put(address, myBtSocket);
                  mBtDeviceAddresses.add(address);
                  Thread mBluetoohConnectionThread = new Thread(new BluetoohConnection(myBtSocket));
                  mBluetoohConnectionThread.start();
                  mBtConnectionThreads.put(address, mBluetoohConnectionThread);
      
              }
      
              public void bluetoothBroadcastMessage(String message) {
                  //send message to all except Id
                  for (int i = 0; i < mBtDeviceAddresses.size(); i++) {
                      sendMessage(mBtDeviceAddresses.get(i), message);
                  }
              }
      
              private void sendMessage(String destination, String message) {
                  BluetoothSocket myBsock = mBtSockets.get(destination);
                  if (myBsock != null) {
                      try {
                          OutputStream outStream = myBsock.getOutputStream();
                          final int pieceSize = 16;
                          for (int i = 0; i < message.length(); i += pieceSize) {
                              byte[] send = message.substring(i,
                                      Math.min(message.length(), i + pieceSize)).getBytes();
                              outStream.write(send);
                          }
                          // we put at the end of message a character to sinalize that message
                          // was finished
                          byte[] terminateFlag = new byte[1];
                          terminateFlag[0] = 0; // ascii table value NULL (code 0)
                          outStream.write(new byte[1]);
                      } catch (IOException e) {
                          Log.d(TAG, "line 278", e);
                      }
                  }
              }
      
          }
      

      你的主要活动应该如下:

      package com.example.gaby.coordinatorv1;
      
      import android.app.Activity;
      import android.os.Bundle;
      import android.view.View;
      import android.widget.Button;
      
      public class MainActivity extends Activity {
      
          private Button discoveryButton;
          private Button messageButton;
      
          private Piconet piconet;
      
          @Override
          public void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              piconet = new Piconet(getApplicationContext());
      
              messageButton = (Button) findViewById(R.id.messageButton);
              messageButton.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
                      piconet.bluetoothBroadcastMessage("Hello World---*Gaby Bou Tayeh*");
                  }
              });
      
              discoveryButton = (Button) findViewById(R.id.discoveryButton);
              discoveryButton.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
                      piconet.startPiconet();
                  }
              });
      
          }
      
      }
      

      这是 XML 布局:

      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      tools:context=".MainActivity" >
      
      <Button
          android:id="@+id/discoveryButton"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="Discover"
          />
      
      <Button
          android:id="@+id/messageButton"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="Send message"
          />
      

      不要忘记在您的清单文件中添加以下权限:

          <uses-permission android:name="android.permission.BLUETOOTH" />
      <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
      

      【讨论】:

      • 嗨,我需要用蓝牙设备(BLE_V4)将我的 Android 手机连接到 5 个 arduino,我可以这样执行你的代码吗?目前我刚刚将手机与单个 BLE V4 配对,我可以发送数据。谢谢。
      【解决方案5】:

      如果它是广播方法中的串行数据,我认为它可能提供。但您将无法将任何语音/音频数据传输到其他从设备。根据蓝牙 4.0,该协议不支持此功能。然而,在广播音频/语音数据方面正在进行改进。

      【讨论】:

        【解决方案6】:

        这是部分可能的(最多 2 台设备),因为设备只能同时连接到另一台设备。在您的情况下,更好的解决方案是创建一个将信息发送到其他设备的 TCP 服务器——但这当然需要互联网连接。另请阅读 Samsung Chord API - 它提供了您需要的功能,但每个设备都必须连接到同一个 Wi-Fi 网络

        【讨论】:

          【解决方案7】:

          我认为蓝牙不可能,但您可以尝试查看WiFi Peer-to-Peer
          允许一对多连接。

          【讨论】:

          • 不需要路由器就在附近,对吧?有安卓设备就够了?
          • AFAIK 你不需要路由器。我认为它将其中一台设备变成热点(当然,没有互联网接入)并让其他设备连接到它。
          • 为什么会禁用普通wifi?
          • 我的意思是说其他人没有权限使用你的互联网。
          • 已经存在。 Superbeam 使用它来设置 WiFi-direct 以交换文件。如果我没记错的话,galaxy 手机有 S-Beam,它还使用 NFC 设置 WiFi 直接连接来交换文件。 - 不要与 Android Beam 混淆,后者使用 NFC 设置蓝牙连接来交换文件,这会稍微慢一点
          猜你喜欢
          • 2015-07-13
          • 2013-02-05
          • 2018-02-06
          • 2020-01-27
          • 1970-01-01
          • 1970-01-01
          • 2016-12-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多