I'm writing simple OBD communicator. I'm running OBDSim (latest version) from cmd (with Administrator rights) `obdsim.exe -g gui_fltk -w COM5` (I found that COM5 port in Windows Bluetooth settings.) Then I'm launching my app with debug mode in Android Studio. I'm working in Windows 7 OS.
MainActivity.java
Client.java
I have strange infinite loops.
When I'm debugging app first time, then it works fine, but SECOND debug launch puts thread in infinite loop on `while((data = (byte) inputStream_.read()) > -1)` line i.e every second launch freezes
1st OK
2nd FAIL
3rd OK
4th FAIL
....
I also saw that when it works ok, then socket's mPort value is always 4, but when it fails, then socket's mPort value is 2.
P.S I tried use
`clientSocket_ = (BluetoothSocket)clbDevice_.getClass().getMethod("createRfcommSocket", new Class[] {int.class}).invoke(clbDevice_,1);` , but then socket connection puts thread into the infinite loop .
I also used OBDII Java API , but same result. Simple EchoOffCommand's inputstream read call puts thread into the infinite loop.
What I'm doing wrong?
MainActivity.java
Code:
com.example.bluetoothchatapp;
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Intent;
import android.content.IntentFilter;
import android.widget.*;
import android.view.*;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import java.util.ArrayList;
import java.util.Set;
public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener
{
private TextView txvAdapterInfo;
private ListView lstBondedList;
private TextView txtEngineRpm;
ArrayList<String> bondedDevList = new ArrayList<>();
ArrayAdapter<String> bondedAdapter;
private BluetoothAdapter mBAdapter;
private ArrayList<BluetoothDevice> mBDeviceList;
private BluetoothDevice mBDevice;
Client client;
final Handler mHandler = new Handler()
{
public void handleMessage(Message msg)
{
Bundle b;
b = msg.getData();
txtEngineRpm.setText(String.valueOf(b.getInt("rpm")));
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txvAdapterInfo = findViewById(R.id.txvAdapterInfo);
lstBondedList = findViewById(R.id.lstBondedList);
bondedAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_activated_1, bondedDevList);
lstBondedList.setAdapter(bondedAdapter);
lstBondedList.setOnItemClickListener(MainActivity.this);
txtEngineRpm = findViewById(R.id.txtEngineRpm);
txtSpeed = findViewById(R.id.txtSpeedLog);
mBDeviceList = new ArrayList<>();
initBluetoothAdapter();
}
@Override
protected void onDestroy()
{
super.onDestroy();
unregisterReceiver(mBroadCastReceiver);
}
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l)
{
mBAdapter.cancelDiscovery();
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2 && i <= mBDeviceList.size())
{
mBDevice = mBDeviceList.get(i);
client = new Client(mBDevice, mHandler);
client.run();
}
}
public int getBondedDevicesList()
{
Set<BluetoothDevice> pairedDevices = mBAdapter.getBondedDevices();
if(pairedDevices.size() > 0)
{
for(BluetoothDevice device : pairedDevices)
{
mBDeviceList.add(device);
bondedDevList.add(device.getName());
bondedAdapter.notifyDataSetChanged();
}
}
return 1;
}
public int initBluetoothAdapter()
{
mBAdapter = BluetoothAdapter.getDefaultAdapter();
if(mBAdapter == null)
{
return -1;
}
if(!mBAdapter.isEnabled())
{
mBAdapter.enable();
}
String adapterMACAdress = mBAdapter.getAddress();
String adapterName = mBAdapter.getName();
txvAdapterInfo.setText(adapterMACAdress + " , " + adapterName);
getBondedDevicesList();
return 1;
}
}
Client.java
Code:
package com.example.bluetoothchatapp;
import android.bluetooth.BluetoothDevice;
import com.github.pires.obd.commands.SpeedCommand;
import com.github.pires.obd.commands.protocol.*;
import com.github.pires.obd.enums.ObdProtocols;
import com.github.pires.obd.commands.engine.*;
import android.bluetooth.BluetoothSocket;
import android.os.Handler;
import android.os.Message;
import android.os.Bundle;
import java.io.IOException;
import java.io.InputStream;
import java.io_OutputStream;
import java.lang.InterruptedException;
import java.lang.reflect.InvocationTargetException;
import java.util.UUID;
public class Client implements Runnable , OBDCommands
{
private Handler clHandler_;
private BluetoothDevice clbDevice_;
private BluetoothSocket clientSocket_;
private InputStream inputStream_;
private OutputStream outputStream_;
StringBuilder obdReadResult_;
private Bundle transferBundle_;
public Client(BluetoothDevice device, Handler handler)
{
clbDevice_ = device;
clHandler_ = handler;
transferBundle_ = new Bundle(1);
obdReadResult_ = new StringBuilder();
}
public void initOBDAdapter() throws InterruptedException
{
try
{
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
try
{
clientSocket_ = clbDevice_.createInsecureRfcommSocketToServiceRecord(uuid);
}
catch (IOException e)
{
e.printStackTrace();
}
try
{
clientSocket_.connect();
}
catch (IOException e)
{
e.printStackTrace();
}
InputStream tmpIn = null;
OutputStream tmpOut = null;
try
{
tmpIn = clientSocket_.getInputStream();
tmpOut = clientSocket_.getOutputStream();
}
catch (IOException e)
{
e.printStackTrace();
}
inputStream_ = tmpIn;
outputStream_ = tmpOut;
synchronized (Client.class)
{
// String ATZ = "AT Z\r"; define in simple OBDCommands interface
writeToOBD(ATZ.getBytes());
readFromOBD();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
public void writeToOBD(byte[] data) throws IOException
{
outputStream_.write(data);
outputStream_.flush();
try
{
Thread.sleep(200);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
public void readFromOBD() throws IOException
{
try
{
obdReadResult_.setLength(0);
byte data;
while((data = (byte) inputStream_.read()) > -1)
{
char c = (char) data;
if(c == '>')
{
break;
}
obdReadResult_.append(c);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
public void logEngine() throws InterruptedException
{
try
{
writeToOBD(ERPM.getBytes());
readFromOBD();
}
catch (IOException e)
{
e.printStackTrace();
}
}
public void run()
{
try
{
initOBDAdapter();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
while (true)
{
try
{
logEngine();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
String tmpStrValue = obdReadResult_.toString().replaceAll("(\\r|\\n)", "");
int rpmValue = Integer.parseInt(tmpStrValue.substring(4, tmpStrValue.length()), 16) / 4;
transferBundle_.putInt("rmp", rpmValue);
Message msg = clHandler_.obtainMessage();
msg.setData(transferBundle_);
clHandler_.sendMessage(msg);
}
}
}
I have strange infinite loops.
When I'm debugging app first time, then it works fine, but SECOND debug launch puts thread in infinite loop on `while((data = (byte) inputStream_.read()) > -1)` line i.e every second launch freezes
1st OK
2nd FAIL
3rd OK
4th FAIL
....
I also saw that when it works ok, then socket's mPort value is always 4, but when it fails, then socket's mPort value is 2.
P.S I tried use
`clientSocket_ = (BluetoothSocket)clbDevice_.getClass().getMethod("createRfcommSocket", new Class[] {int.class}).invoke(clbDevice_,1);` , but then socket connection puts thread into the infinite loop .
I also used OBDII Java API , but same result. Simple EchoOffCommand's inputstream read call puts thread into the infinite loop.
What I'm doing wrong?