Partage

[ANDROID] Bluetooth sur android studio

14 septembre 2017 à 11:24:49

Bonjour! 

Je cherche à envoyer un byte par bluetooth à l'aide d'une application réalisée sous android Studio. 

Malheureusement j'ai un soucis que je n'arrive pas à régler. Il me semble tout bête mais je n'ai pas trouvé de documentation dessus...

L'idée de l'App : Je choisis, à l'aide d'un spinner, un genre (homme/femme). Le choix est relié à une variable via une énumération. J'ai aussi une class BTInterface qui sert à envoyer et recevoir des informations en bluetooth (je m'en fiche de recevoir mais j'ai suivi un tuto sur youtube donc j'ai tout simplement recopié). Finalement j'ai un bouton "enregistré" qui est censé envoyer la variable sélectionné. Entre temps j'ai transformé mon int en byte pour correspondre au critère de mon envoie de donnée. La partie connexion et appareillage n'est pas géré par l'app. L'utilisateur doit se débrouiller pour avoir un smartphone avec bluetooth et s'appareiller à un module bluetooth. Je vous laisse découvrir mon code : 

Main : 

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    public static final String TAG = "MainActivity";

    //définition classe BtInterface
    BtInterface mBtInterface;

    //définition du button
    Button button1;

    //initialisation de la variable var
    public int var = 0;

    //création de l'objet Spinner
    Spinner spinner1;

    //pour ajouter des datas dans un spinner, on a besoin d'un "adapteur"
    ArrayAdapter<CharSequence> adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        //initialisation des objets Spinner
        spinner1 = (Spinner) findViewById(R.id.spinner1);

        //on set les valeurs des énumérations dans le  spinner grâce à ArrayAdapter
        spinner1.setAdapter(new ArrayAdapter<MyEnum1>(this, android.R.layout.simple_spinner_item, MyEnum1.values()));

        //création de l'évènement qui va gérer le spinner1
        spinner1.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

                var = ((MyEnum1) parent.getItemAtPosition(position)).getA();

            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });

        final byte varbyte = (byte)var;

        button1 = (Button) findViewById(R.id.button2);

        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Toast.makeText(MainActivity.this, "var = "+var, Toast.LENGTH_SHORT).show();
                byte[] bytes = varbyte;
                mBtInterface.write(bytes);

            }
        });

    }

}


xml associé : 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="20dp">



    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center"
        android:text="Je suis?"
        android:textSize="25sp"
        android:textStyle="bold" />


    <Spinner
        android:id="@+id/spinner1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="sélectionner genre"/>


    <Space
        android:layout_width="match_parent"
        android:layout_height="20dp"></Space>

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

        <Button
            android:id="@+id/button2"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:padding="20dp"
            android:text="Enregistrer"
            android:textSize="18sp" ></Button>

    </FrameLayout>


</LinearLayout>

Mon énumération (MyEnum1) :

public enum MyEnum1 {

    Boy("homme",  1),
    Girl("femme", 0);

    private final String label;

    public final int a;

    private MyEnum1(String label, int a){
        this.a = a;
        this.label = label;
    }

    @Override
    public String toString(){
        return label;
    }

    public int getA(){
        return a;
    }

}

Ma class BTInterface : 

import android.app.ProgressDialog;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.util.Log;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;

import static com.pandaenterprise.cyril.bluetoothtest.MainActivity.TAG;


public class BtInterface {

    ProgressDialog mProgressDialog;
    private ConnectedThread mConnectedThread;



    /**
     Finally the ConnectedThread which is responsible for maintaining the BTConnection, Sending the data, and
     receiving incoming data through input/output streams respectively.
     **/
    private class ConnectedThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;

        public ConnectedThread(BluetoothSocket socket) {
            Log.d(TAG, "ConnectedThread: Starting.");

            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            //dismiss the progressdialog when connection is established
            try{
                mProgressDialog.dismiss();
            }catch (NullPointerException e){
                e.printStackTrace();
            }


            try {
                tmpIn = mmSocket.getInputStream();
                tmpOut = mmSocket.getOutputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }

        public void run(){
            byte[] buffer = new byte[1024];  // buffer store for the stream

            int bytes; // bytes returned from read()

            // Keep listening to the InputStream until an exception occurs
            while (true) {
                // Read from the InputStream
                try {
                    bytes = mmInStream.read(buffer);
                    String incomingMessage = new String(buffer, 0, bytes);
                    Log.d(TAG, "InputStream: " + incomingMessage);
                } catch (IOException e) {
                    Log.e(TAG, "write: Error reading Input Stream. " + e.getMessage() );
                    break;
                }
            }
        }

        //Call this from the main activity to send data to the remote device
        public void write(byte[] bytes) {
            try {
                mmOutStream.write(bytes);
            } catch (IOException e) {
                Log.e(TAG, "write: Error writing to output stream. " + e.getMessage() );
            }
        }

        /* Call this from the main activity to shutdown the connection */
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) { }
        }
    }

    private void connected(BluetoothSocket mmSocket, BluetoothDevice mmDevice) {
        Log.d(TAG, "connected: Starting.");

        // Start the thread to manage the connection and perform transmissions
        mConnectedThread = new ConnectedThread(mmSocket);
        mConnectedThread.start();
    }

    /**
     * Write to the ConnectedThread in an unsynchronized manner
     *
     * @param out The bytes to write
     * @see ConnectedThread#write(byte[])
     */
    public void write(byte[] out) {
        // Create temporary object
        ConnectedThread r;

        // Synchronize a copy of the ConnectedThread
        Log.d(TAG, "write: Write Called.");
        //perform the write
        mConnectedThread.write(out);
    }

}

En gros, je vois bien que le problème vient du type de variable ou de la déclaration ou de ... enfin ça se joue sur la variable que je veux envoyer. Mais je ne vois pas ce que je dois modifier...

Merci d'avance pour votre aide! 





14 septembre 2017 à 16:16:34

Bonjour,

En regardant vite fait je vois une première erreur. Dans ton MainActivity et dans button1.setOnClickListener

Tu as :

byte[] bytes = varbyte;

Remplace le par :

byte[]bytes = new byte[]{varbyte};

Un byte n'est pas égale a un byte[]. Ce que je fais ici c'est crée un nouveau byte[] ou je met varbyte a l'interieur. ;)

Dans tout le code que tu nous as envoyé il manque la partie connexion, ou tu initialise une variable de type BluetoothSocket

-
Edité par Morin21 14 septembre 2017 à 16:20:35

14 septembre 2017 à 18:12:46

Ok je suis d'accord. Par contre je ne connais pas la différence ^^ Peux-tu me l'expliquer?

Aussi, je ne comprend pas à quoi sert la BluetoothSocket si j'ai déjà connecté mon smartphone au module bluetooth "HC06", faut-il vraiment que j'utilise le BluetoothSocket? J'ai vu beaucoup de tuto qui expliquent comment faire mais pas "pourquoi" je ne comprend pas toujours très bien à quoi sert BluetoothSocket...

Merci d'avance! 

15 septembre 2017 à 9:11:37

La différence est vraiment simple :

  • byte[] est un tableau de byte
  • byte est juste un byte

Ils sont différent l'un de l'autre mais il te suffit de créer un tableau et mettre ton byte a l'intérieur, comme ca tu as un tableau de byte avec 1 seul byte dedans.

Je vais essayer de t'expliquer rapidement et simplement pour le BluetoothSocket :

Il ne suffit pas de connecté ton device a ton module bluetooth pour que ton programme puisse faire la communication. L'appairage entre les deux devices doit être fait dans ton programme.

Dans un premier temps tu dois :

  • Créer la connexion avec un UUID
  • Récupérer ton BluetoothDevice
  • Ensuite tu créer le BluetoothSocket en question, c'est grace a lui que tu vas récupérer ton InputStream et le OutputStream.

Dès que j'ai un peu plus de temps je te fais un exemple de code ;)

Dans un premier temps essai de crée une boite de dialog qui affiche tout les bluetooth qu'il détecte et qu'il te renvoi un BluetoothDevice quand tu clique sur un des Device. Regarde ce lien, il va t'aider a comprendre la fonction .startDiscovery() : ici

Ca va beaucoup t'aider pour la suite.

EDIT :


public class ConnectivityBtThread extends Thread {

    private Context context;
    private BluetoothDevice device;
    private BluetoothSocket bluetoothSocket;


    public ConnectivityBtThread(Context context, BluetoothDevice device){
        this.context = context;
        this.device = device;

    }

    public void run(){

        try {

            // Get a BluetoothSocket to connect with the given BluetoothDevice
            try {
                int sdk = Integer.parseInt(Build.VERSION.SDK);
                UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
                Method m = BluetoothDevice.class.getMethod("createInsecureRfcommSocketToServiceRecord", new Class[]{UUID.class});
                bluetoothSocket = (BluetoothSocket) m.invoke(device, uuid);
            } catch (Exception e) {
                Log.e(this.getClass().getName(), "IO Exception thrown while creating rf comm socket: " + e.getMessage(), e);
            }

            bluetoothSocket.connect();

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

Voici un exemple pour le BluetoothSocket. Attention c'est simplement un exemple, mon thread n'est pas 'Thread safe'.

-
Edité par Morin21 15 septembre 2017 à 16:53:55

17 septembre 2017 à 21:20:22

Ok merci pour toutes les infos. Je vais essayer de décortiquer ça demain. 

Enfaite j'ai déjà fais les applications de bases du bluetooth (activer le bluetooth avec un bouton, chercher des devices, s'appareiller au device, ...) mais je n'avais jamais vraiment compris l'intérêt de ces fonctions dans une application (j'avais comme exemple en tête les enceintes bluetooth où il suffit de s'appareiller pour que ça fonctionne). 

Donc enfaite, une fois que j'ai envoyé mon UUID au device et que j'ai reçu le sien je peux envoyer mes infos? 

17 septembre 2017 à 22:10:17

En quelque sorte oui,

C'est cette étape qui te permet d'avoir ton BluetoothSocket et grace a ce dernier tu peux créer tes flux d'entrée / sortie entre tes deux devices avec InputStream et OutpuStream.

J'espère que ce morceau de code va t'aider. Sinon hésite pas ;)

[ANDROID] Bluetooth sur android studio

× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
  • Editeur
  • Markdown