我正在编写简单的OBD通信器。我正在从cmd(具有管理员权限)obdsim.exe -g gui_fltk -w COM5
中运行OBDSim(最新版本)(我在Windows蓝牙设置中找到了COM5端口。)然后在Android Studio中以调试模式启动我的应用程序。我正在Windows 7 OS中工作。
MainActivity.java
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
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);
}
}
}
我很奇怪。
第一次调试应用程序时,它可以正常工作,但第二次调试启动会将线程置于while((data = (byte) inputStream_.read()) > -1)
行的无限循环中,即每隔一秒启动就会冻结
一等
第二次失败
第三好
第四次失败
....
我还看到,当其正常运行时,套接字的mPort值始终为4,但是当失败时,套接字的mPort值始终为2。
我尝试使用的PS
clientSocket_ = (BluetoothSocket)clbDevice_.getClass().getMethod("createRfcommSocket", new Class[] {int.class}).invoke(clbDevice_,1);
,但是套接字连接将线程置于无限循环中。
我还使用了OBDII Java API,但结果相同。简单的EchoOffCommand的inputstream读取调用将线程置于无限循环中。
我做错了什么?