Google Glass - Wifi Compass集成。油漆环仅触发一次

时间:2014-10-14 16:08:31

标签: android multithreading orientation google-glass

我的问题很难解释,但我会尝试。我正在使用内部导航软件(Wificompass - https://code.google.com/p/wificompass/)和谷歌眼镜制作一个项目。我正在使用谷歌玻璃的方向,而Wificompass软件正在手机上运行)数据从玻璃(服务器)发送到手机(客户端)。这部分已经开始工作和测试了。问题是当我将我的客户端代码集成到wificompass框架中时。我将在编辑源代码之前和之后发布情况。基本上我的问题是阻塞ui线程,如果我使用我的GlassOrientationSocket,我仍然可以按下ui屏幕上的按钮,这些按钮后面的代码仍然运行,但对象(指南针和用户)的绘画被阻止,我不知道如何这可能发生。有人知道如何解释这种行为吗?

额外信息:经过数小时的调试后,我发现多个drawables的绘制循环没有循环。 在原始源代码中,循环工作正常并且不断绘制(不断地在drawables上调用draw),在我的代码中,这个循环只能工作1次(然后在drawables上调用dispatchdraw),当我暂停活动时,循环被触发但只有一次。我在原始代码中唯一改变的是serversocket(在线程上运行)。有人有任何想法吗?欢迎任何建议。

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){}
    }
}}

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(同样版本)

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);    

1 个答案:

答案 0 :(得分:0)

我通过不将侦听器传递给Thread来修复此问题。我使用Message处理程序来处理消息,然后调用通知CompassMonitor类中的所有侦听器,现在就像魅力一样。