我正在构建一个能够从负载传感器读取值的Android应用程序。负载传感器连接到LCD,以显示应用于传感器和Arduino板的重量值。我只是构建这个应用程序来获取LCD /负载传感器的重量值。我正在使用HC-06蓝牙模块,我能够成功连接/配对此设备。 ' MainActivity'活动有一个获取数据'按钮从负载传感器读取数据,但随时按下该应用程序冻结。以下教程的作者告诉我,我需要写一些' Handler'方法。我做了一个没有运气的尝试。
我一直在关注本教程,但我仍然坚持阅读数据
这是我的代码:
package com.proj.splate;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
@SuppressWarnings("unused")
public class MainActivity extends Activity {
Button btnscan;
TextView txtArduino, txtString, txtStringLength, calorie;
Handler bluetoothIn;
final int handlerState = 0; //used to identify handler message
private BluetoothAdapter btAdapter = null;
private BluetoothSocket btSocket; //= null;
private StringBuilder recDataString = new StringBuilder();
private ConnectedThread mConnectedThread;
// SPP UUID service - this should work for most devices
private static final UUID BTMODULEUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
// String for MAC address
private static String address;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Link the buttons and textViews to respective views
btnscan = (Button) findViewById(R.id.scanBtn);
txtString = (TextView) findViewById(R.id.txtString);
txtStringLength = (TextView) findViewById(R.id.testView1);
bluetoothIn = new Handler() {
public void handleMessage(android.os.Message msg) {
if (msg.what == handlerState) {
String readMessage = (String) msg.obj;
recDataString.append(readMessage);
int endOfLineIndex = recDataString.indexOf("~");
if (endOfLineIndex > 0) {
String dataInPrint = recDataString.substring(0, endOfLineIndex);
txtString.setText("Data Received = " + dataInPrint);
int dataLength = dataInPrint.length();
txtStringLength.setText("String Length = " + String.valueOf(dataLength));
if (recDataString.charAt(0) == '#')
{
//get sensor value from string between indices 1-20
String weight = recDataString.substring(1, 20);
//update the textviews with sensor values
calorie.setText(weight + "kg");
}
recDataString.delete(0, recDataString.length());
// strIncom =" ";
dataInPrint = " ";
}
}
}
};
btAdapter = BluetoothAdapter.getDefaultAdapter(); // get Bluetooth adapter
checkBTState();
// Set up onClick listeners for button to scan for data
btnscan.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mConnectedThread.write("0");
}
});
}
private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
return device.createRfcommSocketToServiceRecord(BTMODULEUUID);
//creates secure outgoing connecetion with BT device using UUID
}
@Override
public void onResume() {
super.onResume();
//Get MAC address from DeviceListActivity via intent
Intent intent = getIntent();
//Get the MAC address from the DeviceListActivty via EXTRA
address = intent.getStringExtra(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
//create device and set the MAC address
BluetoothDevice device = btAdapter.getRemoteDevice(address);
try {
btSocket = createBluetoothSocket(device);
} catch (IOException e) {
Toast.makeText(getBaseContext(), "Socket creation failed", Toast.LENGTH_LONG).show();
}
// Establish the Bluetooth socket connection.
try
{
btSocket.connect();
} catch (IOException e) {
try
{
btSocket.close();
} catch (IOException e2)
{
//insert code to deal with this
}
}
mConnectedThread = new ConnectedThread(btSocket);
mConnectedThread.start();
//I send a character when resuming.beginning transmission to check device is connected
//If it is not an exception will be thrown in the write method and finish() will be called
mConnectedThread.write("x");
}
@Override
public void onPause()
{
super.onPause();
try
{
//Don't leave Bluetooth sockets open when leaving activity
btSocket.close();
} catch (IOException e2) {
//insert code to deal with this
}
}
//Checks that the Android device Bluetooth is available and prompts to be turned on if off
private void checkBTState() {
if(btAdapter==null) {
Toast.makeText(getBaseContext(), "Device does not support bluetooth", Toast.LENGTH_LONG).show();
} else {
if (btAdapter.isEnabled()) {
} else {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 1);
}
}
}
//create new class for connect thread
private class ConnectedThread extends Thread {
private final InputStream mmInStream;
private final OutputStream mmOutStream;
//creation of the connect thread
public ConnectedThread(BluetoothSocket socket) {
btSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
//Create I/O streams for connection
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024];
int bytes;
// Keep looping to listen for received messages
while (true) {
try {
bytes = mmInStream.read(buffer);
bluetoothIn.obtainMessage(handlerState, bytes, -1, buffer).sendToTarget();
} catch (IOException e) {
break;
}
}
}
//write method
public void write(String input) {
byte[] msgBuffer = input.getBytes();//converts entered String into bytes
try {
mmOutStream.write(msgBuffer);//write bytes over BT connection via outstream
} catch (IOException e) {
//if you cannot write, close the application
Toast.makeText(getBaseContext(), "Connection Failed", Toast.LENGTH_LONG).show();
finish();
}
}
public class BluetoothInHandler extends Handler{
private Looper sLooper = null;
private Handler mWorkerThreadHandler;
final int handlerState = 0; //used to identify handler message
protected class WorkerArgs {
Handler handler;
String input;
String output;
}
public BluetoothInHandler() {
super();
synchronized (BluetoothInHandler.class) {
if (sLooper == null) {
HandlerThread thread = new HandlerThread("AsyncWorker");
thread.start();
sLooper = thread.getLooper();
}
}
mWorkerThreadHandler = new WorkerHandler(sLooper);
}
@Override
public void handleMessage(Message msg) {
if (msg.what == handlerState) {
WorkerArgs args = (WorkerArgs) msg.obj;
String readMessage = args.output;
//your job;
} else {
super.handleMessage(msg);
}
}
public void write(String input) {
WorkerArgs args = new WorkerArgs();
args.handler = this;
args.input = input;
Message message = mWorkerThreadHandler.obtainMessage(handlerState);
message.obj = args;
mWorkerThreadHandler.sendMessage(message);
}
protected class WorkerHandler extends Handler {
public WorkerHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
if (msg.what == handlerState) {
WorkerArgs args = (WorkerArgs) msg.obj;
byte[] buffer;
//the code here run in a thread, not in the ui thread
//do your job like:
byte[] bytes = mmInStream.read(buffer);
args.output = new String(bytes);
Message message = args.handler.obtainMessage(handlerState);
message.obj = args;
message.sendToTarget();
}
}
}
}
}//ConnectedThread End
}
这是我的Arduino代码:
#include <LiquidCrystal.h>
int led = 13;
int button = 12;
LiquidCrystal lcd(9, 8, 4, 5, 6, 7);
// Pins used for inputs and outputs********************************************************
float sensorValue1;
float containerValue;
char inbyte = 0;
int flag;
const int numReadings = 50;
int readings[numReadings];
int index = 0;
int total = 0;
int average = 0;
//*******************************************************************************************
void setup()
{
pinMode(led, OUTPUT);
digitalWrite(led, HIGH);
Serial.begin(9600);
for (int thisReading = 0; thisReading < numReadings; thisReading++)
{
readings[thisReading] = 0;
}
lcd.begin(16, 2); //change to 16, 2 for smaller 16x2 screens
lcd.clear();
lcd.print("hello, world!");
delay (1000);
lcd.clear();
delay (500);
}
void loop()
{
digitalWrite(led, HIGH);
readSensor2(); //DONE
printLCD(); //DONE
return;
sendAndroidValues();
//when serial values have been received this will be true
if (Serial.available() > 0)
{
inbyte = Serial.read();
if (inbyte == '0')
{
//LED off
digitalWrite(led, LOW);
}
if (inbyte == '1')
{
//LED on
digitalWrite(led, HIGH);
}
}
//delay by 2s. Meaning we will be sent values every 2s approx
//also means that it can take up to 2 seconds to change LED state
delay(2000);
void readSensor2()
{
total = total - readings[index];
readings[index] = analogRead(A0);
total = total + readings[index];
index = index + 1;
if (index >= numReadings)
{
index = 0;
}
average = total / numReadings;
//sensorValue1 = (analogRead(A0) - 330)* i;
//delay(200);
Serial.println(average);
delay(100);
if( digitalRead(button) == HIGH && flag == 1)
{
flag = 0;
containerValue = 0;
}
else if (digitalRead(button) == HIGH && flag != 1)
{
flag = 1; //when the button is pressed the initially sesnsor
containerValue = sensorValue1;
delay(10);
}
//Serial.println(digitalRead(button));
delay (1000);
}
//sends the values from the sensor over serial to BT module
void sendAndroidValues()
{
//puts # before the values so our app knows what to do with the data
Serial.print('#');
//for loop cycles through 4 sensors and sends values via serial
Serial.print(sensorValue1);
Serial.print('+');
//technically not needed but I prefer to break up data values
//so they are easier to see when debugging
Serial.print('~'); //used as an end of transmission character - used in app for string length
Serial.println();
delay(5000); //added a delay to eliminate missed transmissions
}
void printLCD()
{
lcd.setCursor(4, 0);
lcd.print(" GRAMS ");
lcd.setCursor(4, 1);
lcd.print(sensorValue1);
}
答案 0 :(得分:0)
不确定这是否是一个很大的问题,因为它看起来并不像你在handleMessage(Message msg)方法中做了大量的工作,但你的Handler仍在创建主线程。要使用处理程序处理背景消息,您需要将其传递给单独的Looper。一个简单的方法是使用HandlerThread类来提供你的Looper。
但是,完成此操作后,您需要将结果发布回handleMessage(Message msg)
的UI线程,因为您无法修改UI元素(或使用Toasts,请参阅您的&# 34;从主线程以外的线程写入&#34;方法)(参见Activity.runOnUiThread(Runnable runnable))。
此外,您还在使用&#34; ConnectedThread&#34;通过如何从onClickListener中调用方法来将对象作为对象...所以它并没有真正做到你在这方面打算做的事情。要验证这一点,请使用Looper.myLooper()== Looper.getMainLooper()来查看当前正在执行的线程。我建议更多地使用上面建议的Handler解决方案,并发布Runnables以供执行。
最后,由于你的ConnectedThread在一段时间(真实)循环中连续运行而没有暂停,这可能会使你的处理程序充满潜力。