web-dev-qa-db-fra.com

Envoi d'une chaîne via Bluetooth depuis un PC en tant que client vers un mobile en tant que serveur

J'ai besoin d'aide en transférant une chaîne depuis un PC vers un appareil mobile Android via Bluetooth. L'appareil mobile Android devrait agir comme un serveur et afficher le message de la chaîne) sur l'écran de l'appareil. Le PC qui est le client doit envoyer la chaîne à l'appareil mobile.

Je veux que le serveur réagisse sur la chaîne extraite (transférée via Bluetooth). Cela signifie que d'un côté, le serveur doit toujours écouter l'arrivée de nouvelles chaînes, mais de l'autre côté doit toujours être en mesure de réagir à ces messages (par exemple, naviguer d'un menu à l'autre).

Je l'ai essayé en utilisant BlueCove (2.1.1) comme BluetoothStack (pour lequel j'ajoute le pot de BlueCove en tant que bibliothèque aux deux projets) en combinaison avec un exemple de communication serveur-client que j'ai trouvé ici =.

Mises à jour:

Code mis à jour depuis le serveur grâce à user_CC en utilisant une connexion RFComm pour le serveur:

public class RFCommServer extends Thread{

//based on Java.util.UUID
private static UUID MY_UUID = UUID.fromString("446118f0-8b1e-11e2-9e96-0800200c9a66");

// The local server socket
private BluetoothServerSocket mmServerSocket;

// based on Android.bluetooth.BluetoothAdapter
private BluetoothAdapter mAdapter;
private BluetoothDevice remoteDevice;

private Activity activity;

public RFCommServer(Activity activity) {
    this.activity = activity;
}

public void run() {
    BluetoothSocket socket = null;
    mAdapter = BluetoothAdapter.getDefaultAdapter();        

    // Listen to the server socket if we're not connected
    while (true) {

        try {
            // Create a new listening server socket
            Log.d(this.getName(), ".....Initializing RFCOMM SERVER....");

            // MY_UUID is the UUID you want to use for communication
            mmServerSocket = mAdapter.listenUsingRfcommWithServiceRecord("MyService", MY_UUID);
            //mmServerSocket = mAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME, MY_UUID); // you can also try using In Secure connection...

            // This is a blocking call and will only return on a
            // successful connection or an exception
            socket = mmServerSocket.accept();

        } catch (Exception e) {

        }

        try {
            Log.d(this.getName(), "Closing Server Socket.....");
            mmServerSocket.close();

            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            // Get the BluetoothSocket input and output streams

            tmpIn = socket.getInputStream();
            tmpOut = socket.getOutputStream();

            DataInputStream mmInStream = new DataInputStream(tmpIn);
            DataOutputStream mmOutStream = new DataOutputStream(tmpOut);

            // here you can use the Input Stream to take the string from the client whoever is connecting
            //similarly use the output stream to send the data to the client

            RelativeLayout layout = (RelativeLayout) activity.findViewById(R.id.relativeLayout_Layout);
            TextView text = (TextView) layout.findViewById(R.id.textView_Text);

            text.setText(mmInStream.toString());
        } catch (Exception e) {
            //catch your exception here
        }
    }
}

Code du client SPP de ici :

/**
* A simple SPP client that connects with an SPP server
*/
public class SampleSPPClient implements DiscoveryListener{

//object used for waiting
private static Object lock=new Object();

//vector containing the devices discovered
private static Vector vecDevices=new Vector();

private static String connectionURL=null;

public static void main(String[] args) throws IOException {

    SampleSPPClient client=new SampleSPPClient();

    //display local device address and name
    LocalDevice localDevice = LocalDevice.getLocalDevice();
    System.out.println("Address: "+localDevice.getBluetoothAddress());
    System.out.println("Name: "+localDevice.getFriendlyName());

    //find devices
    DiscoveryAgent agent = localDevice.getDiscoveryAgent();

    System.out.println("Starting device inquiry...");
    agent.startInquiry(DiscoveryAgent.GIAC, client);

    try {
        synchronized(lock){
            lock.wait();
        }
    }
    catch (InterruptedException e) {
        e.printStackTrace();
    }


    System.out.println("Device Inquiry Completed. ");

    //print all devices in vecDevices
    int deviceCount=vecDevices.size();

    if(deviceCount <= 0){
        System.out.println("No Devices Found .");
        System.exit(0);
    }
    else{
        //print bluetooth device addresses and names in the format [ No. address (name) ]
        System.out.println("Bluetooth Devices: ");
        for (int i = 0; i <deviceCount; i++) {
            RemoteDevice remoteDevice=(RemoteDevice)vecDevices.elementAt(i);
            System.out.println((i+1)+". "+remoteDevice.getBluetoothAddress()+" ("+remoteDevice.getFriendlyName(true)+")");
        }
    }

    System.out.print("Choose Device index: ");
    BufferedReader bReader=new BufferedReader(new InputStreamReader(System.in));

    String chosenIndex=bReader.readLine();
    int index=Integer.parseInt(chosenIndex.trim());

    //check for spp service
    RemoteDevice remoteDevice=(RemoteDevice)vecDevices.elementAt(index-1);
    UUID[] uuidSet = new UUID[1];
    uuidSet[0]=new UUID("446118f08b1e11e29e960800200c9a66", false);

    System.out.println("\nSearching for service...");
    agent.searchServices(null,uuidSet,remoteDevice,client);

    try {
        synchronized(lock){
            lock.wait();
        }
    }
    catch (InterruptedException e) {
        e.printStackTrace();
    }

    if(connectionURL==null){
        System.out.println("Device does not support Simple SPP Service.");
        System.exit(0);
    }

    //connect to the server and send a line of text
    StreamConnection streamConnection=(StreamConnection)Connector.open(connectionURL);

    //send string
    OutputStream outStream=streamConnection.openOutputStream();
    PrintWriter pWriter=new PrintWriter(new OutputStreamWriter(outStream));
    pWriter.write("Test String from SPP Client\r\n");
    pWriter.flush();


    //read response
    InputStream inStream=streamConnection.openInputStream();
    BufferedReader bReader2=new BufferedReader(new InputStreamReader(inStream));
    String lineRead=bReader2.readLine();
    System.out.println(lineRead);


}//main

//methods of DiscoveryListener
public void deviceDiscovered(RemoteDevice btDevice, DeviceClass cod) {
    //add the device to the vector
    if(!vecDevices.contains(btDevice)){
        vecDevices.addElement(btDevice);
    }
}

//implement this method since services are not being discovered
public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
    if(servRecord!=null && servRecord.length>0){
        connectionURL=servRecord[0].getConnectionURL(0,false);
    }
    synchronized(lock){
        lock.notify();
    }
}

//implement this method since services are not being discovered
public void serviceSearchCompleted(int transID, int respCode) {
    synchronized(lock){
        lock.notify();
    }
}


public void inquiryCompleted(int discType) {
    synchronized(lock){
        lock.notify();
    }

}//end method

}

Pour les tests, j'utilise un Galaxy Nexus (GT-I9250) avec la dernière Android API.

Grâce à user_CC , le client et le serveur s'exécutent désormais sans exception. Mais malheureusement, le client n'est pas en mesure de se connecter au serveur (voir la capture d'écran ci-dessous). C'est parce que le connectionURL n'est jamais défini (donc il saute ici if(connectionURL==null) par défaut.

Comment puis-je changer le code client, afin que je puisse réellement le connecter au serveur? J'ai besoin d'un connectionURL approprié dans la ligne suivante:

StreamConnection streamConnection=(StreamConnection)Connector.open(connectionURL)

Jusqu'à présent, j'ai seulement découvert que j'avais en quelque sorte besoin d'obtenir le ServiceRecord, malheureusement cela n'est pas non plus décrit dans l'exemple de code de ici .

enter image description here

22
Elementary

Vous devrez utiliser le RFComm APIS pour faire fonctionner la communication. J'ai réussi à définir une classe qui est un thread et agira comme un serveur et écoutera les connexions client. J'ai également placé quelques commentaires pour que vous compreniez.

    private class AcceptThread extends Thread {
    // The local server socket
    private BluetoothServerSocket mmServerSocket;

    public AcceptThread() {
    }

    public void run() {         
        BluetoothSocket socket = null;

                    BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();

        // Listen to the server socket if we're not connected
        while (true) {

            try {
                // Create a new listening server socket
                Log.d(TAG, ".....Initializing RFCOMM SERVER....");

                // MY_UUID is the UUID you want to use for communication
                mmServerSocket = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);                    
                //mmServerSocket = mAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME, MY_UUID);  you can also try using In Secure connection...

                // This is a blocking call and will only return on a
                // successful connection or an exception                    
                socket = mmServerSocket.accept();                   

            } catch (Exception e) {

            }

            try {
                Log.d(TAG, "Closing Server Socket.....";                    
                mmServerSocket.close();



                InputStream tmpIn = null;
                OutputStream tmpOut = null;

                // Get the BluetoothSocket input and output streams

                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();


                mmInStream = new DataInputStream(tmpIn);
                mmOutStream = new DataOutputStream(tmpOut); 

                // here you can use the Input Stream to take the string from the client whoever is connecting
                //similarly use the output stream to send the data to the client
            } catch (Exception e) {
                //catch your exception here
            }

        }
    }

}

J'espère que ça aide

Pour votre autre question:

La déclaration de la classe UUID côté client (PC) javax.bluetooth.UUID doit provenir de javax.bluetooth.UUID

   uuidSet2[0] = new UUID("446118f08b1e11e29e960800200c9a66", false);

Déclaration de Java.util.UUID côté serveur (Android)

    UUID MY_UUID = UUID.fromString("446118f0-8b1e-11e2-9e96-0800200c9a66");
7
user_CC

Je ne suis pas un développeur Java mais j'ai rencontré un problème similaire avec Mono pour Android (c #)

L'UUID pour SPP doit être "00001101-0000-1000-8000-00805F9B34FB"
Il s'agit d'un UID bien connu pour identifier un adaptateur Bluetooth SPP.

Dans mon code c # qui ressemble à

private static UUID MY_UUID = UUID.FromString("00001101-0000-1000-8000-00805F9B34FB");

Je suppose que vous pouvez mettre à jour votre code Java en quelque chose comme:

new UUID("00001101-0000-1000-8000-00805F9B34FB", true);

Bien que je ne sois pas sûr des paramètres acceptés par cette fonction, vous devrez peut-être vérifier cela.

J'utilisais l'appareil Android en tant que client, mais les informations peuvent vous être utiles,
donc je vais inclure mon code c # ici que j'ai à l'origine traduit de Java samples,
donc vous devriez pouvoir le traduire:

btAdapter = BluetoothAdapter.DefaultAdapter;

btAdapter.CancelDiscovery(); //Always call CancelDiscovery before doing anything
remoteDevice = btAdapter.GetRemoteDevice(Settings["deviceaddress"].ToString());

socket = remoteDevice.CreateRfcommSocketToServiceRecord(MY_UUID);
socket.Connect();

En gros, j'obtiens l'adaptateur par défaut, j'annule toutes les opérations de découverte en cours, puis je crée un socket sur l'autre appareil. Dans votre cas, vous voudrez écouter au lieu de vous connecter, mais juste pour votre information.

J'espère que cela aide, désolé de ne pas pouvoir vous donner plus Java informations spécifiques.

'Mise à jour:' Je viens de trouver un petit échantillon dans Java qui suit plus ou moins la même méthode que celle que j'utilise: Problèmes avec la connexion bluetooth SPP dans Android?

2
TimothyP