0

My android app Main Activity is using a Thread because a very "heavy" algorithm is being used and without threading it just stacks my UI and app. That's my Thread:

@Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
            mGravity = event.values;
        if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
            mGeomagnetic = event.values;
        if (mGravity != null && mGeomagnetic != null) {
            float R[] = new float[9];
            float I[] = new float[9];
            boolean success = SensorManager.getRotationMatrix(R, I, mGravity,
                    mGeomagnetic);
            if (success) {

                float orientation[] = new float[3];
                SensorManager.getOrientation(R, orientation);
                azimuth_angle = (float) (orientation[0]*180/Math.PI); 
                pitch_angle = (float) (orientation[1]*180/Math.PI);
                roll_angle = (float) (orientation[2]*180/Math.PI);
        p.setText(String.valueOf(pitch_angle));
                 r.setText(String.valueOf(roll_angle));
                 y.setText(String.valueOf(azimuth_angle));


                 new Thread(new Runnable() {

                     public void run()
                       {


                          try 
                           {

                            Locations = Algo( pitch_angle, roll_angle,
                                        azimuth_angle);
                            Thread.sleep(500);
                           } 
                           catch (Exception e) 
                           {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }

                         }

                        }).start();
        }

Problem: Algo time is about 150-300 milliSeconds. I think this thread is activated again before Algo is finished. because the Thread is executed each time onSensorChanged running. What can I do to make Algo return it's values to "Locations" as expected?

P.S Algo is tested on a Service and works properly.

Digol
  • 390
  • 1
  • 15

2 Answers2

1

First of all, your Locations should be written from small letter, because it is a varibale. Second, if some variable is used by multiple threads it must be declared as volatile.

You could add a volatile boolean in which you store your thread state, for example true is running, flase is not. You need to set this variable to true just before you run your thread, and set it to false into finally statement in your thread. When the value of this variable is true (meaning that previous thread is running) you just return from this method, ignorig the event.

private volatile boolean heavyAlgRunning = false;

@Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
            mGravity = event.values;
        if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
            mGeomagnetic = event.values;
        if (mGravity != null && mGeomagnetic != null) {

            float R[] = new float[9];
            float I[] = new float[9];
            boolean success = SensorManager.getRotationMatrix(R, I, mGravity,
                    mGeomagnetic);
            if (success) {

                float orientation[] = new float[3];
                SensorManager.getOrientation(R, orientation);
                azimuth_angle = (float) (orientation[0]*180/Math.PI); 
                pitch_angle = (float) (orientation[1]*180/Math.PI);
                roll_angle = (float) (orientation[2]*180/Math.PI);
        p.setText(String.valueOf(pitch_angle));
                 r.setText(String.valueOf(roll_angle));
                 y.setText(String.valueOf(azimuth_angle));
                 if (heavyAlgRunning) return;
                 heavyAlgRunning = true;

                 new Thread(new Runnable() {

                     public void run()
                       {


                          try 
                           {

                            Locations = Algo( pitch_angle, roll_angle,
                                        azimuth_angle);
                            Thread.sleep(500);
                           } 
                           catch (Throwable e) 
                           {
                                // TODO Auto-generated catch block
                                Log.e("t","t",e);
                                //e.printStackTrace();
                            }
         //                    finally {
         //                        heavyAlgRunning =false;
          //                  }

                              heavyAlgRunning =false;

                         }

                        }).start();
        }
Krzysztof Cichocki
  • 6,294
  • 1
  • 16
  • 32
  • First of all thanks for telling me that View variables need to be with non capital letter. second, I used synchronized as Anil said, that soled my problem. I tried to add you heavyAlgRunning and it make my orientation one sampled and do not calculates the algorithm at all. Do you know why? – Digol May 28 '15 at 09:50
  • Just debug it and seems like finally do not change heavyAlgRinning. – Digol May 28 '15 at 09:53
  • Try this changed version, and post any exceptions that you will have in logCat – Krzysztof Cichocki May 28 '15 at 09:57
  • How come it's still not working? i even tried to place it at the end of Algo and many places, and then tried your last change and it's still the same. – Digol May 28 '15 at 10:01
  • try it now, it was to soon set the true of running the algorithm :) – Krzysztof Cichocki May 28 '15 at 10:03
  • Now the orientation display is very good and fast but the algorithm is calculated only once, heavyAlgoRunning is never changed – Digol May 28 '15 at 11:14
  • I took heavyAlgoRunning out of the thread and it looked like calculating some location points but stopped after 10 points calculated, it suppose to do it all the time – Digol May 28 '15 at 11:18
  • Probably your Algo method is never returning... (btw. the method name should also start from small letter) – Krzysztof Cichocki May 28 '15 at 12:32
1

You need to lock your thread until it finishes equations. So you can try to add synchronized section in try statement or use one of thread system locks: https://stackoverflow.com/a/24582076/3345366

Community
  • 1
  • 1
anil
  • 2,083
  • 21
  • 37
  • Anil thank you for this great solution. It's working. i can get the values calculated and display them. my mistake was also using an Object to activate my algorithm inter methods, so i removed them. now the hole thing is working but super slow. do you have any idea ho to make it faster? maybe make some more Threads for .setText lines? – Digol May 28 '15 at 09:36
  • I removed that before, as synchronized worked for me. – Digol May 28 '15 at 09:53
  • try to put the code above `new Thread...` in `run` method. As much as possible. – anil May 28 '15 at 10:06