Connect multiple devices to one device via Bluetooth
Solution 1
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?
Solution 2
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.
Solution 3
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 .
Solution 4
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" />
domen
Updated on October 13, 2020Comments
-
domen over 3 years
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?
-
android developer over 10 yearsIt doesn't require that a router will be nearby, right? it's enough to have Android devices around ?
-
Andreas over 10 yearsAFAIK 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.
-
android developer over 10 yearsWhy would it disable the normal wifi ?
-
Andreas over 10 yearsI meant to say that the others wouldn't have permission to use your internet.
-
android developer over 10 yearsI wonder if it's possible to overcome the limitation of max users being connected, by making a chain of them.
-
Andreas over 10 yearsI'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.
-
android developer over 10 yearsI 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?
-
Andreas over 10 yearsnot sure about that. They should be able to surf using data, but I don't know if they can do it through WiFi.
-
android developer over 10 yearsI'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.
-
Andreas over 10 yearsConnecting 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)
-
android developer over 10 yearsreally? how would you use NFC to establish the wifi-direct?
-
Andreas over 10 yearsYou 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
-
android developer over 10 yearsI 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... :)
-
Andreas over 10 yearsIt 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
-
android developer over 10 yearsSo 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?
-
Andreas over 10 yearsWifi-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
-
android developer over 10 yearsI 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?
-
Andreas over 10 yearscould be the app that has WiFi-direct build in
-
android developer over 10 yearsI'm quite sure it was demonstrated on the nexus device, on its gallery app.
-
Andreas over 10 yearsNexus 4 running 4.4.2; No wifi-direct in my gallery app
-
android developer over 10 yearseven if it's connected via Wifi-direct to another device?
-
eyal about 6 yearsI have downloaded your library but it has some compilation problems in network packege
-
Billyjoker almost 6 yearsHi, 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.