How to get an InputStream via bluetooth and put in a Textview?

11,218

As an alternative to using the handler, just get the information in the run of the thread..

I have done it this way and it works for me.

public void run() {
            byte[] buffer = new byte[128];  // buffer store for the stream
            int bytes; // bytes returned from read()

            // Keep listening to the InputStream until an exception occurs
            while (true) {
                try {


                    bytes = mmInStream.read(buffer);
                    byte[] readBuf = (byte[]) buffer;
                    String strIncom = new String(readBuf, 0, bytes);                 // create string from bytes array
                    sb.append(strIncom);                                                // append string
                    int endOfLineIndex = sb.indexOf("\r\n");                            // determine the end-of-line
                    if (endOfLineIndex > 0) {  
                        // add the current string to eol to a local string
                        String sbprint = sb.substring(0, endOfLineIndex);

                        // get the start and end indexes of the heading
                        int startHeading = sb.indexOf("HE");
                        int endHeading = sb.indexOf("/HE");

                        // set the heading
                        Henry.this.setCurrentHeading(sb.substring((startHeading + 2), endHeading));

                        // get the start and end indexes of the front range
                        int startFrontRange = sb.indexOf("FR");
                        int endFrontRange = sb.indexOf("/FR");

                        // get the front range
                        Henry.this.currentFrontRange = sb.substring((startFrontRange + 2), endFrontRange);
             ... ( grab all the information you need here ) ...

                        // debugging output what we have
                        // System.out.println("recv: " + sbprint);

                        // clean out the sb to ready next run
                        sb.delete(0, sb.length());   
                    }

I save all the information retrieved from the serial connection in my Application (Henry), then any Activity that wants to use the info gets it from the application. If the view needs to have a updated perspective on the information, I add a timer to the view to kick of a refresh method as often as I like. This has the added advantage of being able to use the information from anywhere in your android application.

I send about 10 data points from the arduino to the device and about 3 data points from the device to the arduino this way. I added my own markup around the datapoints to identify them.

Hope this helps!

Share:
11,218

Related videos on Youtube

user2149122
Author by

user2149122

Updated on September 15, 2022

Comments

  • user2149122
    user2149122 over 1 year

    This is my first question in SO. I am new (and excited) in Android programming and here is my PROBLEM: I am building a project using my android phone and a microcontroller. The microcontroller has a distance sensor and transmits its value. I have managed to get connected to the microcontroller and send correct signals, but I can't get the distance mesurment, or anything else. The application doesn't crash or anything it just won't get the data from the microcontroller (my computer gets the data from microcontroler (data is a string)). My code from the android app is this:

    public class Accelerometer extends Activity {

    // Intent request codes
    private static final int REQUEST_CONNECT_DEVICE = 1;
    private static final int REQUEST_ENABLE_BT = 2;
    private static final int RECIEVE_MESSAGE = 3;
    
    // Program variables
    private byte microcOut;
    private boolean ledStat;
    private boolean connectStat = false;
    private Button btnled;
    private Button connect_button;
    private TextView yAccel, xAccel, incoming;
    protected static final int MOVE_TIME = 80;
    private long lastWrite = 0;
    OnClickListener myClickListener;
    ProgressDialog myProgressDialog;
    private Toast failToast;
    private Handler mHandler,h;
    private StringBuilder sb = new StringBuilder();
    
    // Sensor object used to handle accelerometer
    private SensorManager mySensorManager; 
    private List<Sensor> sensors; 
    private Sensor accSensor;
    
    // Bluetooth Stuff
    private BluetoothAdapter btAdapter = null;
    private BluetoothSocket btSocket = null; 
    private OutputStream outStream = null;
    private InputStream inStream = null;
    private ConnectThread mConnectThread = null;
    private ConnectedThread mConnectedThread;
    
    private String deviceAddress = null;
    // Well known SPP UUID (will *probably* map to RFCOMM channel 1 (default) if not in use); 
    private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    
    //Sound Clip to make app prettier
    MediaPlayer myclip;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setContentView(R.layout.activity_accelerometer);
        myclip = MediaPlayer.create(this, R.raw.cartcar);
        myclip.start();
         // Finds buttons in .xml layout file
        btnled = (Button) findViewById(R.id.led_button1);
        connect_button = (Button) findViewById(R.id.connect_button1);
        yAccel = (TextView) findViewById(R.id.accText1);
        xAccel = (TextView) findViewById(R.id.accText2);
        incoming = (TextView) findViewById(R.id.incoming);
        // Set Sensor
        mySensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); 
        sensors = mySensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
        if(sensors.size() > 0) accSensor = sensors.get(0);
    
        myProgressDialog = new ProgressDialog(this);
        failToast = Toast.makeText(this, R.string.failedToConnect, Toast.LENGTH_SHORT);
        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
             if (myProgressDialog.isShowing()) {
                    myProgressDialog.dismiss();
                }
    
             // Check if bluetooth connection was made to selected device
                if (msg.what == 1) {
                    // Set button to display current status
                    connectStat = true;
                    connect_button.setText(R.string.connected);
    
                    // Reset the BluCar
                    microcOut = 0;
                    ledStat = false;
                    write(microcOut);
                }else {
                    // Connection failed
                 failToast.show();
                }
            }
        };
    
    
        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
                        incoming.setText("Data from Arduino: " + sbprint);            // update TextView 
                    }
                    //Log.d(TAG, "...String:"+ sb.toString() +  "Byte:" + msg.arg1 + "...");
                    break;
                }
            };
        };
     // Check whether bluetooth adapter exists
        btAdapter = BluetoothAdapter.getDefaultAdapter(); 
        if (btAdapter == null) { 
             Toast.makeText(this, R.string.no_bt_device, Toast.LENGTH_LONG).show(); 
             finish(); 
             return; 
        } 
    
        // If BT is not on, request that it be enabled.
        if (!btAdapter.isEnabled()) {
            Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
        }
        /**********************************************************************
         * Buttons for controlling BluCar
         */
        connect_button.setOnClickListener(new View.OnClickListener() {
    
            // Connect to Bluetooth Module
            @Override
            public void onClick(View v) {
                if (connectStat) {
                    // Attempt to disconnect from the device
                    disconnect();
                }else{
                    // Attempt to connect to the device
                    connect();
                }
            }
        });
    
        // Toggle Headlights
        btnled.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (ledStat) {
                    microcOut = (byte) (microcOut & 124);
                    btnled.setText(R.string.ledbuttonON);
                    ledStat = false;
                }else{
                    microcOut = (byte) (microcOut | 128);
                    btnled.setText(R.string.ledbuttonOFF);
                    ledStat = true;
                }
                write(microcOut);
            }
        });
    
    }
    /** Thread used to connect to a specified Bluetooth Device */
    public class ConnectThread extends Thread {
    private String address;
    private boolean connectionStatus;
    
        ConnectThread(String MACaddress) {
            address = MACaddress;
            connectionStatus = true;
    }
    
        public void run() {
        // When this returns, it will 'know' about the server, 
           // via it's MAC address. 
            try {
                BluetoothDevice device = btAdapter.getRemoteDevice(address);
    
                // We need two things before we can successfully connect 
                // (authentication issues aside): a MAC address, which we 
                // already have, and an RFCOMM channel. 
                // Because RFCOMM channels (aka ports) are limited in 
                // number, Android doesn't allow you to use them directly; 
                // instead you request a RFCOMM mapping based on a service 
                // ID. In our case, we will use the well-known SPP Service 
                // ID. This ID is in UUID (GUID to you Microsofties) 
                // format. Given the UUID, Android will handle the 
                // mapping for you. Generally, this will return RFCOMM 1, 
                // but not always; it depends what other BlueTooth services 
                // are in use on your Android device. 
                try { 
                     btSocket = device.createRfcommSocketToServiceRecord(SPP_UUID); 
                } catch (IOException e) { 
                    connectionStatus = false;
                } 
            }catch (IllegalArgumentException e) {
                connectionStatus = false;
            }
    
           // Discovery may be going on, e.g., if you're running a 
           // 'scan for devices' search from your handset's Bluetooth 
           // settings, so we call cancelDiscovery(). It doesn't hurt 
           // to call it, but it might hurt not to... discovery is a 
           // heavyweight process; you don't want it in progress when 
           // a connection attempt is made. 
           btAdapter.cancelDiscovery(); 
    
           // Blocking connect, for a simple client nothing else can 
           // happen until a successful connection is made, so we 
           // don't care if it blocks. 
           try {
                btSocket.connect(); 
           } catch (IOException e1) {
                try {
                     btSocket.close(); 
                } catch (IOException e2) {
                }
           }
    
           // Create a data stream so we can talk to server. 
           try { 
            outStream = btSocket.getOutputStream(); 
           } catch (IOException e2) {
            connectionStatus = false;
           }
    
           // Send final result
           if (connectionStatus) {
            mHandler.sendEmptyMessage(1);
           }else {
            mHandler.sendEmptyMessage(0);
           }
        }
    }
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
         switch (requestCode) {
           case REQUEST_CONNECT_DEVICE:
             // When DeviceListActivity returns with a device to connect
               if (resultCode == Activity.RESULT_OK) {
                // Show please wait dialog
                myProgressDialog = ProgressDialog.show(this, getResources().getString(R.string.pleaseWait), getResources().getString(R.string.makingConnectionString), true);
    
                // Get the device MAC address
                deviceAddress = data.getExtras().getString(DeviceList.EXTRA_DEVICE_ADDRESS);
                // Connect to device with specified MAC address
                  mConnectThread = new ConnectThread(deviceAddress);
                  mConnectThread.start();
    
               }else {
                 // Failure retrieving MAC address
                 Toast.makeText(this, R.string.macFailed, Toast.LENGTH_SHORT).show();
               }
               break;
           case REQUEST_ENABLE_BT:
               // When the request to enable Bluetooth returns
               if (resultCode == Activity.RESULT_OK) {
                   // Bluetooth is now enabled
               } else {
                   // User did not enable Bluetooth or an error occured
                   Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();
                   finish();
               }
            }
       }
    
    public void write(byte data) {
         if (outStream != null) {
              try {
                 outStream.write(data);
              } catch (IOException e) {
              }
          }
      }
    
      public void emptyOutStream() {
         if (outStream != null) {
              try {
                 outStream.flush();
              } catch (IOException e) {
              }
          }
      }
    
      public void connect() {
         // Launch the DeviceListActivity to see devices and do scan
          Intent serverIntent = new Intent(this, DeviceList.class);
          startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
      }
    
      public void disconnect() {
         if (outStream != null) {
             try {
                    outStream.close();
                    connectStat = false;
                    connect_button.setText(R.string.disconnected);
                } catch (IOException e) {
                }
         } 
      }
      private final SensorEventListener mSensorListener = new SensorEventListener() {
    
            @Override
            public void onAccuracyChanged(Sensor sensor, int accuracy) {}
    
            @Override
            public void onSensorChanged(SensorEvent event) {
                // Checks whether to send steering command or not
                long date = System.currentTimeMillis();
                if (date - lastWrite > MOVE_TIME) {
                    yAccel.setText(" " + event.values[1]);
                    xAccel.setText(" " + event.values[0]);
                    if (event.values[1] > 2.5) {
                        // Turn right
                        microcOut = (byte) (microcOut & 248);
                        microcOut = (byte) (microcOut | 4);
                    }else if (event.values[1] < -2.5) {
                        // Turn left
                        microcOut = (byte) (microcOut & 244);
                        microcOut = (byte) (microcOut | 8);
                    }else {
                        // Center the steering servo
                        microcOut = (byte) (microcOut & 240);
                    }
                    write(microcOut);
                    lastWrite = date;
                }
            }
          };
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_accelerometer, menu);
        return true;
    }
    public void onResume() { 
         super.onResume();
         mySensorManager.registerListener(mSensorListener, accSensor, SensorManager.SENSOR_DELAY_GAME);
    }
    @Override 
    public void onDestroy() { 
         emptyOutStream();
         disconnect();
         if (mSensorListener != null) {
             mySensorManager.unregisterListener(mSensorListener);
         }
         super.onDestroy(); 
         myclip.release();
    } 
    private class ConnectedThread extends Thread {
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;
    
        public ConnectedThread(BluetoothSocket 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[256];  // 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);        // Get number of bytes and message in "buffer"
                    h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer).sendToTarget();     // Send to message queue Handler
                } catch (IOException e) {
                    break;
                }
            }
        }
    
        /* Call this from the main activity to send data to the remote device */
        public void write(String message) {
    
            byte[] msgBuffer = message.getBytes();
            try {
                mmOutStream.write(msgBuffer);
            } catch (IOException e) {
    
              }
        }
    }
    

    }

    I have read everything over the subject (BluetoothChat, projects of people on the internet ...) and I am very tired. Any help is much appreciated.

    --EDIT--

    I have managed to get the inputstream into my texteview. My problem now is that my application when it is trying to connect to my device (microcontroller or my pc) gets stuck in the progressdialog (it is connected to the device but the progressdialog will not go away)and waits for something to come in. After a while (like 5-6 secs) even if something comes in it remains stuck and I have to force it to close. I think the problem is in the way the handler handles the thread. In the debugger there is no problem all threads run ok.

    The changes in my code are: In my ConnectThread: `/** Thread used to connect to a specified Bluetooth Device */ public class ConnectThread extends Thread { private String address; private boolean connectionStatus;

        ConnectThread(String MACaddress) {
            address = MACaddress;
            connectionStatus = true;
    }
    
        public void run() {
        // When this returns, it will 'know' about the server, 
           // via it's MAC address. 
            try {
                BluetoothDevice device = btAdapter.getRemoteDevice(address);
    
                // We need two things before we can successfully connect 
                // (authentication issues aside): a MAC address, which we 
                // already have, and an RFCOMM channel. 
                // Because RFCOMM channels (aka ports) are limited in 
                // number, Android doesn't allow you to use them directly; 
                // instead you request a RFCOMM mapping based on a service 
                // ID. In our case, we will use the well-known SPP Service 
                // ID. This ID is in UUID (GUID to you Microsofties) 
                // format. Given the UUID, Android will handle the 
                // mapping for you. Generally, this will return RFCOMM 1, 
                // but not always; it depends what other BlueTooth services 
                // are in use on your Android device. 
                try { 
                     btSocket = device.createRfcommSocketToServiceRecord(SPP_UUID); 
                } catch (IOException e) { 
                    connectionStatus = false;
                } 
            }catch (IllegalArgumentException e) {
                connectionStatus = false;
            }
    
           // Discovery may be going on, e.g., if you're running a 
           // 'scan for devices' search from your handset's Bluetooth 
           // settings, so we call cancelDiscovery(). It doesn't hurt 
           // to call it, but it might hurt not to... discovery is a 
           // heavyweight process; you don't want it in progress when 
           // a connection attempt is made. 
           btAdapter.cancelDiscovery(); 
    
           // Blocking connect, for a simple client nothing else can 
           // happen until a successful connection is made, so we 
           // don't care if it blocks. 
           try {
                btSocket.connect(); 
           } catch (IOException e1) {
                try {
                     btSocket.close(); 
                } catch (IOException e2) {
                }
           }
    
           // Create a data stream so we can talk to server. 
           try { 
                outStream = btSocket.getOutputStream(); 
              } catch (IOException e2) {
                connectionStatus = false;
              }
           try{
            inStream = btSocket.getInputStream();
        }catch (IOException e2){
            connectionStatus = false;
        }
            int bytes; // bytes returned from read()
           // Keep listening to the InputStream until an exception occurs
           while (connectionStatus) {
               try {
                   byte[] b = new byte[64];  // buffer store for the stream
                   // Read from the InputStream
                   bytes = inStream.read(b);        // Get number of bytes and message in "buffer"
                   mHandler.obtainMessage(RECIEVE_MESSAGE, bytes, -1, b).sendToTarget();     // Send to message queue Handler
               } catch (IOException e) {
                   break;
               }
           }
           // Send final result
           if (connectionStatus) {
            mHandler.obtainMessage(1);
           }else {
            mHandler.sendEmptyMessage(0);
           }
        }
    }
    

    ` And in my mHandler in my onCreate method:

     mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
             if (myProgressDialog.isShowing()) {
                    myProgressDialog.dismiss();
                }
    
             // Check if bluetooth connection was made to selected device
                if (msg.what == 1) {
                    // Set button to display current status
                    connectStat = true;
                    connect_button.setText(R.string.connected);
                    // Reset the BluCar
                    microcOut = 0;
                    ledStat = false;
                    write(microcOut);
                }else if (msg.what == 2){
                    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(".");                            // 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
                        incoming.setText(sbprint);            // update TextView
                        connectStat = true;
                        connect_button.setText(R.string.connected);
                    }else{
                        incoming.setText("Problem!");
                    }
                }else {
                    // Connection failed
                 failToast.show();
                }
            }
        };
    

    Another thing I need is how to empty the buffer when it is full.

    PS: Thanks EVERYONE for his/her help I am really grateful.