我的问题很难解释,但我会尝试。我正在使用内部导航软件(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);
答案 0 :(得分:0)
我通过不将侦听器传递给Thread来修复此问题。我使用Message处理程序来处理消息,然后调用通知CompassMonitor类中的所有侦听器,现在就像魅力一样。