简体   繁体   中英

App crashes when send data to a OBD-ii device via Bluetooth (Android-Studio)

i'm developing an application to request information to a car diagnostic scanner (like a ELM327) via Bluetooth. So, i'm using a obd-java-api ( https://github.com/eltonvs/java-obd-api ) for the request commands, but something goes wrong and the app crash. I'm pretty new at java and bluetooth service, so i don't understand at all what is the problem.

Everything goes well until i use the OBD commands. I mean, it works when i connect to the socket, but don't when i use de commands.

Someone have an idea?

I'm already verified if my OBD device works using Bluetooth AT Commands with a ELM327 Terminal an goes well. I though it was a problem with the Echo function but ...i was wrong.

I tried too with the original obd java api( https://github.com/pires/obd-java-api ) and had the same results.

package com.example.obd2_bluetooth_communication;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelUuid;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;


import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Set;
import java.util.UUID;

import br.ufrn.imd.obd.commands.ObdCommandGroup;
import br.ufrn.imd.obd.commands.engine.RPMCommand;
import br.ufrn.imd.obd.commands.protocol.EchoOffCommand;
import br.ufrn.imd.obd.commands.protocol.LineFeedOffCommand;
import br.ufrn.imd.obd.commands.protocol.SelectProtocolCommand;
import br.ufrn.imd.obd.commands.protocol.TimeoutCommand;
import br.ufrn.imd.obd.enums.ObdProtocols;

import static android.graphics.Color.RED;

public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener{

    TextView tvEstadoBT, tvRPM;
    ImageView ivEstadoBT;
    Button btnOnOff, btnPaired, btnEnviar;

    BluetoothAdapter mBlueAdapter;
    Set<BluetoothDevice> paired_devices;
    String plist[];
    ListView lvPairedDevices;
    ArrayAdapter<String> mAdapter;
    ArrayList<BluetoothDevice> mBTDevices = new ArrayList<>();

    private static UUID myuuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    BluetoothSocket socket;
    //UUID theuuid;


    RPMCommand rpmCommand = new RPMCommand();

    static final int STATE_CONFIG = 1;
    static final int STATE_CONNECTED = 2;
    static final int STATE_CONNECTION_FAILED = 3;
    static final int STATE_ERROR = 4;
    static final int STATE_INTERRUPT = 5;
    static final int STATE_DATO_ENVIADO = 6;

    private final BroadcastReceiver mBroadcastReceiver1 = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            // When discovery finds a device
            if (action.equals(mBlueAdapter.ACTION_STATE_CHANGED)) {
                final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, mBlueAdapter.ERROR);

                switch (state){
                    case BluetoothAdapter.STATE_OFF:
                        showToast("Bluetooth apagado");
                        btnOnOff.setText("Encender Bluetooth");
                        tvEstadoBT.setText("Bluetooth apagado");
                        tvEstadoBT.setTextColor(RED);
                        ivEstadoBT.setImageResource(R.drawable.ic_action_off);
                        btnEnviar.setEnabled(false);

                        break;

                    case BluetoothAdapter.STATE_TURNING_OFF:
                        showToast("Apagando...");
                        break;

                    case BluetoothAdapter.STATE_ON:
                        showToast("Bluetooth encendido");
                        btnOnOff.setText("Apagar Bluetooth");
                        tvEstadoBT.setText("Bluetooth encendido");
                        tvEstadoBT.setTextColor(Color.GREEN);
                        ivEstadoBT.setImageResource(R.drawable.ic_action_on);


                        break;

                    case BluetoothAdapter.STATE_TURNING_ON:
                        showToast("Encendiendo...");
                        break;

                }
            }
        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mBroadcastReceiver1);
    }



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

        tvEstadoBT       = findViewById(R.id.tvEstadoBT);
        ivEstadoBT       = findViewById(R.id.ivEstadoBT);
        btnOnOff         = findViewById(R.id.btnOnOff);
        btnPaired        = findViewById(R.id.btnPaired);
        lvPairedDevices  = findViewById(R.id.lvPairedDevices);
        btnEnviar        = findViewById(R.id.btnSend);
        tvRPM            = findViewById(R.id.tvRPM);


        mBlueAdapter = BluetoothAdapter.getDefaultAdapter();

        //Verificar si el dispositivo posee Bluetooth
        if (mBlueAdapter == null) {

            showToast("Tu dispositivo no soporta la opción de Bluetooth");
        }

        //Condiciones iniciales para el botón de encendido/apagado
        if (!mBlueAdapter.isEnabled()) {
            btnOnOff.setText("Encender Bluetooth");
            tvEstadoBT.setText("Bluetooth apagado");
            tvEstadoBT.setTextColor(RED);
            ivEstadoBT.setImageResource(R.drawable.ic_action_off);
        }
        if (mBlueAdapter.isEnabled()) {
            btnOnOff.setText("Apagar Bluetooth");
            tvEstadoBT.setText("Bluetooth encendido");
            tvEstadoBT.setTextColor(Color.GREEN);
            ivEstadoBT.setImageResource(R.drawable.ic_action_on);

            }


        }


    Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(@NonNull Message msg) {

            switch(msg.what)
            {
                case STATE_CONFIG:
                    showToast("Configurado");
                    btnEnviar.setEnabled(true);
                    finish();
                    break;

                case STATE_CONNECTED:
                    showToast("Conectado");
                    btnEnviar.setEnabled(true);
                    finish();
                    break;

                case STATE_CONNECTION_FAILED:
                    showToast("Conexión falló");
                    finish();
                    break;

                case STATE_ERROR:
                    showToast("Ocurrió un error");
                    ;
                    break;

                case STATE_INTERRUPT:
                    showToast("Función interrumpida");

                    break;

                case STATE_DATO_ENVIADO:

                    tvRPM.setText(rpmCommand.getFormattedResult() + " rpm");


                    break;

            }
            return false;
        }
    });

    private void showToast(String msg){

        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }


    public void OnOffCLICK(View view) {

        if(!mBlueAdapter.isEnabled()){
            //showToast("Activando Bluetooth...");
            Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivity(enableIntent);
            IntentFilter BTIntent = new IntentFilter((BluetoothAdapter.ACTION_STATE_CHANGED));
            registerReceiver(mBroadcastReceiver1, BTIntent);
        }
        if(mBlueAdapter.isEnabled()){
            mBlueAdapter.disable();

            IntentFilter BTIntent = new IntentFilter((BluetoothAdapter.ACTION_STATE_CHANGED));
            registerReceiver(mBroadcastReceiver1, BTIntent);
        }
    }


    public void PairedDevicesCLICK(View view) {

        if(!mBlueAdapter.isEnabled()){

            showToast("La función no está disponible porque el Bluettoth está apagado");
        }
        else{

            paired_devices = mBlueAdapter.getBondedDevices();
            mBTDevices = new ArrayList<>();
            int count = paired_devices.size();
            plist = new String[count];
            int j = 0;
            for(BluetoothDevice device : paired_devices)
            {
                mBTDevices.add(device);
                plist[j] = device.getName();
                j++;
            }

            mAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,plist);
            lvPairedDevices.setAdapter(mAdapter);
            lvPairedDevices.setOnItemClickListener(MainActivity.this);

        }
    }

    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {

        /*String deviceName = mBTDevices.get(i).getName();
        String deviceAddress = mBTDevices.get(i).getAddress();

        showToast("Connecting to: " + deviceName);*/
        /*ParcelUuid[] uuids = mBTDevices.get(i).getUuids();
        theuuid = UUID.fromString(uuids[0].toString());
        showToast(theuuid.toString());*/
        ClientClass cliente = new ClientClass(mBTDevices.get(i));
        cliente.start();

    }

    public void EnviarCLICK(View view) {

        ObdCommandGroup obdCommands = new ObdCommandGroup();

        obdCommands.add(new EchoOffCommand());
        obdCommands.add(new LineFeedOffCommand());
        obdCommands.add(new TimeoutCommand(255));
        obdCommands.add(new SelectProtocolCommand(ObdProtocols.AUTO));
        //obdCommands.add(new RPMCommand());
        obdCommands.add(rpmCommand);

        try {
            obdCommands.run(socket.getInputStream(), socket.getOutputStream());
            Message message = Message.obtain();
            message.what = STATE_DATO_ENVIADO;
            handler.sendMessage(message);

        } catch (IOException e) {
            e.printStackTrace();
            Message message = Message.obtain();
            message.what = STATE_ERROR;
            handler.sendMessage(message);
        } catch (InterruptedException e) {
            e.printStackTrace();
            Message message = Message.obtain();
            message.what = STATE_INTERRUPT;
            handler.sendMessage(message);
        }
    }

    private class ClientClass extends Thread{

        private BluetoothDevice OBD2;
        private BluetoothSocket socket;

        public ClientClass (BluetoothDevice device1)
        {
            OBD2 = device1;
            /*ParcelUuid[] uuids = OBD2.getUuids();

            if (uuids != null)
            {
                theuuid = UUID.fromString(uuids[0].toString());
                //showToast(theuuid.toString());
            }*/

            try {
                //socket = OBD2.createInsecureRfcommSocketToServiceRecord(theuuid);
                socket = OBD2.createInsecureRfcommSocketToServiceRecord(myuuid);
            } catch (IOException e) {
                e.printStackTrace();
                Message message = Message.obtain();
                message.what = STATE_ERROR;
                handler.sendMessage(message);
            }
        }

        public void run()
        {
            mBlueAdapter.cancelDiscovery();
            try {
                socket.connect();
                Message message = Message.obtain();
                message.what = STATE_CONNECTED;
                handler.sendMessage(message);

            } catch (IOException e) {
                e.printStackTrace();
                try {
                    socket.close();
                    Message message = Message.obtain();
                    message.what = STATE_CONNECTION_FAILED;
                    handler.sendMessage(message);
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                return;


            }
        }
    }
}

I expect RPMcommand result, but app crashes when i request that.

I'm the creator of the library you're using. First of all, thanks for using my project!

Reading your error log, I saw that you're having a problem with your broadcast receiver, and not with the OBD api. I think you forgot to register the receiver in the onCreate method (since you're trying to unregister in the onDestroy ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM