I could get the data appear saved in variable sbprint on screen from main activity. The varible sbprint i get from background activity that buffer bluetooth data. I want to log the data appear on screen to another class.
The problem is i can't use serializable since the data always stream from my bluetooth module in real-time mode. The code based on here
I use handler to update my UI from data buffered
NOTE: I obtain shared preference inside handler (this is inside MainActivity.java)
h = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case RECIEVE_MESSAGE: // if receive massage
byte[] readBuf = (byte[]) msg.obj;
String strIncom = new String(readBuf, 0, msg.arg1); // create string from bytes array
sb.append(strIncom); // append string
int endOfLineIndex = sb.indexOf("\r\n"); // determine the end-of-line
if (endOfLineIndex > 0) { // if end-of-line,
String sbprint = sb.substring(0, endOfLineIndex); // extract string
sb.delete(0, sb.length()); // and clear
txtArduino.setText("Data from Arduino: " + sbprint); // update TextView
SharedPreferences logPreferences = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
SharedPreferences.Editor editor = logPreferences.edit();
String textLog = txtArduino.getText().toString();
editor.putString("log", textLog);
editor.commit();
}
//Log.d(TAG, "...String:"+ sb.toString() + "Byte:" + msg.arg1 + "...");
break;
}
};
};
the h Handler get the message object from ConnectedThread class based on bluetooth documentation in this command,
h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer).sendToTarget(); // Send to message queue Handler
My question is, how do I pass the variable sbprint into my new screen in another class using handler just like above.
here's how i received data from data passed in another. I pass the data in variable buffer by getting from shared preferences as suggested
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_datalog);
tvDatalog = (TextView) findViewById(R.id.tvDatalog);
SharedPreferences logPreferences = PreferenceManager.getDefaultSharedPreferences(this);
String text = logPreferences.getString("log", "null");
tvDatalog.setText(text+"\r\n");
}
NOTE:
I got the data from my MainActivity but seems like my asynctask that works inside my MainActivity stopped as the screen change to another class. How do i make my background activity also works on both class. I mean whenever i am changing my screen on one to another the background activity always working.
If I understand correctly, you might want to use an interface. You can define an interface in the Activity that contains the Handler. Then you can implement the interface in the desired Class.
Related
I am working on an Android app that will constantly receive data from an Arduino HC-05 and store it in a database. For now I am focusing on receiving the data properly (so just displaying it on the screen is my next step).
I have followed this guide (PDF) to setup a basic app that will receive data from the Arduino. However, it doesn't include a section about using the received data. I've tried adding two lines of code to the handleMessage function in order to display the received data on screen, but I don't see any difference in the textview (it stays "Hello World!").
I know that my Arduino is sending the data just fine, since on another app called "Serial Bluetooth Terminal" it is displayed properly. Here is the code for the Handler class:
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
byte[] writeBuf = (byte[]) msg.obj;
int begin = (int)msg.arg1;
int end = (int)msg.arg2;
switch(msg.what) {
case 1:
String writeMessage = new String(writeBuf);
writeMessage = writeMessage.substring(begin, end);
// 2 lines of code I've added here:
TextView tempTextView = (TextView) findViewById(R.id.text_view);
tempTextView.setText(writeMessage);
break;
}
}
};
Aside from the 2 lines, the code is basically the same as the final stage of the guide. And here is the code for the Arduino (which currently just sends "1 2.00 3.00" over and over):
#include <SoftwareSerial.h>
SoftwareSerial BTSerial(0, 1); //RX|TX
int Temp= 1;
float Ph = 2;
float Ec = 3;
void setup() {
Serial.begin(9600);
BTSerial.begin(9600);
}
void loop() {
Serial.print(Temp);
Serial.print(" ");
delay(100);
Serial.print(Ph);
Serial.print(" ");
delay(100);
Serial.print(Ec);
Serial.print(" ");
delay(100);
Serial.print('\n');
if(Serial.available())
BTSerial.write(Serial.read());
}
I have probably a simple question but has me stumped. For my Android Wear application, I have two sensors working (step counter and heartrate).The wear app then sends these values back to the mobile application. I am sending them using the Message API. My stepcount sendMessage() and heartrate sendMessage() method look the same. Here is my heartrate sendMessage method.
private void sendMessageToHandheld(final String message) {
if (mGoogleApiClient == null)
return;
Log.d(LOG_TAG,"sending a message to handheld: "+message);
// use the api client to send the heartbeat value to our handheld
final PendingResult<NodeApi.GetConnectedNodesResult> nodes = Wearable.NodeApi.getConnectedNodes(mGoogleApiClient);
nodes.setResultCallback(new ResultCallback<NodeApi.GetConnectedNodesResult>() {
#Override
public void onResult(NodeApi.GetConnectedNodesResult result) {
final List<Node> nodes = result.getNodes();
if (nodes != null) {
for (int i=0; i<nodes.size(); i++) {
final Node node = nodes.get(i);
Wearable.MessageApi.sendMessage(mGoogleApiClient, node.getId(), message, bytes);
}
}
}
});
}
Problem is I am only using one messageReceived method on the mobile. So I cant differentiate from the step value coming in or the heartrate value coming in.
#Override
public void onMessageReceived(MessageEvent messageEvent) {
super.onMessageReceived(messageEvent);
Log.d(LOG_TAG, "received a message from wear: " + messageEvent.getPath());
if (messageEvent.getPath().contains("HEARTBEAT")){
// save the new heartbeat value
currentValue = Integer.parseInt(messageEvent.getPath());
if(handler!=null) {
// if a handler is registered, send the value as new message
Log.d(LOG_TAG, "received a heartbeat message from wear: " + messageEvent.getPath());
handler.sendEmptyMessage(currentValue);
}
}
else {
// save the new steps value
currentStepValue = Integer.parseInt(messageEvent.getPath());
if (handler != null) {
// if a handler is registered, send the value as new message
Log.d(LOG_TAG, "received a step message from wear: " + messageEvent.getPath());
handler.sendEmptyMessage(currentStepValue);
}
}
I tried passing in a byte array into the Heartrate sendMessage() and other strings as flags so that I could tell the values apart but no luck. Anyone know what the best way to go about this would be?
Any help would be appreciated.
Cheers
It seems you are sending the data inside the path attribute. This is not the correct use of this parameter.
Let's take a look at the MessageApi.sendMessage(GoogleApiClient client, String nodeId, String path, byte[] data method.
What you want to do is use String path to provide identifier for your message, for example in your case it would be step_counter and heartbeat. This way you can identify it on the other side, when you receive the message.
The sensor data should go into data field. You can put it raw there, but a better way is to create a DataMap and then serialize it into byte[]. This way you can enrich the data later easily.
I wanted to know how to send a byte in binary form via bluetooth.
At the moment I use this code:
mSendButton = (Button) findViewById(R.id.button_send);
mSendButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// Send a message using content of the edit text widget
TextView view = (TextView) findViewById(R.id.edit_text_out);
String message = view.getText().toString();
sendMessage(message);
}
});
only in this way sends string and not a byte.
Thanks for the help.
This is the source:
private void sendMessage(String message) {
// Check that we're actually connected before trying anything
if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) {
Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show();
return;
}
// Check that there's actually something to send
if (message.length() > 0) {
// Get the message bytes and tell the BluetoothChatService to write
byte[] send = message.getBytes();
mChatService.write(send);
// Reset out string buffer to zero and clear the edit text field
mOutStringBuffer.setLength(0);
mOutEditText.setText(mOutStringBuffer);
}
}
According to your source code, you are sending byte array already with the write method. If you called mChatService.write(byte[]data) so calling something like this, should work:
mChatService.write(new byte[]{5});
Where 5 is the byte value you want to send, in other words, the call to the sendMessage method is only translating your String into a byte array which is then sent to the bluetooth service.
I'm can send data from the phone to the arduino and get a response in the phone, but just in the same activity, for practical reasons I need to show the data received in the phone in another activity, so I try to pass the received data using the put extras option but I get an error and te aplication crashed, because the data is receiving in other thread I think that that could cause problems if the received data isn't complete before launch the second activity, any sugestions?
ok i have done this a really long time ago and i don't remember exactly what changes i made in the bluetooth sample so just follow these steps and you will be sending and receiving strings from any class.
if you are using the bluetooth chat example in android sdk samples, then do the following:
-in the bluetoothchat class:
*change "private" BluetoothChatService mChatService into "public".
then in the activity you want to send a string from do this
BluetoothChat.mChatService.write(byteArray);
where byteArray is as it sounds an array of bytes, so you need a a string to byte array converter to make things easy:
public static byte[] convertStringToByteArray(String s)
{
byte[] byteArray = null;
if(s!=null)
{
if(s.length()>0)
{
try
{
byteArray = s.getBytes();
} catch (Exception e)
{
e.printStackTrace();
}
}
}
return byteArray;
}
that's for sending, and as for receiving:
what i did is make a Boolean for entering and exiting a specific class so for example when i enter a class i would make this Boolean true and forward the string i receive in the Bluetoothchat class to the class i want, like for example you will go to the bluetooth chat class at these code lines:
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
// construct a string from the valid bytes in the buffer
String readMessage = new String(readBuf, 0, msg.arg1);
mConversationArrayAdapter.add(mConnectedDeviceName+": " + readMessage);
where readMessage is the string message you recieve , but instead you will make it "readMessage" a public static variable.....so you would say if i'm in activity for example number one then set the static boolean value to true and you would make a function for example called update which checks if the boolean was true then get the readMessage string and do whatever you want with it , like set text for example:
if(Bluetoothchat.one==true)
tv.settext(Bluetoothchat.readMessage);
then you need to change this boolean to false when you exit the current activity you are in so the application won't crash, so you can do something like this:
#Override
public void onBackPressed() {
BluetoothChatone.one=false;
super.onBackPressed();
}
and if you get errors tell me so i can see what i have missed to tell you.
I'm running trough a curious bug where I receive bad values from a serial connection. I created a post earlier but no one have responded yet.
[other problem] : Bluetooth SPP (serial) glitchs (Android)
Because I would like to finish this project soon I think I will have to implement a "patch" that will filter all the values. If the new value is around +/- 15% to my previous value I will keep it and if it exceed this cutoff range I will discard it. Here is the code where I receive the values :
hBluetooth = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case RECEIVE_MESSAGE: // If we receive a message
byte[] readBuf = (byte[]) msg.obj;
String stringIncome = new String(readBuf, 0, msg.arg1); // Create string from byte array
stringBuilder.append(stringIncome);
int endOfLineIndex = stringBuilder.indexOf("\r\n"); // Determine the end-of-line
Log.e(TAG, "Line"+endOfLineIndex);
if (endOfLineIndex > 0) { // If we are at the end-of-line we parsed all the data that was sent
rmsgBluetooth = stringBuilder.substring(0, endOfLineIndex); // The string is extracted in a string object rmsgBluetooth
stringBuilder.setLength(0);
Could some one help me to implement a filter that will output the retained value in a string ? Thanks.
Here is my solution :
sensorReading = Float.parseFloat(rmsgBluetooth);
if(Math.abs(sensorReadingOld - sensorReading)<10 || sensorReadingOld == 0 ){
sensorReadingOld = sensorReading;
}
else {
sensorReading = sensorReadingOld;
}