I would like to create a game, where you must connect multiple devices (4+) to a main device (ex. a tablet) via Bluetooth. There would be two apps, a main one to which all data would be send from the phones, and to the phones. Is that even possible?
-
Were you able to get it working ? – Jake Mar 27 '14 at 01:01
-
Yes it's possible with this library : https://github.com/arissa34/Android-Multi-Bluetooth-Library – Rami Jul 09 '17 at 13:58
-
Is there a similar library for iOS? – chikitin Mar 22 '21 at 00:20
7 Answers
Yes, that is possible. At its lowest level Bluetooth allows you to connect up to 7 devices to one master device. I have done this and it has worked well for me, but only on other platforms (linux) where I had lots of manual control - I've never tried that on Android and there are some possible complications so you will need to do some testing to be certain.
One of the issues is that you need the tablet to the master and Android doesn't give you any explicit control of this. It is likely that this won't be a problem because * the tablet will automatically become the master when you try to connect a second device to it, or * you will be able to control the master/slave roles by how you setup your socket connection
I will caution though that most apps using Bluetooth on mobile are not attempting many simultaneous connections and Bluetooth can be a bit fragile, e.g. what if two devices already have a Bluetooth connection for some other app - how might that affect the roles?

- 17,103
- 8
- 67
- 75
Bluetooth 4.0 Allows you in a Bluetooth piconet one master can communicate up to 7 active slaves, there can be some other devices up to 248 devices which sleeping.
Also you can use some slaves as bridge to participate with more devices.

- 2,727
- 26
- 37
Yes you can do so and I have created a library for the same.
This allows you to connect up-to four devices to the main server device creating different channels for each client and running interactions on different threads.
To use this library simple add compile com.mdg.androble:library:0.1.2
in dependency section of your build.gradl
e .

- 1,220
- 10
- 28

- 31
- 1
- 3
-
2I have downloaded your library but it has some compilation problems in network packege – eyal May 06 '18 at 16:09
This is the class where the connection is established and messages are recieved. Make sure to pair the devices before you run the application. If you want to have a slave/master connection, where each slave can only send messages to the master , and the master can broadcast messages to all slaves. You should only pair the master with each slave , but you shouldn't pair the slaves together.
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);
}
}
}
}
Your main activity should be as follow :
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();
}
});
}
}
And here's the XML Layout :
<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"
/>
Do not forget to add the following permissions to your Manifest File :
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

- 151
- 1
- 3
-
Hi, i need to connect my Android mobile phone to 5 arduino with bluetooth devices (BLE_V4), could i perform your code in this way? Currently i've just paired the mobile to a single BLE V4 and i can send data. Thx. – Billyjoker Jul 30 '18 at 13:13
I think its possible provided if it is a serial data in broadcasting method. but you will not be able to transfer any voice/audio data to the other slave device. As per Bluetooth 4.0, the protocol does not support this. However there is a improvement going on to broadcast the audio/voice data.

- 1
That is partly possible (for max 2 devices), because device can be connected only to one other device same time. Better solution in your case will be create an TCP server which sends informations to other devices - but that, of course, requires internet connection. Read also about Samsung Chord API - it provides functions which you need, but then every devices have to be connected to one and the same Wi-Fi network

- 7,659
- 9
- 48
- 84
I don't think it's possible with bluetooth, but you could try looking into WiFi Peer-to-Peer,
which allows one-to-many connections.

- 2,007
- 5
- 26
- 37
-
It doesn't require that a router will be nearby, right? it's enough to have Android devices around ? – android developer Mar 22 '14 at 17:43
-
AFAIK you don't need a router. I think it turns one of the devices into a hotspot (without internet access, ofcourse) and lets the other devices connect to it. – Andreas Mar 22 '14 at 22:59
-
-
I meant to say that the others wouldn't have permission to use your internet. – Andreas Mar 24 '14 at 10:05
-
I wonder if it's possible to overcome the limitation of max users being connected, by making a chain of them. – android developer Mar 24 '14 at 10:19
-
I'm not sure what the maximum amount of connections is for p2p wifi, but as soon as you go over a certain amount of connections, I'm sure it would be a better idea to use a server. – Andreas Mar 24 '14 at 11:12
-
I see. thanks. so you say that if 2 devices are connected via wifi, it doesn't mean they can't surf the web using a router, right? – android developer Mar 24 '14 at 13:28
-
not sure about that. They should be able to surf using data, but I don't know if they can do it through WiFi. – Andreas Mar 24 '14 at 14:03
-
I've now tested. both connected devices can surf the web just fine via the WIFI . However, for some reason, even though i've read on the internet that Wifi direct doesn't need an active WIFI, I can't disable WIFI and enable WIFI-direct. – android developer Mar 24 '14 at 16:04
-
Connecting via WiFi-direct doesn't require an active WiFi connection. You can do the setup with NFC or something similar. The connection itself does require **WiFi** to communicate **directly** with the other device (It wouldn't be called WiFi-direct if it didn't require WiFi). Also, what you need isn't wifi direct, but peer to peer wifi (if you want to connect to more than 1 person) – Andreas Mar 25 '14 at 08:15
-
-
You send the connection info with the NFC chip, and whoever reads the info can use it to connect to you. It's a bit like wifi-protected setup (WPS) on your router – Andreas Mar 26 '14 at 08:53
-
I meant, do you have it as a built in feature on Android? and if so, how do you do it? of course that if it doesn't exist, you can make apps... :) – android developer Mar 26 '14 at 09:09
-
1It already exists. Superbeam uses it to setup WiFi-direct to exchange files. The galaxy phones have S-Beam, if I'm not mistaken, which also uses NFC to setup a WiFi-direct connection to exchange files. - Not to be confused with Android beam, which uses NFC to setup a bluetooth connection to exchange files and is this slightly slower – Andreas Mar 26 '14 at 09:13
-
So it's not built in, and there are apps (stock or third party) that uses it. ok, thank you. so it seems Wifi-direct can be established via NFC only by using apps. what about the sharing part? it seems that even though i've connected 2 devices via Wifi-direct, and I choose a photo on the gallery app (of google), I can't see the ability to share it via Wifi-direct. Some videos show that it does exist. How could it be? – android developer Mar 26 '14 at 09:41
-
Wifi-direct en WiFi P2P are built in, as is NFC. Combining those is something you will have to do in your app (if it's usefull, at least; please don't put things in just because). Other people are able to do it because 1) they have a samsung device, 2) they use a custom rom, 3) they have an app that allows it – Andreas Mar 26 '14 at 09:48
-
I don't understand. I meant that there was an item called "wifi-direct" on a video I've watched, when you click on the sharing button. is it also not built in? – android developer Mar 26 '14 at 09:56
-
-
I'm quite sure it was demonstrated on the nexus device, on its gallery app. – android developer Mar 26 '14 at 10:04
-
-