I am creating an app for Android-Arduino bluetooth serial communication. I am able to connect to arduino successfully. My app can send data to arduino without hassle and I have verified it. But While receiving data from arduino, my app only receives a part of data being send. For example if "404" is being send from arduino, my app only show "4" as being received.
I checked with other such apps and all other apps are able to receive "404" itself. So problem is with my code.
This is my code which read data from arduino:
public String read(byte[] bytes){
try {
mInput.read(bytes);
strInput = new String(bytes);
}catch(Exception e){
e.printStackTrace();
}
return strInput;
}
//mInput is the input stream of bluetooth connection
As you can see data is recived to a byte buffer and converted to a string using new String(bytes); method. How ever when I toast the string, only 4 is being toasted instead of 404 send from arduino.
The byte buffer is of size 256.
EDIT: as requested the full code for BluetoothManager.java is this:
public class BluetoothManager {
private BluetoothAdapter bluetoothAdapter;
private BluetoothDevice bluetoothDevice;
private BluetoothSocket bluetoothSocket;
private ConnectedThread connectedThread;
private byte[] buffer;
public BluetoothManager(){
buffer=new byte[256];
bluetoothSocket=null;
bluetoothAdapter=null;
bluetoothDevice=null;
connectedThread=null;
getBluetoothAdapter();
if(!isBluetoothAvailable()){
turnBluetoothOn();
}
scanToConnect();
}
public void turnBluetoothOff(){
try {
bluetoothSocket.close();
bluetoothSocket=null;
bluetoothAdapter.cancelDiscovery();
bluetoothAdapter.disable();
bluetoothAdapter=null;
bluetoothDevice=null;
}catch(Exception e){
e.printStackTrace();
}
}
private boolean isBluetoothAvailable(){
return bluetoothAdapter.isEnabled();
}
private void turnBluetoothOn(){
bluetoothAdapter.enable();
}
public String readData(Context context){
String outputString=null;
if(isBluetoothAvailable()) {
outputString = connectedThread.read(buffer);
}else{
Toast.makeText(context, "Error: Not Connected", Toast.LENGTH_LONG).show();
}
return outputString;
}
public void writeData(String string, Context context){
if(isBluetoothAvailable()) {
connectedThread.write(string.getBytes());
}else{
Toast.makeText(context, "Error: Not Connected", Toast.LENGTH_LONG).show();
}
}
private void getBluetoothAdapter(){
try{
bluetoothAdapter=BluetoothAdapter.getDefaultAdapter();
}catch (Exception e){
e.printStackTrace();
}
}
private void scanToConnect(){
Set<BluetoothDevice> pairedDevices=bluetoothAdapter.getBondedDevices();
if(pairedDevices.size()>0){
try {
for (BluetoothDevice device : pairedDevices) {
if (device.getName().equals("HC-05")) {
bluetoothDevice = device;
new connectBt(bluetoothDevice);
break;
}
}
}catch(Exception e){
e.printStackTrace();
}
}
}
private class connectBt extends Thread {
public connectBt(BluetoothDevice device) {
BluetoothSocket tmp = null;
bluetoothDevice = device;
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
try {
tmp = device.createRfcommSocketToServiceRecord(uuid);
} catch (IOException e) {
e.printStackTrace();
}
bluetoothSocket = tmp;
run();
}
public void run() {
bluetoothAdapter.cancelDiscovery();
try {
bluetoothSocket.connect();
connectedThread = new ConnectedThread(bluetoothSocket);
} catch (IOException connectException) {
closeSocket();
}
}
private void closeSocket() {
try {
bluetoothSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private class ConnectedThread extends Thread{
private InputStream mInput=null;
private OutputStream mOutput=null;
private String strInput;
public ConnectedThread(BluetoothSocket socket){
bluetoothSocket=socket;
InputStream tmpIn=null;
OutputStream tmpOut=null;
try{
tmpIn=socket.getInputStream();
tmpOut=socket.getOutputStream();
}catch(IOException e){
e.printStackTrace();
closeSocket();
}
mInput=tmpIn;
mOutput=tmpOut;
}
public void write(byte[] bytes){
try{
mOutput.write(bytes);
}catch(IOException e){
e.printStackTrace();
}
}
public String read(byte[] bytes){
try {
mInput.read(bytes);
strInput = new String(bytes);
}catch(Exception e){
e.printStackTrace();
}
return strInput;
}
public void closeSocket(){
try{
bluetoothSocket.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}
Edit-2: On further debugging I found out that mInput.available() returns 0 while mInput.read(bytes) returns 1.Why is this behavior while in my arduino code I am using bluetooth.println("404");
http://felhr85.net/2014/11/11/usbserial-a-serial-port-driver-library-for-android-v2-0/
Try this it should work. Also please provide the full code of it. May be the Error should be in the part where you are connecting the function to Serial Event handler.
I was having the same problem. I solved by adding delimiter(\n) while sending from arduino i.e println() and checking in android code. Try below code in android, its working for me:
Try this code: http://pastebin.com/sfb3kuu6
Okey I solved this problem by putting a delay in my read() method.
Related
I am struggling to get my connect thread started when pressed "connect" button on my activity. I have tried to google the right answer for this but I have got very confused about what method to implement to get it work. I'm not sure if it's a Handler or what to be implemented with this kind of issue. I would be very thankful if someone would provide me some code template how to implement this!
To Connect
BluetoothSocket socket;
Handler bt_handler;
int handlerState;
OutputStream outputStream;
InputStream inputStream;
ConnectedThread connectedThread;
BluetoothAdapter adapter=BluetoothAdapter.getDefaultAdapter();
BluetoothDevice device=adapter.getRemoteDevice(mac_address);
UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
try {
socket=device.createInsecureRfcommSocketToServiceRecord(MY_UUID);
socket.connect();
outputStream=socket.getOutputStream();
inputStream=socket.getInputStream();
connectedThread = new ConnectedThread(socket);
connectedThread.start();
}catch(Exception e){
/** Handle the exception here **/
}
Thread
private class ConnectedThread extends Thread {
InputStream inputStream=null;
int avilableBytes=0;
public ConnectedThread(BluetoothSocket socket){
InputStream temp=null;
try{
temp=socket.getInputStream();
}catch (IOException e){
e.printStackTrace();
}
inputStream=temp;
}
public void run() {
try{
int bytes;
while (true){
try{
avilableBytes=inputStream.available();
byte[] buffer=new byte[avilableBytes];
if (avilableBytes>0){
bytes=inputStream.read(buffer);
final String readMessage=new String(buffer);
if (bytes>=3){
bt_handler.obtainMessage(handlerState, bytes, -1, readMessage).sendToTarget();
}
else {
SystemClock.sleep(100);
}
}
}catch (IOException e){
e.printStackTrace();
}
}
}catch (Exception e){
e.printStackTrace();
}
}
}
bt_handler
bt_handler=new Handler(){
#Override
public void handleMessage(Message msg) {
if (msg.what==handlerState){
String readMessage=(String)msg.obj;
Log.v(TAG, readMessage);
}
}
define bt_handler inside onCreate()
ConnectedThread is inner class.
I am trying to connect bluetooth device and want to send data to that device and also want to receive data from that device.
To achieve this I follow android developer bluetooth document but seems I unable to connect another device because while connecting it's throwing following exception.
09-13 13:27:56.913: I/BluetoothConnect(2980): Connect exception:-java.io.IOException: [JSR82] connect: Connection is not created (failed or aborted).
Steps which I follow.
Enabling Bluetooth
Intent turnOnIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(turnOnIntent, REQUEST_ENABLE_BT);
Getting Bluetooth Paired Device
Set<BluetoothDevice> bondSet = myBluetoothAdapter.getBondedDevices();
ArrayList<HashMap<String, String>> bondedhDevicesList = new ArrayList<HashMap<String, String>>();
for (Iterator<BluetoothDevice> it = bondSet.iterator(); it.hasNext();) {
BluetoothDevice bluetoothDevice = (BluetoothDevice) it.next();
HashMap<String, String> map = new HashMap<String, String>();
map.put("name", bluetoothDevice.getName());
map.put("address", bluetoothDevice.getAddress());
bondedhDevicesList.add(map);
}
Getting UUID of device
bluetoothDevice =
myBluetoothAdapter.getRemoteDevice(address);
// min api 15 !!!
Method m;
try {
m = bluetoothDevice.getClass().
getMethod("fetchUuidsWithSdp", (Class[]) null);
m.invoke(bluetoothDevice, (Object[]) null );
} catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Connecting to device
private static final UUID MY_UUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
public ConnectThread(BluetoothDevice device, String uuid, BluetoothAdapter mBluetoothAdapter) {
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
this.mBluetoothAdapter = mBluetoothAdapter;
mmDevice = device;
Method m;
try {
mBluetoothAdapter.cancelDiscovery();
mmSocket = device.createInsecureRfcommSocketToServiceRecord(MY_UUID);
m = device.getClass().getMethod("createInsecureRfcommSocket", new Class[] {int.class});
mmSocket = (BluetoothSocket) m.invoke(device, 1);
} catch (IOException | IllegalArgumentException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
// TODO Auto-generated catch block
Log.i("BluetoothConnect", e.toString());
e.printStackTrace();
}
//mBluetoothAdapter.cancelDiscovery();
//socket.connect();
}
public void run() {
// Cancel discovery because it will slow down the connection
mBluetoothAdapter.cancelDiscovery();
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
Constants.globalSocket = mmSocket;
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
Log.i("BluetoothConnect", "Connect exception:-"+connectException.toString());
try {
mmSocket.close();
} catch (IOException closeException) {
Log.i("BluetoothConnect", "close exception:-"+closeException.toString());
}
return;
}
}
But while connecting then i am getting that exception.
5. Writing to device.
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024]; // 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 = mmInStream.read(buffer);
// Send the obtained bytes to the UI activity
CreatePacket.mHandler.obtainMessage(MESSAGE_READ , bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.i("ConnectedThread", "while receiving data:-"+e.toString());
break;
}
}
}
public void write(byte[] bytes) {
Log.i("ConnectedThread", "data while writing:-"+bytes.toString());
try {
mmOutStream.write(bytes);
} catch (IOException e) {
Log.i("ConnectedThread", "while writing data to bluetooth:-"+e.toString());
}
}
If I still try to write then data then I am getting following exception.
Please give me any hint or reference.
09-13 13:48:55.079: I/ConnectedThread(2980): while writing data to bluetooth:-java.io.IOException: socket closed
I am stuck on this from last three day but still not getting any solution.
The best way is to refer the sample chat application provided by the Android. That has covered all necessary tasks like list out available devices, establish connection, send data and receive, etc. U can get that and refer.
https://android.googlesource.com/platform/development/+/eclair-passion-release/samples/BluetoothChat
Here is a sample code which I am using to connect to my Bluetooth module..
public class OpenBluetoothPort extends AsyncTask<String, Void, BluetoothSocket> {
private final UUID SPP_UUID = UUID
.fromString("00001101-0000-1000-8000-00805F9B34FB");
private BluetoothAdapter mBluetoothAdapter;
private OnBluetoothPortOpened mCallback;
private BluetoothSocket mBSocket;
public interface OnBluetoothPortOpened {
public void OnBluetoothConnectionSuccess(BluetoothSocket socket);
public void OnBluetoothConnectionFailed();
}
public OpenBluetoothPort(Context context, OnBluetoothPortOpened callback) {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mCallback = callback;
}
#Override
protected BluetoothSocket doInBackground(String... params) {
if(mBluetoothAdapter.isEnabled()) {
try {
for(BluetoothDevice bt: mBluetoothAdapter.getBondedDevices()) {
if(bt.getName().equalsIgnoreCase(params[0])) {
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(bt.getAddress());
mBluetoothAdapter.cancelDiscovery();
mBSocket = device.createRfcommSocketToServiceRecord(SPP_UUID);
mBSocket.connect();
return mBSocket;
}
}
} catch(IOException e) {
if(mBSocket != null) {
try {
mBSocket.close();
} catch (IOException e1) {
Log.i("Bluetooth Close Exception","Error in closing bluetooth in OpenBluetoothPort.class");
e1.printStackTrace();
}
mBSocket = null;
}
Log.i("Bluetooth Connect Exception","Error in connecting in OpenBluetoothPort.class");
e.printStackTrace();
return null;
}
}
return null;
}
#Override
protected void onPostExecute(BluetoothSocket result) {
super.onPostExecute(result);
if(result != null && result.isConnected()) {
mCallback.OnBluetoothConnectionSuccess(result);
} else {
mCallback.OnBluetoothConnectionFailed();
}
}
}
public class ConnectThread extends Thread
{
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
private final OutputStream mmOutStream;
private UUID uuid = UUID.randomUUID();
private byte[] temp;
public ConnectThread(BluetoothDevice device,byte[] temp)
{
BluetoothSocket socket = null;
OutputStream tmpOut = null;
mmDevice = device;
this.temp = temp;
try
{
Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
socket = (BluetoothSocket) m.invoke(device, 1);
tmpOut = socket.getOutputStream();
}
catch (Exception e) { }
mmSocket = socket;
mmOutStream = tmpOut;
}
public void run()
{ enter code here
try
{
mmSocket.connect();
write(temp);
}
catch (IOException connectException)
{
try
{
mmSocket.close();
}
catch (IOException closeException)
{ }
return;
}
}
public void write(byte[] bytes)
{
try
{
mmOutStream.write(bytes);
mmOutStream.flush();
mmOutStream.close();
}
catch (IOException e) { }
}
public void cancel()
{
try
{
mmSocket.close();
}
catch (IOException e) { }
}
}
I am trying to transfer a txt file to another device. I am passing the bluetooth device and message(in bytes) to this class and starting the thread form main activity. After scanning, the devices displaying and pairing is also working. I am not getting any exception in the code. But I am not receiving a file.
Why I am not receiving a file on other mobile?
Can somebody help me please.
Thanks, Faraz
I'm trying to send data from an android device to a remote bluetooth device supporting Serial Port Profile(SPP). I notice whenever I open and close a socket after each press of a button, it is too slow. What socket commands should be executed in the Run() and Onclick() functions? The following is a class which does Bluetooth IO:
public class Selecteddevice extends Activity implements OnClickListener {
private static final String TAG = "THINBTCLIENT";
private BluetoothAdapter mBluetoothAdapter = null;
private BluetoothDevice device;
private BluetoothSocket btSocket = null;
private OutputStream outStream = null;
private static final UUID MY_UUID =
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
public static String address;
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
this.setContentView(R.layout.selecteddevice);
findViewById(R.id.toggleButton1).setOnClickListener(this);
findViewById(R.id.toggleButton2).setOnClickListener(this);
findViewById(R.id.toggleButton3).setOnClickListener(this);
}
#Override
public void onStart() {
super.onStart();
String address = getIntent().getStringExtra("address");
TextView tv1 = (TextView) findViewById(R.id.textView_address);
tv1.setText(" DEVICE ADDRESS: " + address);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
device = mBluetoothAdapter.getRemoteDevice(address);
run();
}
public void run(){
mBluetoothAdapter.cancelDiscovery();
try {
btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e)
{
Log.e(TAG, "ON START: Socket creation failed.", e);
}
try {
btSocket.connect();
} catch (IOException e)
{
Log.e(TAG, "sendTestByte: Socket connection failed.", e);
}
}
public void sendTestString(String s){
try {
outStream = btSocket.getOutputStream();
} catch (IOException e)
{
Log.e(TAG, "sendTestByte: OutputStream creation failed.", e);
}
try {
outStream.write(s.getBytes());
Log.d(TAG, "sendTestByte: OutputStream write succeeded.");
} catch (IOException e)
{
Log.e(TAG, "sendTestByte: OutputStream writefailed.", e);
}
}
public void onClick(View v){
switch(v.getId())
{
case R.id.toggleButton1:
this.sendTestString("1");
break;
case R.id.toggleButton2:
this.sendTestString("2");
break;
case R.id.toggleButton3:
this.sendTestString("3");
break;
}
}
#Override
public void onPause() {
super.onPause();
if (outStream != null) {
try {
outStream.flush();
} catch (IOException e5)
{
Log.e(TAG, "ON PAUSE: Couldn't flush output stream.", e5);
}
}
try {
btSocket.close();
} catch (IOException e6)
{
Log.e(TAG, "ON PAUSE: Unable to close socket.", e6);
}
}
#Override
public void onStop() {
super.onStop();
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
My program crashes after pairing with the error message:
07-27 13:00:57.483: E/THINBTCLIENT(7855): sendTestByte: OutputStream writefailed.
07-27 13:00:57.483: E/THINBTCLIENT(7855): java.io.IOException: socket closed
07-27 13:00:57.483: E/THINBTCLIENT(7855): at
android.bluetooth.BluetoothSocket.write(BluetoothSocket.java:331)
...
What am I doing wrong?
Thanks.
If you are sure the connection is established without any error and you can get the socket, try assigning your OutputStream member in run() method as follows:
public void run()
{
mBluetoothAdapter.cancelDiscovery();
try
{
btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e)
{
Log.e(TAG, "ON START: Socket creation failed.", e);
}
try
{
btSocket.connect();
} catch (IOException e)
{
Log.e(TAG, "sendTestByte: Socket connection failed.", e);
}
try
{
outStream = btSocket.getOutputStream();
} catch (IOException e)
{
Log.e(TAG, "sendTestByte: OutputStream creation failed.", e);
}
}
public void sendTestString(String s)
{
try
{
outStream.write(s.getBytes());
outSttream.flush(); // <-- Try flush to force sending data in buffer
Log.d(TAG, "sendTestByte: OutputStream write succeeded.");
} catch (IOException e)
{
Log.e(TAG, "sendTestByte: OutputStream writefailed.", e);
}
}
You are not actually closing socket but this should work. Make sure connection with master device is not lost before write() call
I'm pretty new to writing Android apps, and I wanted to write a piece of code that broadcasts the sensor data at a regular interval, say 1 second. Searching open-source codes I managed to write a sender class as below:
public class Sender extends Thread {
private static final String TAG = "Sending";
private static final int PORT = 12346;
private static final int TIMEOUT_MS = 500;
private static final int BUF_SIZE = 1024;
private WifiManager mWifi;
Sender(WifiManager wifi) {
mWifi = wifi;
}
public void run() {
try {
DatagramSocket socket = new DatagramSocket(PORT);
socket.setBroadcast(true);
socket.setSoTimeout(TIMEOUT_MS);
sendData(socket);
socket.close();
Thread.sleep(1000);
}
catch (IOException ioe) {
Log.e(TAG, "Couldn't send data", ioe);
}
catch (InterruptedException ie) {
Log.e(TAG, "Can't sleep", ie);
}
}
private void sendData(DatagramSocket socket) throws IOException {
byte[] buf = new byte[BUF_SIZE];
buf = object.toString().getBytes();
InetAddress addr = InetAddress.getByName("192.168.0.255"); // TO FIX
DatagramPacket packet = new DatagramPacket(buf, buf.length, addr, PORT);
socket.send(packet);
}
public void main(String[] args) {
new Sender(null).start();
while (true) {
}
}
}
And here's how I start it from within the onCreate method:
public void onCreate(Bundle savedInstanceState) {
...
new Sender((WifiManager) getSystemService(Context.WIFI_SERVICE)).start();
...
}
Now, if I open Wireshark on my laptop, I only see one packet sent at the time the app is started instead of every one second.
Could someone please point out where I did wrong? Honestly I'm not that familiar with threads and stuff, so I may just be missing something obvious here...
EDIT
OK, so the run method must be looped. See corrected code in the answer below.
Here's the corrected run method code:
public void run() {
while (true) {
try {
DatagramSocket socket = new DatagramSocket(PORT);
socket.setBroadcast(true);
socket.setSoTimeout(TIMEOUT_MS);
sendData(socket);
socket.close();
Thread.sleep(1000);
}
catch (IOException ioe) {
Log.e(TAG, "Couldn't send data", ioe);
}
catch (InterruptedException ie) {
Log.e(TAG, "Can't sleep", ie);
}
}
}