Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to read from the InputStream of a bluetooth on Android

I am trying to test this bluetooth communication example between a PC and an Android phone. My SPP client is exactly the one from there and it works fine. I am new to Android and I didn't want to make it run in a separate thread because I don't know how, so I just did everything in the onCreate() method. If this is not the best way, feel free to point me to a better way, but this is not my main problem.

The problem is I wanted to display the text received via bluetooth on a textView and I don't know how to read from InputStream. When the code is left like that, it displays something like java.io.DataInputStream@41b0cb68 I tried it like here it didn't display anything, also I don't know what encoding is being used.

here's my android app's code:

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

import android.app.Activity;
import android.bluetooth.*;
import android.util.Log;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class MainActivity extends Activity {

//based on java.util.UUID
private static UUID MY_UUID = UUID.fromString("446118f0-8b1e-11e2-9e96-0800200c9a66");

// The local server socket
private BluetoothServerSocket mmServerSocket;

// based on android.bluetooth.BluetoothAdapter
private BluetoothAdapter mAdapter;
private BluetoothDevice remoteDevice;
TextView text;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    text = (TextView) findViewById(R.id.textView_Text);

    BluetoothSocket socket = null;
    mAdapter = BluetoothAdapter.getDefaultAdapter();        

    // Listen to the server socket if we're not connected
   // while (true) {

        try {
            // Create a new listening server socket
            Log.d((String) this.getTitle(), ".....Initializing RFCOMM SERVER....");

            // MY_UUID is the UUID you want to use for communication
            mmServerSocket = mAdapter.listenUsingRfcommWithServiceRecord("MyService",    MY_UUID);
            //mmServerSocket =  mAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME, MY_UUID); // you can also try  using In Secure connection...

            // This is a blocking call and will only return on a
            // successful connection or an exception
            socket = mmServerSocket.accept();

        } catch (Exception e) {

        }

        try {
            Log.d((String) this.getTitle(), "Closing Server Socket.....");
            mmServerSocket.close();

            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            // Get the BluetoothSocket input and output streams

            tmpIn = socket.getInputStream();
            tmpOut = socket.getOutputStream();

            DataInputStream mmInStream = new DataInputStream(tmpIn);
            DataOutputStream mmOutStream = new DataOutputStream(tmpOut);

            // here you can use the Input Stream to take the string from the client  whoever is connecting
            //similarly use the output stream to send the data to the client


            text.setText(mmInStream.toString());
        } catch (Exception e) {
            //catch your exception here
        }
   // }
}
}

I commented out the while(true) loop because I think it was making my app crash when onPause() was being called. I know this is not the best implementation but I really want to read from the bluetooth I feel like I am very close :), other aspects will be dealt with afterwards (like working with threads and so on).

like image 595
ChrisX Avatar asked Jan 10 '23 23:01

ChrisX


2 Answers

I finally managed to correctly display in a TextView the string sent from the PC ("Test String from SPP Client\r\n").

I used this question, namely this piece of code, just below DataOutputStream mmOutStream = new DataOutputStream(tmpOut);:

// Read from the InputStream
            bytes = mmInStream.read(buffer);
            String readMessage = new String(buffer, 0, bytes);
            // Send the obtained bytes to the UI Activity

This is a very rudimentary example, designed only to show how to display strings received via bluetooth on the screen of the device. It is not done in a separate thread, and after it receives the string you have to close the app and restart it again, but the main purpose of the app was achieved (as I stated when I asked this question). What I really, really wanted was to receive a string from PC and display it on screen.

Here's my complete MainActivity, if somebody wants me to post a more complete approach (like using a separate thread) I will post it here once I complete it.

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

import android.app.Activity;
import android.bluetooth.*;
import android.util.Log;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class MainActivity extends Activity {

//based on java.util.UUID
private static UUID MY_UUID = UUID.fromString("446118f0-8b1e-11e2-9e96-0800200c9a66");

// The local server socket
private BluetoothServerSocket mmServerSocket;

// based on android.bluetooth.BluetoothAdapter
private BluetoothAdapter mAdapter;
private BluetoothDevice remoteDevice;
TextView text;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    text = (TextView) findViewById(R.id.textView_Text);

    BluetoothSocket socket = null;
    mAdapter = BluetoothAdapter.getDefaultAdapter();        

    // Listen to the server socket if we're not connected
   // while (true) {

        try {
            // Create a new listening server socket
            Log.d((String) this.getTitle(), ".....Initializing RFCOMM SERVER....");

            // MY_UUID is the UUID you want to use for communication
            mmServerSocket = mAdapter.listenUsingRfcommWithServiceRecord("MyService",    MY_UUID);
            //mmServerSocket =  mAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME, MY_UUID); // you can also try  using In Secure connection...

            // This is a blocking call and will only return on a
            // successful connection or an exception
            socket = mmServerSocket.accept();

        } catch (Exception e) {

        }

        byte[] buffer = new byte[256];  // buffer store for the stream
        int bytes; // bytes returned from read()
        try {
            Log.d((String) this.getTitle(), "Closing Server Socket.....");
            mmServerSocket.close();

            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            // Get the BluetoothSocket input and output streams

            tmpIn = socket.getInputStream();
            tmpOut = socket.getOutputStream();

            DataInputStream mmInStream = new DataInputStream(tmpIn);
            DataOutputStream mmOutStream = new DataOutputStream(tmpOut);            
            // here you can use the Input Stream to take the string from the client  whoever is connecting
            //similarly use the output stream to send the data to the client

         // Read from the InputStream
            bytes = mmInStream.read(buffer);
            String readMessage = new String(buffer, 0, bytes);
            // Send the obtained bytes to the UI Activity


            text.setText(readMessage);
        } catch (Exception e) {
            //catch your exception here
        }
   // }
}
}

Any questions? :)

like image 106
ChrisX Avatar answered Jan 18 '23 23:01

ChrisX


Basically, you'll need to match the way data is sent from one device to the way data is received by the other one.

SPP is stream based and transfers bytes of data. So, whatever bytes the sending device transmits must be interpreted correctly by the receiver.

An InputStream gives you access to the raw bytes transmitted, and you'll have to do something with them; i.e. decode them in some way as needed. For instance, if the sender uses an ObjectOutputStream to do the encoding prior to transmission, the receiver will have to use an ObjectInputStream to decode the input.

You may want to read up on InputStream (read()), ObjectInputStream, and toString().

Besides, reading from a blocking stream should almost always be done in a separate thread; and especially so when reading from some remote device/host/network/... with possible unknown delays or transmission speed.

like image 43
JimmyB Avatar answered Jan 18 '23 22:01

JimmyB