Home Tutorials Hands on Sensor arrow - Co-ordinate maths
Sensor arrow - Co-ordinate maths
Sunday, 08 March 2009 18:54
Article Index
Sensor arrow
Co-ordinate maths
Handling the sensor values
Simulation
All Pages

The app here shows how to use the orientaion sensors in both hardware and software. This is useful because when developing you often want to keep switching between a real handset and the emulator, but of course the emulator doesn't support hardware (normally!), and the handset prefers to use its own hardware so won't listen to the simulator on your PC. This is accomplished using a proxy class in java which is aware of everything except its actual sensor listening method - we'll come to that shortly.

The full source is given at the end of this article, but for now lets look at exactly how these sensor values arrive in hardware:

public void onSensorChanged(SensorEvent event) {
    if (!isRegistered) return;
    
    switch(event.sensor.getType()) {
        case Sensor.TYPE_ORIENTATION: {
            for (int i = 0; i < 3; i++) {
                mActivity.mSensorArrowView.mOrientationValues[i] = event.values[i];
            }
            mActivity.mSensorArrowView.calcAngle();
            mActivity.mSensorArrowView.invalidate();
        }
        break;
    }
}

And with the software simulator

public void onSensorChanged(SensorEvent event) {
    if (!isRegistered) return;

    switch(event.type) {
        case Sensor.TYPE_ORIENTATION: {
            for (int i = 0; i < 3; i++) {
                mActivity.mSensorArrowView.mOrientationValues[i] = event.values[i];
            }
            mActivity.mSensorArrowView.calcAngle();
            mActivity.mSensorArrowView.invalidate();
        }
        break;
    }
}

The values arrive as part of a SensorEvent object, so all we do is extract them appropriately. The trick is, the SensorEvent object isn't the same type for each method - for hardware it's android.hardware.SensorEvent and with the simulator it's org.openintents.sensorsimulator.hardware.SensorEvent.

To handle both cases in the same app, we use these methods in each child class using the proxy as a parent. Here's how that parent looks:

public abstract class ProxySensor {
	protected SensorArrowActivity mActivity;
    public boolean isRegistered = false;

    public ProxySensor(SensorArrowActivity activity) {
    	mActivity = activity;
    }
    
    public abstract boolean register();
    public abstract boolean unregister();
}

So we can see any children must implement a register() and unregister() method. If we want them to listen to sensor events, we must also implement the appropriate sensor listening interface. Here's how the hardware one does it:

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;

import com.androidacademy.tutorials.sensorarrow.R;
import com.androidacademy.tutorials.sensorarrow.SensorArrowActivity;
import com.androidacademy.tutorials.sensorarrow.proxy.ProxySensor;

public class HardwareSensor extends ProxySensor implements SensorEventListener {
    private SensorManager mSensorManager;

    public HardwareSensor(SensorArrowActivity activity) {
    	super(activity);
    	
    	mSensorManager = (SensorManager) mActivity.getSystemService(
    		Activity.SENSOR_SERVICE);
    	isRegistered = register();
    }
    ...
}

And the software one:

import org.openintents.sensorsimulator.hardware.Sensor;
import org.openintents.sensorsimulator.hardware.SensorEvent;
import org.openintents.sensorsimulator.hardware.SensorEventListener;
import org.openintents.sensorsimulator.hardware.SensorManagerSimulator;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.hardware.SensorManager;

import com.androidacademy.tutorials.sensorarrow.R;
import com.androidacademy.tutorials.sensorarrow.SensorArrowActivity;
import com.androidacademy.tutorials.sensorarrow.proxy.ProxySensor;

public class SoftwareSensor extends ProxySensor implements SensorEventListener {
    private SensorManagerSimulator mSensorManager;

    public SoftwareSensor(SensorArrowActivity activity) {
    	super(activity);
    	
    	mSensorManager = SensorManagerSimulator.getSystemService(
    		mActivity, Activity.SENSOR_SERVICE);
    	isRegistered = register();
    }
    ...
}

Notice the difference in the imports statements for each class - that's how the SensorEvent mentioned earlier is a different type in each listener method.

The point to all this is we can now switch between hardware and software sensors no matter if the app is running on a handset (hardware) or the emulator (software):


Choose sensor

 

Add comment


Security code
Refresh

Portions are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License. Android Academy is independent from Google. All trademarks acknowledged.
 
Glossary
We have 71 guests online