Question

I'd like to display a red button if I get a certain input from arduino device which is connected via bluetooth. My code looks like:

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

    if (savedInstanceState == null) {
        getSupportFragmentManager().beginTransaction()
                .add(R.id.container, new PlaceholderFragment())
                .commit();
    }

    blueconnect(); //creates my bluetooth connection

    if (waitarrival() == 1)
        Global.fullpaper = 1;


    if (Global.fullpaper == 1) {
        View paperbutton = findViewById(R.id.buttonPaper);
        paperbutton.getBackground().setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY);}


}

and

public int waitarrival()
{
    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 = Global.mmInStream.read(buffer);
            if (bytes ==  30) //send 30 when trashcan finishes the movement sequence
                return 1;
        } catch (IOException e) {
            break;
        }
    }

    return 0;
}   

and my arduino code simply:

void setup() {
Serial.begin (9600);
}
void loop() 
{
  Serial.write(30);
}

When I first start my code, it just shows a white screen. If I wait long enough (like 10 seconds) red button is actually displayed. However this is too much waiting time... How can I fix this? Any help will be really appreciated at this point. Thank you in advance.

Edit: =======================================================================

I created the AsyncTask Class:

private class switchcolors extends AsyncTask<Void, Void, Integer>
{
    protected Integer doInBackground(Void...params) 
    {
        byte[] buffer = new byte[1024];  // buffer store for the stream
        int bytes; // bytes returned from read()
        long targetTime = System.currentTimeMillis() + 50000; //wait for 50s


        while( System.currentTimeMillis() < targetTime ) 
        {
            try 
            {
                bytes = Global.mmInStream.read(buffer);
                if (bytes > 0)
                {
                    if (buffer[0] == 30) //send 30 from arduino ( Serial.write(30) )
                        return 1;
                }
            } 
            catch (IOException e) {}
        }

        return 0;
    }


    protected void onPostExecute(Integer result) 
    {
        if (result == 1)
        {
            View paperbutton = findViewById(R.id.buttonPaper);
            paperbutton.getBackground().setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY);           
        }
    }
}

and use this class in onCreate() method:

new switchcolors().execute();

The page is correctly displayed but red button is not showed... Can I get some help?

Edit 2 ================================================ Never mind. The above works! It was my Bluetooth device that had a connection problem

Was it helpful?

Solution

The problem here is that waitarrival() is blocking your ui thread, specifically the call to read().

What you'd want to do instead is:

public int waitarrival() {
    while( Global.mmInStream.available() > 1 ) { // at least one byte available
        byte data = Global.mmInStream.read(); // read just one byte, that's all we need
        if( data == 30 ) {
            return 1; // if we received the '30' we were looking for, then we're good to go.
        }
    }
    return 0; // this is returned in all other cases -- i.e. no byte available, or no 30s.
}  

Once that's done, you'd probably want check this periodically to see if there was a reaction from the bluetooth device. You could look at the Android Bluetooth Chat sample to see how to properly put the entire thing on a background thread -- that's the preferred pattern for this.

If you're really want to wait for this, and handle your own timeout, you could wrap this entire method into an AsyncTask, with something like this --

protected Integer doInBackGround( Integer[] timeout ) {
    long targetTime = System.CurrentTimeMillis() + timeout[0] * 1000; // time out in seconds...

    while( System.CurrentTimeMillis() < targetTime ) {
       if( waitforarrival() == 1 )
           return 1;
       Thread.sleep(100); // sleep 1/10th of a second
    }

    return 0;
}

Your onPostExecute() would then update the UI based on the result.

And then you'd invoke it from onCreate() like so:

myTask.execute( 60 ); // wait for arrival for a minute.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top