The Orient Express
So, I got a new toy^H^H^Hphone the other day, and I started playing around with programming for it. The new one is an Android (Xperia X10 Mini), and I found plenty of resources for programming it.
So, yesterday I spent playing around with the direction sensors - and I came up with a simple gyro/compass. Since this could be a fun basis for a game that I would like to play, in case you write it, I thought I'd share. (And also, becase the implementations I found on the web were quite tied into other stuff.)
So, how do I get at the sensors? I register a listener! Most implementations I've seen register the main object as the listener. That's cool for simple implementations (as if my example isn't a simple implementation!), but IMHO it looks messy if the main object implements a ton of interfaces. Not to mention it discourages code reuse. Thus, I'd rather implement it as its own class. This is what it looks like:
package com.blueturtle.orientexp; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; public class OrientationListener implements SensorEventListener { private SensorManager olManager=null; private Sensor olSensor=null; private BTBase olContext=null; private float[] olOrientation = new float[3]; // Constructor public OrientationListener(BTBase context, SensorManager man) { olContext=context; olManager = man; // Get a sensor olSensor = olManager.getDefaultSensor( Sensor.TYPE_MAGNETIC_FIELD); // Debug check, we do have a sensor, right? // (Comment next two lines when you are tired of the dialog) olContext.shout("Orientation sensor", "Orientation sensor name:\n"+olSensor.getName()); // Enable the sensor enable(); } // All we do when we enable the sensor is registering the listener public void enable() { olManager.registerListener(this, olSensor, SensorManager.SENSOR_DELAY_GAME); } // And when we disable the sensor, we do it by // unregistering the listener public void disable() { olManager.unregisterListener(this); } // Unused, but must be "implemented" public void onAccuracyChanged(Sensor arg0, int arg1) { } // Copy the sensor data to a local variable public void onSensorChanged(SensorEvent se) { for (int i=0; i<3; ++i) { olOrientation[i] = se.values[i]; } olContext.update(BTBase.BTBASE_ORIENTATION); } // Return the current orientation to anyone who asks public float[] getOrienttation() { return olOrientation; } }
But wait! What's that BTBase thingie? The short answer is this:
package com.blueturtle.orientexp; public interface BTBase { // Flags public int BTBASE_ORIENTATION=0x1; // Flag for orientation callbacks // Interface methods public void update(int flag); // Callback public void shout(String title, String msg); // Debug dialog }
The slightly longer answer is that i want to give the sensors to call back to the main object. So I created an interface that will be called back by the sensors. The flag is used for information about exactly who made the callback (I plan to add more listeners, e.g. for GPS and timers).
But something's missing! What's that? Oh, the main class. For now, all we'll do is write out the values in a simple text view. Here we go:
package com.blueturtle.orientexp; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.hardware.SensorManager; import android.os.Bundle; import android.widget.TextView; public class OrientExp extends Activity implements BTBase { private TextView myYaw=null; private TextView myPitch=null; private TextView myRoll=null; private OrientationListener myListener=null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Get references to the text views used to output the data // Defined in res/layout/main.xml myYaw = (TextView) findViewById(R.id.viewyaw); myPitch = (TextView) findViewById(R.id.viewpitch); myRoll = (TextView) findViewById(R.id.viewroll); // Create the listener (the second argument is this object retrieving // a sensor manager and passing it along) myListener = new OrientationListener(this, (SensorManager)getSystemService(Context.SENSOR_SERVICE)); } public void update(int flags) { // Get the data float[] data = myListener.getOrienttation(); // Update interface text myYaw.setText("Yaw: "+ data[0]); myPitch.setText("Pitch: "+data[1]); myRoll.setText("Roll: "+data[2]); } // Create a message dialog for debug messages public void shout(String title, String msg) { AlertDialog.Builder dialog = new AlertDialog.Builder(this); dialog.setTitle(title); dialog.setMessage(msg); dialog.show(); } // Disable the orientation sensors on pause public void onPause() { super.onPause(); myListener.disable(); } // And resume afterwards public void onResume() { super.onResume(); myListener.enable(); } }
That's it!
Isn't it? No. The textviews are defined in the layout document res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:id="@+id/viewyaw" <!-- This id is what we use to identify the textview in OrientExp.java --> android:textSize="15pt" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Yaw: " /> <TextView android:id="@+id/viewpitch" android:textSize="15pt" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Pitch: " /> <TextView android:id="@+id/viewroll" android:textSize="15pt" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Roll: " /> </LinearLayout>
Nothing to write home about here. I create three textveiws with an id, a text size and a default text. The default text is replaced by the activity object when we get our first sensor reading.
That's it. There's no more to the demo. I suppose I could have changed stuff in the manifest, but there's nothing that needs a change there for this test application, so why bother?
Now, all that's needed is a device to try it on. Sure, there is the emulator - but it doesn't excercise the orientation sensors particularly. Of course, there is someone who wrote an simulator for the motion sensors in the emulator: http://code.google.com/p/openintents/wiki/SensorSimulator It isn't all that complicated to implement, but I'll leave that as an excercise for the reader.
- By ibnalhazardous at 07/22/2010 - 14:14
- android
- orientation sensors
- programming
- ibnalhazardous's blog

Recent comments
15 weeks 5 days ago
1 year 40 weeks ago
2 years 8 weeks ago
2 years 40 weeks ago
2 years 40 weeks ago
2 years 40 weeks ago
2 years 40 weeks ago
2 years 45 weeks ago
2 years 46 weeks ago
2 years 48 weeks ago