0

My problem is hard to explain but i am going to try. I am making a project with inhouse navigation software (Wificompass - https://code.google.com/p/wificompass/ ) and google glass. i am using the orientation of the google glass and the Wificompass software is running on phone) Data is sent true wifi from the glass(server) to the phone (client). this part is working and tested already. The problem is when i integrate my client code into the wificompass framework. i will post the situation before and after i edited the source code. Basically my problem is a blocking ui thread if i use my GlassOrientationSocket, i can still press buttons on the ui screen and the code behind these buttons still runs, but the painting of objects (compass and user) gets blocked and i have no idea how this can happen. Does anybody know how this behavior can be explained ?

Extra info: After hours of debugging i found that the paint loop for multiple drawables doesnt loop. In the original source code the loop works fine and keeps drawing (constantly calling draw on drawables), in my code this loop only works 1 time (then dispatchdraw is called on drawables), and when i pause activity the loop is triggered but only once. The only thing i changed in the originial code is the serversocket (that runs on thread). Anybody have any idea?, any advice is welcome.

BEFORE

public class CompassSensorWatcher implements SensorEventListener {

protected SensorManager sensorManager;

protected Sensor compass;

protected Sensor accelerometer;

protected Context context;

float[] inR = new float[16];

float[] I = new float[16];

float[] gravity = new float[3];

float[] geomag = new float[3];

float[] orientVals = new float[3];

float azimuth = 0;

float angle = 0;

int minX = 0, minY = 0, maxX = 0, maxY = 0, centerX = 0, centerY = 0, width = 0, height = 0;

float l = 0.3f;

protected CompassListener listener;

protected float lastAzimuth = 0f;



public CompassSensorWatcher(Context context,CompassListener cl,float lowpassFilter) {
    this.context = context;
    this.listener=cl;
    this.l=lowpassFilter;

    sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
    compass = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
    accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

    try {
        sensorManager.registerListener(this, compass, SensorManager.SENSOR_DELAY_UI);
        sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_UI);
    } catch (Exception e) {
        Logger.e("could not register listener", e);
    }
}

/*
 * (non-Javadoc)
 * 
 * @see android.hardware.SensorEventListener#onAccuracyChanged(android.hardware.Sensor, int)
 */
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}

/*
 * (non-Javadoc)
 * 
 * @see android.hardware.SensorEventListener#onSensorChanged(android.hardware.SensorEvent)
 */
@Override
public void onSensorChanged(SensorEvent event) {

    // Logger.d("sensor changed "+event);
    // we use TYPE_MAGNETIC_FIELD to get changes in the direction, but use SensorManager to get directions
    if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE)
        return;

    // Gets the value of the sensor that has been changed
    switch (event.sensor.getType()) {
    case Sensor.TYPE_ACCELEROMETER:
        gravity = event.values.clone();
        break;
    case Sensor.TYPE_MAGNETIC_FIELD:
        geomag = event.values.clone();

        break;
    }

    // If gravity and geomag have values then find rotation matrix
    if (gravity != null && geomag != null) {

        // checks that the rotation matrix is found
        boolean success = SensorManager.getRotationMatrix(inR, I, gravity, geomag);

            SensorManager.getOrientation(inR, orientVals);

            angle = (float) ToolBox.normalizeAngle(orientVals[0]);
            azimuth = (float) Math.toDegrees(angle);

            lowPassFilter();

            angle=(float) Math.toRadians(azimuth);

            if(listener!=null){
                listener.onCompassChanged(azimuth,angle,getAzimuthLetter(azimuth));
            }
        }
    }


public void stop(){
    try {
        sensorManager.unregisterListener(this);
    } catch (Exception e) {
        Logger.w("could not unregister listener", e);
    }
}

public String getAzimuthLetter(float azimuth) {
    String letter = "";
    int a = (int) azimuth;

    if (a < 23 || a >= 315) {
        letter = "N";
    } else if (a < 45 + 23) {
        letter = "NO";
    } else if (a < 90 + 23) {
        letter = "O";
    } else if (a < 135 + 23) {
        letter = "SO";
    } else if (a < (180 + 23)) {
        letter = "S";
    } else if (a < (225 + 23)) {
        letter = "SW";
    } else if (a < (270 + 23)) {
        letter = "W";
    } else {
        letter = "NW";
    }

    return letter;
}

protected void lowPassFilter() {
    // lowpass filter
    float dazimuth = azimuth -lastAzimuth;

    if (dazimuth > 180) {
        // change to range -180 to 0
        dazimuth = (float) (dazimuth - 360f);
    } else if (dazimuth < -180) {
        // change to range 0 to 180
        dazimuth = (float) (360f + dazimuth);
    }
    // lowpass filter
    azimuth = lastAzimuth+ dazimuth*l;

    azimuth%=360;

    if(azimuth<0){
        azimuth+=360;
    }

    lastAzimuth=azimuth;


}}

//

public class CompassMonitor {

static protected ArrayList<CompassListener> listeners=new ArrayList<CompassListener>();

static protected CompassSensorWatcher monitor=null;

static public synchronized void registerListener(Context context,CompassListener listener){

    if(listeners.size()==0){
        monitor=new CompassSensorWatcher(context,new CompassListener(){

            @Override
            public void onCompassChanged(float azimuth, float angle,String direction) {
                notifyListeners(azimuth,angle,direction);
            }

        },0.5f);
    }
    listeners.add(listener);
}

static synchronized public void unregisterListener(CompassListener listener){
    if (listeners != null && listener != null)
        listeners.remove(listener);


    if (listeners != null && listeners.size() == 0 && monitor != null) {
        try {
            monitor.stop();
        } catch (Exception e) {
            Logger.w("could not stop Compass Monitor", e);
        }
        monitor = null;
    }
}

static synchronized protected void notifyListeners(float azimuth,float angle, String direction){
    for(CompassListener l:listeners){
        try{
            l.onCompassChanged(azimuth,angle,direction);
        }catch(Exception ex){}
    }
}}

AFTER

public class GlassOrientationSocket implements Runnable {
public final static int PORT = 6604;
Socket mClientSocket;
Context context;
String mResult;
CompassListener listener;

public GlassOrientationSocket(Context context,CompassListener listener) {

    this.context = context;
    this.listener = listener;
}

@SuppressWarnings("deprecation")
@Override
public void run() {
    //Replace this with ip-address of android server (aka Google glass)
    String serverIP = "192.168.1.104";
    //port should be same as ServerSocketActivity
    try {
        mClientSocket = new Socket(serverIP, PORT);
        BufferedReader input = new BufferedReader(new InputStreamReader(mClientSocket.getInputStream()));
        WifiManager wim = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        List<WifiConfiguration> l = wim.getConfiguredNetworks();
        WifiConfiguration wc = l.get(0);
        while(true)
        {
            mResult = input.readLine();
            int angleCutter = mResult.indexOf("|",0);
            int azimuthLetterCutter = mResult.indexOf("|",angleCutter + 1);
            //Check if stream contatins good data
            if(mResult.substring(0,angleCutter) != "BAD DATA") {
                float azimuth = Float.valueOf(mResult.substring(0, angleCutter));
                float angle = Float.valueOf(mResult.substring(angleCutter + 1, azimuthLetterCutter));
                String azimuthLetter = mResult.substring(azimuthLetterCutter, mResult.length());
                listener.onCompassChanged(azimuth, angle, azimuthLetter);
            }
            else
            {
                Toast.makeText(context, "BAD SENSOR DATA", Toast.LENGTH_SHORT).show();
            }
        }

    } catch (UnknownHostException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}}

//

public class CompassMonitor {

static protected ArrayList<CompassListener> listeners=new ArrayList<CompassListener>();

static protected GlassOrientationSocket monitor=null;

static public synchronized void registerListener(Context context,CompassListener listener){
    if(listeners.size()==0){
        monitor=new GlassOrientationSocket(context,new CompassListener(){

            @Override
            public void onCompassChanged(float azimuth, float angle,String direction) {
                notifyListeners(azimuth,angle,direction);
            }

        });
        Thread thread = new Thread(monitor);
        thread.isDaemon();
        thread.start();
    }
    listeners.add(listener);
}

static synchronized public void unregisterListener(CompassListener listener){
    if (listeners != null && listener != null)
        listeners.remove(listener);
}

static synchronized protected void notifyListeners(float azimuth,float angle, String direction){
    for(CompassListener l:listeners){
        try{
            l.onCompassChanged(azimuth,angle,direction);
        }catch(Exception ex){}
    }
}

}

GENERIC INTERFACE (SAME IN BOTH VERSIONS)

public interface CompassListener {
/**
 * This method will be called, if the azimuth of the compass changes. The values are lowpass filtered, to get smother results. 
 * @param azimuth the current direction of the device towards north in degrees
 * @param angle the current direction of the device towards north in radiant
 * @param direction a String describing the the compass direction, i.e. N, SO, NW
 */
public void onCompassChanged(float azimuth,float angle,String direction);    
Menno
  • 31
  • 5

1 Answers1

0

I fixed this issue by not passing the listener to the Thread. I used a Message handler to handle the message, and then call notify all listeners in the CompassMonitor Class, Works like a charm now.

Menno
  • 31
  • 5