0

I hope my question is not repeated at all, i tried reading another people that asks for similar information but couldnt fix my problem.

The thing here is that i have an android app that uses bluetooth , i have succesfully set the connection , i know that my app is sending a message when it gets connected to another device, but the problem here is that when i receive a message i would like to make it appear in a text view , or in a toast , but it is not reading properly.

Hope you guys can help me ill give you my code

package com.example.cesar.drcarobd2;



public class MainActivity extends AppCompatActivity implements SensorEventListener, AdapterView.OnItemClickListener {

private static final int CONEXION_EXITOSA = 0 ;
private static final int MESSAGE_READ = 1;
public static final int VELOCIDAD_ESCRITO = 2;
private static final int RPM_ESCRITO = 3 ;
// device sensor manager
private SensorManager mSensorManager;
ArrayAdapter<String> listAdapter;
ListView listView;
TextView brujula;
TextView velocidad;
BluetoothAdapter btAdapter; //creas un Adaptador bluetooth
Set<BluetoothDevice> ArregloDispositivos;
ArrayList<String> dispositivosApareados;
ArrayList<BluetoothDevice> dispositivos;
IntentFilter filtro;
BroadcastReceiver receptor;
private ArrayAdapter<String> Adapterdeconversacion;
String tag = "debugging";
public static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB") ;  //UUID de conexion bt
Handler mhandler = new Handler(){


    @Override
    public void handleMessage(Message msg){
        ConnectedThread threadEscritura = new ConnectedThread((BluetoothSocket)msg.obj);
       // threadEscritura.run();
       // ConnectedThread threadConectado = new ConnectedThread((BluetoothSocket)msg.obj);
        Log.i(tag, "en el handler");
       // threadConectado.run();
        super.handleMessage(msg);
        switch(msg.what){
            case CONEXION_EXITOSA:
                    //Hacer algo
                Toast.makeText(getApplicationContext(), "Conexión", Toast.LENGTH_SHORT).show();
                Log.i(tag, "Conectado");
                String s = "Conectado Satisfactoriamente ";
                threadEscritura.write(s.getBytes());
                Log.i(tag, "Mensaje de Conexion Enviado");
               // threadConectado.run();
                break;
            case MESSAGE_READ:
                byte[] bufferleido = (byte[])msg.obj;
                String texto = new String(bufferleido);
                System.out.println(texto);
                Toast.makeText(getApplicationContext(), texto, Toast.LENGTH_SHORT).show();
                Log.i(tag, "Haciendo el Toast");
                velocidad.setText(texto);
                Log.i(tag, "Haciendo el Texto");
            case VELOCIDAD_ESCRITO:
                String mensajeVelocidad = "010D" + '\r';
                threadEscritura.write(mensajeVelocidad.getBytes());
                Log.i(tag, "Enviando Mensaje Velocidad");
                break;
            case RPM_ESCRITO:
                String mensajeRPM = "010C" + '\r';
                threadEscritura.write(mensajeRPM.getBytes());
                break;
        }//fin switch
    }//fin HandleMessage
};//fin handler



//TODO    HACER METODO QUE  ENVÍE EL MENSAJE DE LA VELOCIDAD

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    init();//llamas la inicializacion de todos
    if(btAdapter==null){//vamos a revisar si hay bluetooth en el dispositivo en caso de que sea null avisamos que no hay bluetooth
        Toast.makeText(getApplicationContext(), "No se detecto bluetooth", Toast.LENGTH_SHORT).show();
        finish();
    }//fin if
    else{//en caso de que si hay bluetooth vamos a continuar revisando que este o no activado
        if(!btAdapter.isEnabled()){//en caso de que no este activado
           encenderBt();//llamamos metodo enceder bluetooth
        }

        getDispositivosSincronizados(); //Vamos a revisar los dispositivos sincronizados , los vamos a meter en un array
        iniciarDescubrimiento(); //y despues vamos a iniciar el descubrimiento y vamos a poblar esa lista
    }//fin else


    // Informamos el nombre del texto view donde despliego la brujula
    brujula = (TextView) findViewById(R.id.brujula_textview);
    //Text View de la velocidad
    velocidad = (TextView) findViewById(R.id.velocidad_textview);
    // initialize your android device sensor capabilities
    mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);


    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });


}




private void iniciarDescubrimiento() {
    btAdapter.cancelDiscovery();
    btAdapter.startDiscovery();
}

private void encenderBt() {//enciende el bt del dispositivo
    Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);//Haremos una peticion para activarlo
    startActivityForResult(intent, 1);
}

private void getDispositivosSincronizados() {

    ArregloDispositivos = btAdapter.getBondedDevices();
    if(ArregloDispositivos.size()>0){//si tenemos mas de un dispositivop apareado en el telefono
        for(BluetoothDevice device:ArregloDispositivos){//Para cada uno de los dispositivos apareados los vamos a incluir en nuestra lista
            dispositivosApareados.add(device.getName());

        }//fin for
    }//fin if
}

private void init() {//usado para bt , no interfiere con brjula  Aqui inicializamos

    listView=(ListView)findViewById(R.id.listView);
    listView.setOnItemClickListener(this);
    listAdapter= new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,0 );
    listView.setAdapter(listAdapter);
    btAdapter = BluetoothAdapter.getDefaultAdapter(); //inicias un adaptador bluetooth
    dispositivosApareados = new ArrayList<String>();
    filtro = new IntentFilter(BluetoothDevice.ACTION_FOUND);
    dispositivos = new ArrayList<BluetoothDevice>();
    receptor = new BroadcastReceiver() { //hacemos broadcast para encontrar nuevos dispositivos
        @Override
        public void onReceive(Context context, Intent intent) {
            String Accion = intent.getAction();//realizamos una accion

            if(BluetoothDevice.ACTION_FOUND.equals(Accion)){//Si encontramos un dispositivo Bluetooth entonces lo añadimos a la lista
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                dispositivos.add(device);
               // listAdapter.add(device.getName()+"\n"+device.getAddress()); ----------------------------------------------------------------------------------probable eliminacion

                String s = "";
                for(int a=0 ; a< dispositivosApareados.size(); a++){
                    if(device.getName().equals(dispositivosApareados.get(a))){//si algun elemento de los dispositivos apareados del celular y de la lista de dispositivos son iguales, sabremos que ya estaban apareados
                        s = "(Apareado)";  //una vez que sabemos que estan apareados ese valor se concatena con la direccion del dispositivo bluetooth en cuestion
                        break;
                    }//fin if
                }//fin for


                listAdapter.add(device.getName()+" "+s+" "+"\n"+device.getAddress()); //se toma el nombre del dispositivo, se le añade la marca de Apareado y se concatena su direccion tambien
            }//fin if

            else if(BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(Accion)){//comparar los strings del filtro con los strings de las acciones

            }//fin elseif started
            else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(Accion)){//comparar los strings del filtro con los strings de las acciones

            }//fin elseif finished
            else if(BluetoothAdapter.ACTION_STATE_CHANGED.equals(Accion)){//comparar los strings del filtro con los strings de las acciones
                if(btAdapter.getState() == btAdapter.STATE_OFF){//en caso de que haya un cambio de estado a apagado prendemos de nuevo
                    encenderBt();
                }//fin if state of
            }//fin elseif changed

        }//fin funcion onReceive
    };//fin broadcast receiver

    registerReceiver(receptor, filtro);
    filtro = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
    registerReceiver(receptor, filtro);
    filtro = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
    registerReceiver(receptor, filtro);
    filtro = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
    registerReceiver(receptor, filtro);
}

@Override
protected void onPause(){// Estado de la aplicacion al ser Pausada
    super.onPause();
    unregisterReceiver(receptor);//debemos quitar el registro de los dispositivos bluetooth en caso de pausar la app
    // este si es para la brujula, si se pausa la app detenemos los sensores para guardar bateria
    mSensorManager.unregisterListener(this);
}//fin del metodo on Pause


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(resultCode == RESULT_CANCELED){
        Toast.makeText(getBaseContext(), "El bluetooth debe ser activado", Toast.LENGTH_SHORT).show();
        finish();//si el usuario cancela la activacion del bluetooth terminamos el uso de la app pues no funcionaria de ese modo
    }//fin if
}

@Override
protected void onResume() {
    super.onResume();

    // for the system's orientation sensor registered listeners
    mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
            SensorManager.SENSOR_DELAY_GAME);
}


@Override
public void onSensorChanged(SensorEvent event) {

    float x = event.values[0];
    String dir = "";
    if (x >= 337.5 || x < 22.5) {
        dir = "N";
    } else if (x >= 22.5 && x < 67.5) {
        dir = "NE";
    } else if (x >= 67.5 && x < 112.5) {
        dir = "E";
    } else if (x >= 112.5 && x < 157.5) {
        dir = "SE";
    } else if (x >= 157.5 && x < 202.5) {
        dir = "S";
    } else if (x >= 202.5 && x < 247.5) {
        dir = "SO";
    } else if (x >= 247.5 && x < 292.5) {
        dir = "O";
    } else if (x >= 292.5 && x < 337.5) {
        dir = "NO";
    }
    brujula.setText(dir);

}



@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
    // not in use
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}


@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {//METODO ocupado por la implementacion del onItemClickListener que funcionara para hacer clickeable la lista en lugar del boton

    if(btAdapter.isDiscovering()){
        btAdapter.cancelDiscovery();
    }
    if(listAdapter.getItem(position).contains("Apareado")){
        BluetoothDevice dispositivoSeleccionado = dispositivos.get(position);//position es donde fue clickeado
        ConnectThread conectar = new ConnectThread(dispositivoSeleccionado);// esa posicion representa un dispositivo bluetooth al ser clickeado hace un thread para conectarse
        conectar.start();
    }//fin if
    else{
        Toast.makeText(getApplicationContext(),"El dispositivo no esta apareado",Toast.LENGTH_SHORT).show();
    }//fin else
}//finOnItemClick


private class ConnectThread extends Thread {
    private final BluetoothSocket mmSocket;
    private final BluetoothDevice mmDevice;


    public void VelocidadContinuo(){


    }


    public ConnectThread(BluetoothDevice device) {
        // Use a temporary object that is later assigned to mmSocket,
        // because mmSocket is final
        BluetoothSocket tmp = null;
        mmDevice = device;
        Log.i(tag, "En la parte del Socket");
        // Get a BluetoothSocket to connect with the given BluetoothDevice
        try {
            // MY_UUID is the app's UUID string, also used by the server code
            tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
        } catch (IOException e) {
            Log.i(tag, "Error en el Socket");}
        mmSocket = tmp;
    }

    public void run() {
        // Cancel discovery because it will slow down the connection
        btAdapter.cancelDiscovery();

        try {
            // Connect the device through the socket. This will block
            // until it succeeds or throws an exception
            mmSocket.connect();
            Log.i(tag, "Conexión realizada con el Socket");
        } catch (IOException connectException) { Log.i(tag, "Error de conexión en run de Connect Thread");
            // Si no te puedes conectar cierras el socket y sales
            try {
                mmSocket.close();
            } catch (IOException closeException) { }
            return;

        }



        // Do work to manage the connection (in a separate thread)

        mhandler.obtainMessage(CONEXION_EXITOSA,mmSocket).sendToTarget();
    }




    /** Will cancel an in-progress connection, and close the socket */
    public void cancel() {
        try {
            mmSocket.close();
        } catch (IOException e) { }
    }
}


//--------------------------------------------------------Iniciamos con el código para el SOCKET


private class ConnectedThread extends Thread {
    private final BluetoothSocket mmSocket;
    private final InputStream mmInStream;
    private final OutputStream mmOutStream;

    public ConnectedThread(BluetoothSocket socket) {
        mmSocket = socket;
        InputStream tmpIn = null;
        OutputStream tmpOut = null;

        // Get the input and output streams, using temp objects because
        // member streams are final
        try {
            tmpIn = socket.getInputStream();
            tmpOut = socket.getOutputStream();
        } catch (IOException e) { }

        mmInStream = tmpIn;
        mmOutStream = tmpOut;
    }

    public void run() {
        byte[] buffer;   // buffer store for the stream
        int bytes; // bytes returned from read()

        // Keep listening to the InputStream until an exception occurs
        while (true) {
            try {
                // Read from the InputStream
                buffer = new byte[1024];
                bytes = mmInStream.read(buffer);
                // Enviar mensajes a la actividad de la UI
                mhandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
                //mhandler.obtainMessage(MESSAGE_READ,mmSocket).sendToTarget(); //TEMPORAL AL RECIBIR ALGO MANDAR EL MENSAJE DE PEDIR VELOCIDAD OBD2
                        .sendToTarget();

                Log.i(tag, "Bytes leidos wooho");
                Log.i(tag, String.valueOf(bytes));

            } catch (IOException e) {
                Log.e(tag, "disconnected", e);
                // Start the service over to restart listening mode
                this.start();
                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) { }
    }

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

}

The connection socket is at the end of the code , with the write method )That is working)

And the case that do something are at the begginig.

Thanks a lot for your help guys.

Cesar Cisneros
  • 65
  • 1
  • 2
  • 9

1 Answers1

0

Is your code running from a thread different from the main thread? In that case you need to switch to the main thread to show your toast message or to make modifications on the UI.

Android: Toast in a thread

In that case, all you need to do is:

    activity.runOnUiThread(new Runnable() {

    @Override
    public void run() {
        Toast.makeText(getApplicationContext(), "Conexión",
                       Toast.LENGTH_SHORT).show();

    }
});
Community
  • 1
  • 1
Alex Mantaut
  • 3,657
  • 3
  • 35
  • 45
  • Ups sorry i wrote a few comments before paying attention, and it was my bad because i wasnt too explicit. – Cesar Cisneros Oct 06 '15 at 20:00
  • You're welcome, hope it works. Yes, to modify any UI element from another thread you need to switch to the UI Thread with the runOnUiThread() method – Alex Mantaut Oct 06 '15 at 20:03
  • Bro. When i get in the 'CONEXION_EXITOSA' case , the (Toast appears properly sayin "conexion"). and , at that time it sends a String "Concectado Satisfactoriamente" to the selected device. The problem comes after that, when im expecting the other device to answer me. The first toast when i connect appears properly but the following toasts on the MESSAGE_READ case dont, Do you have an idea of why i see the toast in one case and not in the other? – Cesar Cisneros Oct 06 '15 at 20:11
  • Are you sure that the reply from the device is being received? Did you set a breakpoint or a log after reading the bytes, just before `mhandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer).sendToTarget();` ? If no bytes are being read then it might be a BT communication problem, else it might be a UI problem – Alex Mantaut Oct 06 '15 at 23:55
  • Ok perfect. i just set the logs , and i notice that im not even entering the reading part. My log notified me the following things. -Conection started -Entered the handler -Connected -First Message Sent correctly -Entered Handler // ----------------------------- Never enters the Reading Case – Cesar Cisneros Oct 07 '15 at 04:15
  • Alex HI AGAIN ! Bro, i walked a little step more, now i already mannaged to notice that im receiving information , i was able to send a string , just when the device get connected, and the other device is receiving, both devices are properly connected, im making a log everytime i receive a string from other device, now that im sure that im receiving i cant use it to show what im receiving, i think it is because im not changing the state of my handler mhandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer).sendToTarget(); Any idea? – Cesar Cisneros Oct 07 '15 at 09:43
  • Glad to hear you got the BT communication working... Regarding obtaining the message, were you able to log the data received by the app before calling the sendToTarget() method? If that was successful, have you tried logging the data from the handleMessage() method (before trying to show the Toast)? I am asking this to try to narrow down where the problem is... BTW, if you manage to fix your issues can you update the question with the corrections? – Alex Mantaut Oct 07 '15 at 15:47
  • Hello Alex, i just updated the code that im using now, im triying to log all the posible information, now i know that im receiving the message, but im not entering the case MESSAGE_READ in the handler that means that my switch statement is not working :( but the information is being received , Thx a lot bro – Cesar Cisneros Oct 12 '15 at 05:53
  • Sorry for not replying sooner... Have you tried changing the way you create the Handler? Try `mHandler = new Handler(Looper.getMainLooper()) {` If this doesn't work can you please add your log to the question? – Alex Mantaut Oct 16 '15 at 19:50
  • Alex hello bro !! , bro i just discovered something important... The messages are being received and they are being displayed ! but only in one situation , if i connect the devices , and send the messages from B to A , nothing happens , but when i close the bluetooth chat example in "B" all the messages appear in A. the way i want to. what could it be ? – Cesar Cisneros Oct 19 '15 at 04:31
  • Mmm, are you sending exactly 1024 bytes? because in the read() method you seem to be reading a buffer of exactly that size, in that case the read will block until it reads 1024 bytes or the stream is closed... You can either reduce the array lenght or use the int read(byte[] b,int off,int len) method – Alex Mantaut Oct 19 '15 at 13:29