Android getting data from UIThread

I am trying to send android data to arduino using Bluetooth

.my gui contains readings SeekBar

and accelerometer. Everything is Sockets

formed successfully and everything works fine if I write data in OutputStream

the Socket

from method onSeekBarChanged()

so that the data is passed to arduino whenever I change the SeekBar.

 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        if(seekBar.getId() == R.id.seekBar)
        {
            speed.setText(String.valueOf(progress));
            String outputData = String.valueOf(progress)+",";
            try
            {
            streams.write(outputData.getBytes());//writes data to OutputStream of Socket
            }catch (Exception e){
                Log.d("RTR","Sockets not yet formed");
            }

        }
    }

      

The problem is I need to send data Accelerometer

continuously along with the current value SeekBar

. So I tried to write to the OutputStream

method Socket

from the onSensorChanged(SensorEvent event)

accelerometer.Result:Program not responding.

public void onSensorChanged(SensorEvent event) {

        if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
        {
            float accXYZ[] = event.values;

            float accX = accXYZ[0];
            float accY = accXYZ[1];
            float accZ = accXYZ[2];

            x.setText(String.format("%.2f",accX));
            y.setText(String.format("%.2f",accY));
            z.setText(String.format("%.2f",accZ));

            String outputData = x.getText().toString()+","+speed.getText().toString()+";";

            try{
                  streams.write(outputData.getBytes());
            }catch (Exception e){
                //Log.d("RTR","X");
            }

        }
    }

      

I understand that this is too much of an overload for UI Thread

. I think I should create new Thread

with an infinite loop in the method run()

to transfer data continuously. How can I send accelerometer and SeekBar data to this new thread continuously.

Or I need to collect UIThread accelerometer and SeekBar data from this new thread.

In Short, how do I get data from UIThread to this new Thread.

      

Please provide all possible solutions that you are aware of for my problem and any complications with my current procedure.

+3


source to share


1 answer


A good way to do this is to use a built-in class Looper

. Looper is a message queuing system that supports the Android UI thread, and you can use it with your own threads as well. What's nice about the way it was built is that it creates very little garbage collection overhead (depending on what types of arguments you use, it might not be one).

I write this for free, so you have to hack it a bit for it to work, but here's what it might look like:

class LooperThread extends Thread {
    private static final int MSG_TYPE_OUTPUT_DATA = 0;
    private Handler mHandler;
    private volatile OutputStream mOutputStream;

    public void run() {
        Looper.prepare();

        mHandler = new Handler() {
            public void handleMessage(Message msg) {
                if (msg.what == MSG_TYPE_OUTPUT_DATA
                    && mOutputStream != null) {
                    //try-catch left out for brevity
                    mOutputStream.write(msg.obj.getBytes());
                }
            }
        };

        Looper.loop();
    }

    public void submitReading(String outputData) {
        mHandler.sendMessage(mHandler.obtainMessage(MSG_TYPE_OUTPUT_DATA, outputData);
    }
}

      

Your setup code will do something like this:

private void setup() {
    Socket sock = setupBluetoothConnection();
    this.looperThread = new LooperThread();
    this.looperThread.setOutputStream(sock.getOutputStream());
    this.looperThread.start();
}

      



Finally, your sensor's event handler:

public void onSensorChanged(SensorEvent event) {

    if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
    {
        // snip...
        String outputData = x.getText().toString()+","+speed.getText().toString()+";";

        this.looperThread.submitReading(outputData);
    }
}

      

This gives you one background thread that processes messages as fast as possible, and that you can send messages in a thread-safe manner from any other thread. They are processed in order.

You will need to take care to properly terminate the looper stream when done, and make sure it can lose the socket connection.

If you need to slow it down at a certain rate of messages per second, things get a little more complicated. OutputStream.write is a blocking operation, so I left that for convenience. What would you do, register System.nanoTime()

where you last processed the message in the instance field and inside the handleMessage () method, whenever the next message arrives before enough time has passed, you will calculate how long you need to wait before you will be able to process the message. This is much easier than handling it on the "send" side using sendMessageDelayed ().

+5


source







All Articles