|
Page 2 of 4
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):
|