it-swarm.com.de

Verbinden Sie mehrere Geräte über Bluetooth mit einem Gerät

Ich möchte ein Spiel erstellen, bei dem Sie mehrere Geräte (4+) über Bluetooth mit einem Hauptgerät (z. B. einem Tablet) verbinden müssen. Es würde zwei Apps geben, eine Haupt-App, an die alle Daten von den Telefonen und zu den Telefonen gesendet würden. Ist das überhaupt möglich?

28
domen

Ja das ist möglich Auf der niedrigsten Ebene können Sie mit Bluetooth bis zu 7 Geräte mit einem Master-Gerät verbinden. Ich habe dies getan und es hat gut für mich funktioniert, aber nur auf anderen Plattformen (Linux), auf denen ich viel manuelle Kontrolle hatte - ich habe das noch nie auf Android und es sind einige möglich Komplikationen, so müssen Sie einige Tests durchführen, um sicher zu sein.

Eines der Probleme ist, dass Sie das Tablet beim Master benötigen und Android gibt Ihnen keine explizite Kontrolle darüber. Es ist wahrscheinlich, dass dies aufgrund des Tablets kein Problem darstellt wird automatisch zum Master, wenn Sie versuchen, ein zweites Gerät daran anzuschließen, oder * Sie können die Master-/Slave-Rollen steuern, indem Sie Ihre Socket-Verbindung einrichten

Ich werde jedoch darauf hinweisen, dass die meisten Apps, die Bluetooth auf Mobilgeräten verwenden, nicht viele gleichzeitige Verbindungen versuchen und Bluetooth ein bisschen zerbrechlich sein kann, z. Was ist, wenn zwei Geräte bereits eine Bluetooth-Verbindung für eine andere App haben - wie könnte sich das auf die Rollen auswirken?

19
Tom

Bluetooth 4.0 Ermöglicht es Ihnen, in einem Bluetooth-Piconet einen Master mit bis zu 7 aktiven Slaves zu kommunizieren. Es können einige andere Geräte mit bis zu 248 schlafenden Geräten vorhanden sein.

Sie können auch einige Slaves als Bridge verwenden, um an mehr Geräten teilzunehmen.

7
siniradam

Ja, das kannst du und ich habe eine Bibliothek dafür erstellt.
Auf diese Weise können Sie bis zu vier Geräte mit dem Hauptservergerät verbinden, indem Sie für jeden Client verschiedene Kanäle erstellen und Interaktionen auf verschiedenen Threads ausführen.
Um diese Bibliothek zu benutzen, fügen Sie einfach compile com.mdg.androble:library:0.1.2 im Abhängigkeitsbereich Ihres build.gradle.

3
Pulkit Karira

Dies ist die Klasse, in der die Verbindung hergestellt und Nachrichten empfangen werden. Stellen Sie sicher, dass Sie die Geräte koppeln, bevor Sie die Anwendung ausführen. Wenn Sie eine Slave/Master-Verbindung wünschen, bei der jeder Slave nur Nachrichten an den Master senden kann und der Master Nachrichten an alle Slaves senden kann. Sie sollten nur den Master mit jedem Slave koppeln, aber Sie sollten die Slaves nicht miteinander koppeln.

    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);
                }
            }
        }

    }

Ihre Haupttätigkeit sollte wie folgt sein:

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();
            }
        });

    }

}

Und hier ist das 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"
    />

Vergessen Sie nicht, die folgenden Berechtigungen zu Ihrer Manifest-Datei hinzuzufügen:

    <uses-permission Android:name="Android.permission.BLUETOOTH" />
<uses-permission Android:name="Android.permission.BLUETOOTH_ADMIN" />
1
Gaby Bou Tayeh

Ich halte es für möglich, wenn es sich um serielle Daten im Rundfunkverfahren handelt. Sie können jedoch keine Sprach-/Audiodaten auf das andere Slave-Gerät übertragen. Ab Bluetooth 4.0 unterstützt das Protokoll dies nicht. Es gibt jedoch eine Verbesserung beim Senden der Audio-/Sprachdaten.

0
Abhijit