I have setup two commands in Oncreate and both send data to a bluetooth device. I need the 2nd command to wait for a data string to be received from the 1st command before advancing to the 2nd command. Each command just send a byte to BT. I tried a while looping true but does not seam to work and hangs on the while true statement. I assume the while true is not letting the handler fire when in the loop. Both commands work fine individually as long as I don't send both.
This is the code in Oncreate with both commands and while true statement
looping=true;
intByteCount =9;
GetData(intCommand); // (Command 1)Send byte to get data on reveiver
while( looping) { // Wait add data to be received before next command
Log.d("TAG", "On Hold ? ");
}
intByteCount=160; // (command 2)
GetTitle(intCommand);
This is the code in a handler for bluetooth that sets the looping to false once all the bytes have been received.
Handler h = new Handler() {
#Override
// public void handleMessage(android.os.Message msg) {
public void handleMessage(android.os.Message msg) {
byte[]readBuf = (byte[]) msg.obj;
if (intByteCount==9){
// Data is channel status and Master value
byte[] encodedBytes = new byte[5];
System.arraycopy(readBuf, 0, encodedBytes, 0, encodedBytes.length);
looping=false;
};
The GetTitle and GetData are basically the same
Here is the GetTitle()
private void GetData(int FixtureNumber) {
Log.d("TAG", "Value " + intArrayToInt(intArray1));
intByteCount=9; // set to receive 9 bytes
byte buffer[] = new byte[6];
buffer[0] = ((byte) 1); // Command (get data)
buffer[1] = ((byte) Master_value);
buffer[2] = ((byte) intArrayToInt(intArray1));
buffer[3] = ((byte) intArrayToInt(intArray2));
buffer[4] = ((byte) 3);
buffer[5] = ((byte) 4);
if (isBTConnected) {
try {
mmOutputStream.write(buffer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Here is the final code to get both control data
new Thread(new Runnable() {
#Override
public void run() {
intByteCount =9;
GetData(intCommand); // Send byte to get data on reveiver
//you can use a for here and check if the command was executed or just wait and execute the 2nd command
try {
Thread.sleep(1000); //wait 2 seconds
} catch (InterruptedException e) {
e.printStackTrace();
}
intByteCount=160; // Sed incoming data byte count
GetTitle(intCommand);
}
}).start();
You can use a Thread and wait x amount of time, :
new Thread(new Runnable() {
#Override
public void run() {
//your 1st command
//you can use a for here and check if the command was executed or just wait and execute the 2nd command
try {
Thread.sleep(2000); //wait 2 seconds
} catch (InterruptedException e) {
e.printStackTrace();
}
//your 2nd command
}
}).start();
Thank you Agustin that worked fine. The received data was quick so just a delay will work without the control boolean. Here is the new code.
new Thread(new Runnable() {
#Override
public void run() {
intByteCount =9;
GetData(intCommand); // Send byte to get data on reveiver
//you can use a for here and check if the command was executed or just wait and execute the 2nd command
try {
Thread.sleep(1000); //wait 2 seconds
} catch (InterruptedException e) {
e.printStackTrace();
}
intByteCount=160; // Sed incoming data byte count
GetTitle(intCommand);
}
}).start();
You are currently holding up the main thread there, something it is not advised to do. The best option for this is to modify the code so that the second Bluetooth command is done in a function that is called where the looping == false code is used.
Related
My code is starting to get a bit hard to debug which leads me to believe that my design choices are not ideal. I am a novice Android programming and would love some help with streamlining the design for optimum operation.
Intro
I am writing an application that uses rfcomm interface to transfer data between a client and server device. The client needs to request certain things from the server using a specific key, then it needs to wait until the server sends the result back.
Current Design
A button press triggers a request for information from the server.
A new thread is started which performs the request.
A key which is a unique integer is converted to a byte array and sent to the server.
Thread has a while loop that is waiting for a specific boolean to flip from false to true indicating a response back from the server.
Information is received on the server side. Server uses key to identify what to do next.
server starts a thread to run some query and gets a jsonString back as a result.
Server sends jsonstring converted to byte array prepended with the same identifying key back to the client.
Client reads message, and sends the byte array to a handling method based on the identifying key.
Handling method stores jsonString to a class variable and then flips the boolean to let the other thread know that the value it was waiting on has been set.
Json string is converted to object on the client side. Something is done with that object.
This code currently correctly sends info to the server, server correctly does search and gets a valid json string result. However, the issue occurs when the server writes its results make to the client. I am getting 20 messages instead of one and none match the search key...
My questions
Am I doing things in an efficient way design wise?
Can I benefit from using synchronized keyword or and Atomic Boolean to make my code more thread safe? How would I go about implementing it?
Is there a max length for converting strings to byte array? Maybe the code is trying to break up the sending for me and that's why I'm getting 20 different results?
Relevant code
public class ClientSpokesmanClass {
private final int searchKey = 2222222; //set the key to some int.
private boolean pendingSearchResults = false;
List<Place> places = new ArrayList<Place>();
private final Handler handler = new Handler(){
#Override
public void handleMessage(Message msg){
switch(msg.what) {
...
case MESSAGE_READ:
//Message received from server
readAndDistribute(msg.arg1, msg.obj);
break;
...
}
}
};
public List<Place> getPlacesFromServer(String query){
//ask server for search results
requestSearchFromServer(query);
//just wait for them...
while (pendingSearchResults){
//just waiting
}
return places;
}
private void requestSearchFromConnectedDevice(String query) {
if (mBluetoothState == STATE_CONNECTED){
byte[] bites = new byte[4];
bites = ByteBuffer.wrap(bites).putInt(searchKey).array();
byte[] stringBytes = null;
try {
stringBytes = query.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
Log.e(TAG, "unsupported encoding", e);
}
int keyLength = bites.length;
int stringLength = stringBytes.length;
byte[] combined = new byte[keyLength+stringLength];
System.arraycopy(bites, 0, combined, 0, keyLength);
System.arraycopy(stringBytes, 0, combined, keyLength, stringLength);
mBluetoothService.write(combined);
}
pendingSearchResults = true;
}
private void receiveSearchResults(byte[] bites){
String jsonString = "";
PlacesJSONParser parser = new PlacesJSONParser();
try {
jsonString = new String(bites, "UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
Log.e(TAG, "unsupported encoding", e);
}
if (D) Log.d(TAG, "Json string we got is "+jsonString);
try {
places = parser.parse(new JSONObject(jsonString));
} catch (JSONException e) {
// TODO Auto-generated catch block
Log.e(TAG, "JSON exception", e);
}
pendingSearchResults = false;
}
/**
* Reads come here first. Then, based on the key prepended to them,
* they then go to other methods for further work.
* #param bytes
* #param buffer
*/
private synchronized void readAndDistribute(int bytes, Object buffer){
byte[] buff = (byte[]) buffer;
int key = ByteBuffer.wrap(Arrays.copyOfRange(buff, 0, 4)).getInt();
if (key == searchKey){
receiveSearchResults(Arrays.copyOfRange(buff, 4, bytes));
}else{
//do something else
}
}
}
.
public class ClientUI extends Activity {
...
onQueryTextSubmit(String query){
final String queryFinal = query;
Thread thread = new Thread(){
public void run() {
places = ClientSpokesmanClass.getPlacesFromServer(query);
doSomethingWithPlaces();
}
};
thread.start();
}
}
.
public class ServerReceive {
private searchKey = 2222222;
...
//code that handles messages, reads key, and then runs doSearchAndWriteResults()
...
private synchronized void doSearchAndWriteResults(byte[] bites){
if (D) Log.d(TAG, "+++writeSearchResults");
//Initialize query and placesString
String query = null;
String placesString;
//Convert byte array to the query string
try {
query = new String(bites, "UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
Log.e(TAG, "unsupported encoding",e);
}
//if the string was converted successfully...
if (query != null){
//Run the places query and set the json string to placesString
if (D) Log.d(TAG, "query is "+query);
PlacesProvider placeProvider = new PlacesProvider();
placesString = placeProvider.getPlacesString(query);
}
//initialize a bite array
byte[] stringBytes = null;
try {
//convert jsonString to byte array
stringBytes = placesString.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
Log.e(TAG, "unsupported encoding",e);
}
//Put the search key to a byte array. I am using this key on the client side
//to confirm that we are reading searchResults and not some other type of write.
byte[] bite = new byte[4];
bite = ByteBuffer.wrap(bite).putInt(searchKey).array();
//Get the lengths of the two byte arrays
int keyLength = bite.length;
int stringLength = stringBytes.length;
//combine the byte arrays for sending
byte[] combined = new byte[keyLength+stringLength];
System.arraycopy(bite, 0, combined, 0, keyLength);
System.arraycopy(stringBytes, 0, combined, keyLength, stringLength);
if (D) Log.d(TAG, "Actually writing things here...");
//send the byte arrrays over rfcomm
mBluetoothService.write(combined);
}
}
Take a look at https://github.com/gettyimages/connect_sdk_java. Specifically, at the test application. It performs a search using an AsyncTask and the private class notifies the UI via onPostExecute. Hopefully, this will get you further along.
In the bluetoothChat example app, the sent and received data is added into a ArrayAdapter called mConversationArrayAdapter. There, each character is added into the array.
In my case, I have a String instead of an array because I don't need to send and receive several data, I only need to send one string, and receive one string each time.
The problem that I'm getting is that if I first receive a string like hello world, and then I receive a shorter one, the first is overwrited by the second, instead of deleting the first and writing the new.
So, if i first receive hello world, and then I supposse that I have to receive bye, what I really receive is byelo world.
So, how can I clear the buffer each time a receive what I want?
Code Snipets
Send data:
byte[] send1 = message_full1.getBytes();
GlobalVar.mTransmission.write(send1);
Write call:
public void write(byte[] out) {
/**Create temporary object*/
ConnectedThread r;
/**Synchronize a copy of the ConnectedThread*/
synchronized (this) {
if (GlobalVar.mState != GlobalVar.STATE_CONNECTED) return;
r = GlobalVar.mConnectedThread;
}
/**Perform the write unsynchronized*/
r.write(out);
}
Write Thread:
public void write(byte[] buffer) {
try {
GlobalVar.mmOutStream.write(buffer);
/**Share the sent message back to the UI Activity*/
GlobalVar.mHandler.obtainMessage(GlobalVar.MESSAGE_WRITE, -1, -1, buffer).sendToTarget();
} catch (IOException e) {}
}
Finally, read Thread:
public void run() {
byte[] buffer = new byte[12]; // buffer store for the stream
int bytes; // bytes returned from read()
/**Keep listening to the InputStream until an exception occurs*/
while (true) {
try {
/**Read from the InputStream*/
bytes = GlobalVar.mmInStream.read(buffer);
/**Send the obtained bytes to the UI activity*/
GlobalVar.mHandler.obtainMessage(GlobalVar.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
} catch (IOException e) {
GlobalVar.mTransmission.connectionLost();
/**Start the service over to restart listening mode*/
//GlobalVar.mTransmission.start();
break;
}
}
}
try this
bytes = inputStream.read(buffer);
buffer[bytes] = '\0';
I been searching for my answer for a couple of hours now and I can't figure it out. Please help.
What I want to do is to use the VpnService in Android to grab network packets like the application tPacketCapture
I started by using the ToyVpn sample code from google and modifying it so I don't send the data to a server. However, I'm not sure if this is correct.
My configure method uses the wlan ip address for binder.addAddress() before calling establish(). I am using a nexus 7 and I used "adb shell netcfg | grep wlan0" to get the address:
wlan0 UP 192.168.0.6/24 0x00001043 10:bf:48:bf:5f:9d
And add it in my method:
private void configure() throws Exception {
// If the old interface has exactly the same parameters, use it!
if (mInterface != null) {
Log.i(TAG, "Using the previous interface");
return;
}
// Configure a builder while parsing the parameters.
Builder builder = new Builder();
builder.setMtu(1500);
builder.addAddress("192.168.0.6", 24);
try {
mInterface.close();
} catch (Exception e) {
// ignore
}
mInterface = builder.establish();
}
After calling this, I call the run method which I modified to pass a String instead of a InetSocketAddress and this is not important because I am not using it anywhere:
private void run(String run) throws Exception {
configure();
FileInputStream in = new FileInputStream(mInterface.getFileDescriptor());
// Allocate the buffer for a single packet.
ByteBuffer packet = ByteBuffer.allocate(32767);
// We use a timer to determine the status of the tunnel. It
// works on both sides. A positive value means sending, and
// any other means receiving. We start with receiving.
int timer = 0;
// We keep forwarding packets till something goes wrong.
while (true) {
// Assume that we did not make any progress in this iteration.
boolean idle = true;
// Read the outgoing packet from the input stream.
int length = in.read(packet.array());
if (length > 0) {
Log.i(TAG,"************new packet");
while (packet.hasRemaining()) {
Log.i(TAG,""+packet.get());
//System.out.print((char) packet.get());
}
// Write the outgoing packet to the tunnel.
packet.limit(length);
// tunnel.write(packet);
packet.clear();
// There might be more outgoing packets.
idle = false;
// If we were receiving, switch to sending.
if (timer < 1) {
timer = 1;
}
}
}
}
When I do adb logcat, nothing is happening. Am I going about this correctly? I feel like I am missing something.
Thank you!
EDIT:
From the logs I see the following lines:
I/ActivityManager( 460): START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.android.toyvpn/.ToyVpnClient} from pid 10247
I/ActivityManager( 460): Start proc com.example.android.toyvpn for activity com.example.android.toyvpn/.ToyVpnClient: pid=10287 uid=10122 gids={50122, 3003, 1028}
I/ActivityManager( 460): Displayed com.example.android.toyvpn/.ToyVpnClient: +1s144ms
I/Vpn ( 460): Switched from [Legacy VPN] to com.example.android.toyvpn
D/Vpn ( 460): setting state=IDLE, reason=prepare
I/ToyVpnService(10287): running vpnService
D/Vpn ( 460): setting state=CONNECTING, reason=establish
D/VpnJni ( 460): Address added on tun0: 192.168.0.6/24
I/Vpn ( 460): Established by com.example.android.toyvpn.ToyVpnService on tun0
W/ContextImpl( 460): Calling a method in the system process without a qualified user: android.app.ContextImpl.bindService:1406 com.android.server.connectivity.Vpn.establish:289 com.android.server.ConnectivityService.establishVpn:3263 android.net.IConnectivityManager$Stub.onTransact:504 android.os.Binder.execTransact:351
D/Vpn ( 460): setting state=AUTHENTICATING, reason=establish
So it seems to be connecting.
Full source:
public class ToyVpnService extends VpnService implements Handler.Callback, Runnable {
private static final String TAG = "ToyVpnService";
private Handler mHandler;
private Thread mThread;
private ParcelFileDescriptor mInterface;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// The handler is only used to show messages.
if (mHandler == null) {
mHandler = new Handler(this);
}
// Stop the previous session by interrupting the thread.
if (mThread != null) {
mThread.interrupt();
}
// Start a new session by creating a new thread.
mThread = new Thread(this, "ToyVpnThread");
mThread.start();
return START_STICKY;
}
#Override
public void onDestroy() {
if (mThread != null) {
mThread.interrupt();
}
}
#Override
public boolean handleMessage(Message message) {
if (message != null) {
Toast.makeText(this, message.what, Toast.LENGTH_SHORT).show();
}
return true;
}
#Override
public synchronized void run() {
Log.i(TAG,"running vpnService");
try {
runVpnConnection();
} catch (Exception e) {
e.printStackTrace();
//Log.e(TAG, "Got " + e.toString());
} finally {
try {
mInterface.close();
} catch (Exception e) {
// ignore
}
mInterface = null;
mHandler.sendEmptyMessage(R.string.disconnected);
Log.i(TAG, "Exiting");
}
}
private boolean runVpnConnection() throws Exception {
configure();
FileInputStream in = new FileInputStream(mInterface.getFileDescriptor());
// Allocate the buffer for a single packet.
ByteBuffer packet = ByteBuffer.allocate(32767);
// We keep forwarding packets till something goes wrong.
while (true) {
// Assume that we did not make any progress in this iteration.
boolean idle = true;
// Read the outgoing packet from the input stream.
int length = in.read(packet.array());
if (length > 0) {
Log.i(TAG,"************new packet");
System.exit(-1);
while (packet.hasRemaining()) {
Log.i(TAG,""+packet.get());
//System.out.print((char) packet.get());
}
packet.limit(length);
// tunnel.write(packet);
packet.clear();
// There might be more outgoing packets.
idle = false;
}
Thread.sleep(50);
}
}
public String getLocalIpAddress()
{
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
Log.i(TAG,"****** INET ADDRESS ******");
Log.i(TAG,"address: "+inetAddress.getHostAddress());
Log.i(TAG,"hostname: "+inetAddress.getHostName());
Log.i(TAG,"address.toString(): "+inetAddress.getHostAddress().toString());
if (!inetAddress.isLoopbackAddress()) {
//IPAddresses.setText(inetAddress.getHostAddress().toString());
Log.i(TAG,"IS NOT LOOPBACK ADDRESS: "+inetAddress.getHostAddress().toString());
return inetAddress.getHostAddress().toString();
} else{
Log.i(TAG,"It is a loopback address");
}
}
}
} catch (SocketException ex) {
String LOG_TAG = null;
Log.e(LOG_TAG, ex.toString());
}
return null;
}
private void configure() throws Exception {
// If the old interface has exactly the same parameters, use it!
if (mInterface != null) {
Log.i(TAG, "Using the previous interface");
return;
}
// Configure a builder while parsing the parameters.
Builder builder = new Builder();
builder.setMtu(1500);
builder.addAddress("192.168.0.6", 24);
try {
mInterface.close();
} catch (Exception e) {
// ignore
}
mInterface = builder.establish();
}
}
Ok, it was not easy at all but I figured out how to capture packets. Since I am not extremely familiar with networking (but this new job is requesting that I am) I had difficulty with setting everything correctly. Basically after setting the right route in the VpnService.builder I got to receiving packets correctly.
So:
builder.addAddress("192.168.0.6", 24); // was wrong, you need to put an internal IP (10.0.2.0 for example)
and
builder.addRoute("0.0.0.0", 0); // needs to be this.
you don't need to set up a DnsServer through builder.addDnsServer() to make it work. Hope this helps anyone!
My configure method uses the wlan ip address for binder.addAddress() before >calling establish(). I am using a nexus 7 and I used "adb shell netcfg | grep >wlan0" to get the address:
wlan0 UP 192.168.0.6/24 0x00001043 10:bf:48:bf:5f:9d
I have wrote a simple script in python to show you netcfg graphically from adb.
It is updating every second.
https://github.com/ilanben/graphical_netcfg
Enjoy :)
i wrote a Server for our global Leadbord which actually works now.
I can send data to it if it's active. But if it's down my app does not stop. I dont get a solution for it i hope you can help me. Here is the sending:
public void saveToDatabase(LeadboardElement element2) {
final LeadboardElement element = element2;
send = false;
// Need to be a thread! else android blocks it because it could take to
// long to send!
this.thread = new Thread() {
public void run() {
try {
Socket soc = new Socket(Config.TCP_SERVERNAME_IP,
Config.TCP_PORT);
DataOutputStream out = new DataOutputStream(
soc.getOutputStream());
DataInputStream in = new DataInputStream(
new BufferedInputStream(soc.getInputStream()));
// to call the save statement!
out.writeInt(0);
// give the stuff
out.writeUTF(element.getName());
out.writeInt(element.getLevel());
out.writeInt(element.getKillPoints());
// close it
out.close();
in.close();
soc.close();
send = true;
//join at every error
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
};
// start it
thread.start();
// join thread
if (!send) {
boolean retry = true;
while(retry)
try {
this.thread.join();
retry = false;
Log.w(TAG, "sending to server stopped!");
} catch (InterruptedException e2) {
Log.w(TAG, "Thread could not be joined");
}
}
}
I noticed that i need to do it in a thread since API 5 so it works like this. It's called at the end of an Game if the player touches the screen. Everything get stopped and the data is sent to the Server. If hes down it does not work we stuck in the fade to black.
I guess i need something like a timeout. I tried it with a CountDownTimer but this acutally does not solve the problem.
Thanks alot!
Changing the way you initialize the socket, you can set a timeout.
Socket s1 = new Socket();
s1.setSoTimeout(200);
s1.connect(new InetSocketAddress("192.168.1." + i, 1254), 200);
Add a timeout when creating a new Socket
I have been using InputStream.read( byte[] b, int off, int len ) method to read in data, but now have run into a timeout problem. I am sometimes expecting timeouts from reading, and should have the program adjust itself accordingly after a timeout. I have tried to implement a Thread but I really know nothing about Threads and cannot get it to work. I also want to add that this thread is being initialized within another thread. I'm not sure what the implications of this are but it may cause a problem.
My initial code had worked for the majority of times I need to read, but whenever I'm expecting a timeout, my program freezes at the read() call and never times out. When I implemented this new code, the times when my initial code worked now time out. I use Thread.wait(500) which I assume is 500 milliseconds, but I cannot find any Javadocs including the wait() function. Here and Here.
Other posts relating to this: 1, 2, 3.
I have also looked into declaring a timeout for the BluetoothSocket, but I cannot find it anywhere in the documentation.
Here is what my initial code looks like:
public void run(int length) throws IOException {
buffer = new byte[1024];
try {
bytes = mmInStream.read(buffer, 0, length);
mHandler.obtainMessage(MainMenu.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Message msg = mHandler.obtainMessage(MainMenu.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString( TOAST, "Device has disconnected from the Bluetooth Module." );
msg.setData(bundle);
mHandler.sendMessage(msg);
connectionLost();
BluetoothService.this.start();
}
This is what I have tried to implement:
public void run(int length) throws IOException {
buffer = new byte[1024];
length1 = length;
Thread myThread = new Thread(new Runnable() {
public void run() {
try {
bytes = mmInStream.read( buffer, 0, length1 );
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
synchronized (myThread) {
myThread.start();
try {
myThread.wait(500);
if(myThread.isAlive()) {
mmInStream.close();
Log.i( "InStream", "Timeout exceeded!");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
myThread.run();
mHandler.obtainMessage(MainMenu.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Message msg = mHandler.obtainMessage(MainMenu.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString( TOAST, "Device has disconnected from the Bluetooth Module." );
msg.setData(bundle);
mHandler.sendMessage(msg);
connectionLost();
BluetoothService.this.start();
}
EDIT:
So I'm trying to recreate
buffer = new byte[1024];
bytes = mmInStream.read(buffer, 0, length);
I have done the following:
Scanner scan = new Scanner(new InputStreamReader(mmInStream));
String readIn;
try {
readIn = scan.next();
bytes = 5; // I tried with or without this, since I do not think it matters...
buffer = readIn.getBytes( Charset.forName( "US-ASCII" ) );
}
Later in my code I make this call....Sorry edit again, the buf=read( 5 ) call goes to what is shown above.
byte[] buf = buffer;
write( a );
buf = read( 5 );
Log.i(TAG, "Before buf[5]" );
try {
buf[5] = '\0';
} catch( NullPointerException e ) {
return false;
}
When I use the original method, It passes this buf[5] call fine. But when I use the new method, it gives me an IndexOutOfBoundsException at that spot. Am I missing something? The expected input should be CMD\r\n
The bluetooth chat example is really poor in this respect, you should use an input scanner instead of mmInStream.read. Here's what I use and it works reasonably well...
For your use case you skip the entire buffer and byte and write and read (no need to use any of those when you are using a scanner and inputstreamreader as those handle that stuff for you)... in other words the below code takes care of all that for you. I changed the delimiter for you to CRLF. What the code below does is you send a string and it writes it and then reads. If you don't need to send anything to the remote device, just start at scan = new Scanner. Each time a line is read and it ends with \r\n it will store it in the string instring.
So if you want to send "a", you would write
String readIn = beginListenForData("a");
The a will be sent under the mmOutStream and then the scanner will read the mmInStream and collect all the characters, then once it sees a CRLF it will return the characters it read and return them in your readIn string. Make sense?
private String beginListenForData(String msg0) {
msg0 += "\r"; //this adds a return character to the string, you can omit this if you just send an a and the remote device understands what that means.
String instring = "";
try {
mmOutStream.write(msg0.getBytes());
} catch (IOException ex) {
stop();
}
scan = new Scanner(new InputStreamReader(mmInStream));
scan.useDelimiter(Pattern.compile("[\\r\\n]+"));
instring = scan.next();
scan = null;
return instring;
}