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.
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 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 trying to communicate with a USB device that uses interrupt transfer for communications.
it is not a polled device, either side may send at any time. All the examples I find seem to be poll-response where you send data first, wait for the send to complete, then wait for the response, process it and then go back to sending data again.
My code is modeled after the following which I found here on stackoverflow (I'm showing the original I based it on because my own code has a lot more going on and is less compact)
boolean retval = request.queue(buffer, 1);
if (mConnection.requestWait() == request) {
// wait for confirmation (request was sent)
UsbRequest inRequest = new UsbRequest();
// URB for the incoming data
inRequest.initialize(mConnection, mEndpointIn);
// the direction is dictated by this initialisation to the incoming endpoint.
if(inRequest.queue(buffer, bufferMaxLength) == true){
mConnection.requestWait();
// wait for this request to be completed
// at this point buffer contains the data received
}
}
The second requestWait() will block until something arrives, so I can't do another TX operation until I receive something! What am I missing?
You said: "The second requestWait() will block until something arrives, so I can't do another TX operation until I receive something"
Having written code of my own also based on the example you show, I think I understand where you are confused: The second requestWait() will return for any USB operation, not just the one that preceeded it. (from the Android API documentation "Note that this may return requests queued on multiple UsbEndpoints")
So if you queue a Send request even while you are waiting, your "receive waitRequest" will return, but for the Send endpoint. You should always check the endpoint of the result of waitRequest, or compare it to the initial request itself. If it matches inRequest, then it's actually the receive operation you were blocking on. If it doesn't match, compare it to your Send request (or in my example code below, I simply assume that it's a send response and ignore it)
You will need to queue send and receive requests from different methods or threads however rather than in the same loop as is implied by the code you supplied.
Here is the code from my own project (be aware that my app is running into heap corruptions, so the code below may not be perfect, but it does allow me to send even while a receive operation is pending)
So here is my receive loop, you'll see the similarities with your code:
while(mUsbDevice != null ) {
if (inRequest.queue(buffer, BUFFER_SIZE) == true) {
// (mUsbConnection.requestWait() is blocking
if (mUsbConnection.requestWait() == inRequest){
// this is an actual receive
// do receive processing here (send to conusmer)
} else{
Log.d(TAG, "mConnection.requestWait() returned for a different request (likely a send operation)");
}
} else {
Log.e(TAG, "failed to queue USB request");
}
buffer.clear();
}
I do the sending form another thread which uses messages to queue incoming send requests:
mHandler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == 1) { // 1 means send a 64 bytes array in msg.obj
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
final byte[] array = (byte[]) msg.obj;
buffer.clear();
buffer.put( array );
UsbRequest outRequest = new UsbRequest();
outRequest.initialize(mUsbConnection, mUsbEndpointOut);
outRequest.queue(buffer, BUFFER_SIZE);
Log.d(L.TAG, "Queueing request:"+outRequest);
// don't do a mConnection.requestWait() here, ReceiveThread is already listening
} else if (msg.what == 2) { // 2 means exit
Log.d(L.TAG, "SenderThread::handleMessage(): terminate");
Looper.myLooper().quit();
} else {
Log.e(L.TAG, "SenderThread::handleMessage(): unknow message type: " + msg.what);
}
}
};
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.
i am using a single port to receive both files and messages in a messenger app. i wanted to ask how can i differenntiate between the files and the messages? i have researched and found that m going to have to make a protoco, i tried but i cant seem to make one. is there any way to accomplish this?
right now i am receiving the connection like this :
public class ReceiveConnection extends Thread {
Socket clientSocket = null;
public ReceiveConnection(Socket socket)
{
this.clientSocket = socket;
SocketOperator.this.sockets.put(socket.getInetAddress(), socket);
}
#Override
public void run() {
try {
BufferedReader in = new BufferedReader(newInputStreamReader(clientSocket.getInputStream()));
while ((inputLine = in.readLine()) != null) {
if (inputLine.contains("TEXT") == true)
{
Log.i("SocketOP","text");
appManager.messageReceived(inputLine);
}
}
if (inputLine.contains("TEXT") == false)
{
InputStream is=clientSocket.getInputStream();
while(is!= null){
Log.i("SocketOP","filee");
appManager.fileReceived(is);
}
}
i have concatinated the string "TEXT" with my text message so it is coming through. putting an ELSE statement isnt working. how can i add a notifier with the file so that i know when the file is being received?
You should create a message header that contains the following data:
Starts with unique byte sequence (2-4 bytes long) that acts as a message separator. This should be a unique non-text sequence that is not very common ( e.g. not CRLF or other control sequence).
Contains message type byte, so that you know if this is text message or file.
Contains length of the message, which helps while extracting the message.