Brandon75f
Brandon75f

Reputation: 3

Android doing to much on main thread: Tried separate threads

Im having an issue with choppy animations and the app eventually crashing. I have tried separating into threads yet i still get the message of doing to much in the main thread. I am making the assumption that my sensor update and the work load in the UI are directly proportional and if i can some how take the load off of the UI thread things will begin to smooth out with the animations and sensors. Is there a way to get the Sensor listener off the UI thread and still update the View in the UI?

import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.TextView;


public class MyActivity extends Activity implements SensorEventListener {



private SensorManager mSensorManager;
private Sensor sensorAccelerometer;
private Sensor sensorMagneticField;
public static ImageView right;
public static ImageView left;

double pitch = 0;
double roll = 0;
public static float currentX = 0f;
public static float currentY = 0f;
public static float degreeR = 0.f;
public static float degreeL = 0.f;

public static TextView rightText;
public static TextView leftText;

public static RotateAnimation rotationLeft;
public static RotateAnimation rotationRight;

private float[] valuesAccelerometer;
private float[] valuesMagneticField;

private float[] matrixR;
private float[] matrixI;
private float[] matrixValues;

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

    left = (ImageView)findViewById(R.id.leftView);
    right = (ImageView)findViewById(R.id.rightView);
    leftText = (TextView)findViewById(R.id.leftText);
    rightText = (TextView)findViewById(R.id.rightText);

    mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
    sensorAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    sensorMagneticField = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);

    valuesAccelerometer = new float[3];
    valuesMagneticField = new float[3];

    matrixR = new float[9];
    matrixI = new float[9];
    matrixValues = new float[3];



}





 @Override
 public void onSensorChanged(final SensorEvent event) {

    switch (event.sensor.getType()){
        case Sensor.TYPE_ACCELEROMETER:
            for (int i =0; i <3;i++){
                valuesAccelerometer[i] = event.values[i];
            }
            break;
        case Sensor.TYPE_MAGNETIC_FIELD:
            for (int i =0;i<3;i++){
                valuesMagneticField[i] = event.values[i];
            }
            break;
    }
    boolean success = SensorManager.getRotationMatrix(
            matrixR,
            matrixI,
            valuesAccelerometer,
            valuesMagneticField);
    if (success){
        SensorManager.getOrientation(matrixR,matrixValues);
        double azimuth = Math.toDegrees(matrixValues[0]);
        pitch = Math.toDegrees(matrixValues[1]);
        roll = Math.toDegrees(matrixValues[2]);
    }



    degreeL = Math.round(roll);
    degreeR = Math.round(pitch);

    Thread animateL = new animateLeft();
    Thread animateR = new animateRight();
    animateL.run();
    animateR.run();
        /*Button button = (Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                currentX = (-degreeR-degreeR);
                currentY = ((degreeL - 90)-degreeL);///working here
            }
        });*/



}



     import android.view.animation.Animation;
     import android.view.animation.LinearInterpolator;
    import android.view.animation.RotateAnimation;

    public class animateLeft extends Thread {

    @Override
    public  void run() {

       android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
       MyActivity.leftText.setText("" + MyActivity.degreeL);

        MyActivity.rotationRight = new RotateAnimation(
                MyActivity.currentX,
                MyActivity.degreeR,
                Animation.RELATIVE_TO_SELF, 0.5f,
                Animation.RELATIVE_TO_SELF, 0.5f);
        MyActivity.rotationLeft = new RotateAnimation(
                MyActivity.currentY,
                MyActivity.degreeL,
                Animation.RELATIVE_TO_SELF, 0.5f,
                Animation.RELATIVE_TO_SELF, 0.5f);
        MyActivity.rotationRight.setInterpolator(new LinearInterpolator());
        MyActivity.rotationRight.setFillAfter(true);
        MyActivity.rotationRight.setDuration(100);
        MyActivity.currentY = (MyActivity.degreeL+90);
        MyActivity.left.startAnimation(MyActivity.rotationLeft);


    }


    }
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;

public class animateRight extends Thread {
    @Override
    public void run() {
        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
      MyActivity.rightText.setText("" + MyActivity.degreeR);
       MyActivity.rotationLeft = new RotateAnimation(
                MyActivity.currentY,
                MyActivity.degreeL,
                Animation.RELATIVE_TO_SELF, 0.5f,
                Animation.RELATIVE_TO_SELF, 0.5f);
        MyActivity.rotationRight = new RotateAnimation(
                MyActivity.currentX,
                MyActivity.degreeR,
                Animation.RELATIVE_TO_SELF, 0.5f,
                Animation.RELATIVE_TO_SELF, 0.5f);

        MyActivity.rotationLeft.setDuration(100);
        MyActivity.rotationLeft.setFillAfter(true);
        MyActivity.currentX = (-MyActivity.degreeR);
        MyActivity.rotationLeft.setInterpolator(new LinearInterpolator());
        MyActivity.right.startAnimation(MyActivity.rotationRight);


    }

}

Upvotes: 0

Views: 166

Answers (2)

Tore Rudberg
Tore Rudberg

Reputation: 1624

A little late, but if others still want to know, here is a good way to achieve this. As always when multithreading, make sure you know what you are doing and take the time to so it right, to avoid those weird errors. Have fun!

Class members:

private HandlerThread mSensorThread;
private Handler mSensorHandler;

in OnCreate:

mSensorThread = new HandlerThread("Sensor thread", Thread.MAX_PRIORITY);
mSensorThread.start();
mSensorHandler = new Handler(mSensorThread.getLooper()) //Blocks until looper is prepared, which is fairly quick
yourSensorManager.registerListener(yourListener, yourSensor, interval, mSensorHandler);

When unregistering, also do:

mSensorThread.quitSafely();

Upvotes: 0

Kakarot
Kakarot

Reputation: 4252

You should use AsyncTask for such purposes. It allows you to perform tasks in a background by encapsulating it in doInBackground(Params...) method and once you are done, you can post UI events using onPostExecute(Result) of the AsyncTask class.

You can read more about it at the following link Async Task

Upvotes: 1

Related Questions