I have recently been playing with the Android SDK. The following code is the culmination of my efforts so far. These files allow you to create an Activity that will run on the phone, create a Thread, and then create a SurfaceView that will act as the main application.

While there are no controls used, and the actual activity is fairly limited, these files demonstrate how to override a surfaceView, and take both touch and accelerometer input in the same class. Ultimately this is all of the basic framework needed to start building a game or other non-control based application.

The screen color and ball color both change based on the accelerometer input. The ball moves based on said input, and touching the screen relocates the ball to that position.

TiltBallActivity.java

package com.tornquist.nathan;

import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;

public class TiltBallActivity extends Activity{
    /** Called when the activity is first created. */
	MainGamePanel viewPanel;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //Window state functions.
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        //This works without declaring a viewPanel instance here.
        //The instance declaration is needed to pass the
        //onPause and onResume commands though.
        viewPanel = new MainGamePanel(this);
        setContentView(viewPanel);
    }

    //Restarts the accelerometer after onPause
    protected void onResume() {
        super.onResume();
        viewPanel.resume(this);
    }

    //Standard Method run when the Application loses focus.
    //This runs the pause() function in the viewPanel so that
    //the accelerometer can be paused.
    protected void onPause() {
        super.onPause();
        viewPanel.pause();
    }
}

MainGamePanel.java

package com.tornquist.nathan;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.view.Display;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class MainGamePanel extends SurfaceView implements SensorEventListener, SurfaceHolder.Callback
{
	//Variable Declarations.
	private MainThread thread;
	public int xColor;
	public int yColor;
	public int zColor;

	public float xPos;
	public float yPos;
	public float oldXPos;
	public float oldYPos;

	public int screenWidth;
	public int screenHeight;

	private SensorManager mSensorManager;
	private Sensor mAccelerometer;

	Paint paint;

	public MainGamePanel(Context context)
	{
		//Standard Initialization
		super(context);

		//This line adds a callback for the touch screen.
		//This allows you to actually capture touch input.
		getHolder().addCallback(this);

		thread = new MainThread(getHolder(),this);

		xColor = 100;
		yColor = 100;
		zColor = 100;

		paint = new Paint();
		paint.setAntiAlias(true);

		Display display = ((Activity) context).getWindowManager().getDefaultDisplay();
		screenWidth = display.getWidth();
		screenHeight = display.getHeight();

		yPos = screenHeight/2;
		xPos = screenWidth/2;
		oldYPos = yPos;
		oldXPos = xPos;

		//This registers the accelerometer.  Without registering it, the onSensorChanged
		//event will never be called, and you cannot get the accelerometer values.
		mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);

		mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

		mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_FASTEST);

		//Also required for touch input.
		setFocusable(true);
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		// at this point the surface is created and
		// we can safely start the game loop
		thread.setRunning(true);
		thread.start();
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		boolean retry = true;
		while (retry) {
			try {
				thread.join();
				retry = false;
			} catch (InterruptedException e) {
				// try again shutting down the thread
			}
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (event.getAction() == MotionEvent.ACTION_DOWN) {
						// check if in the lower part of the screen we exit
			if (event.getY() > getHeight() - 50) {
				thread.setRunning(false);
				((Activity)getContext()).finish();
			}

			if (xColor < 235)
				xColor = xColor + 20;
			else
				xColor = 0;
			if (yColor < 235)
				yColor = yColor + 20;
			else
				yColor = 0;
			if (zColor < 235)
				zColor = zColor + 20;
			else
				zColor = 0;

			yPos = event.getY();
			xPos = event.getX();
		}
		return true;
	}

	@Override
	protected void onDraw(Canvas canvas)
	{
		//canvas.drawColor(Color.CYAN);
		canvas.drawColor(Color.rgb(xColor, yColor, zColor));
		int xInvert = (int) (255 - xColor);
		int yInvert = (int) (255 - yColor);
		int zInvert = (int) (255 - zColor);

		paint.setColor(Color.rgb(xInvert, yInvert, zInvert));
		paint.setStyle(Style.FILL);
		canvas.drawCircle(xPos, yPos, 50, paint);
	}

	public void update() {
	}

	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
	}

	@Override
	public void onSensorChanged(SensorEvent event) {

		oldYPos = yPos;
		oldXPos = xPos;

		xColor = (int) (255 + (event.values[0])*11);
		if (xColor > 255)
			xColor = 255;
		if (xColor < 0)
			xColor = 0;

		yColor = (int) (255 + (event.values[1])*11);
		if (yColor > 255)
			yColor = 255;
		if (yColor < 0)
			yColor = 0;

		zColor = (int) (255 + (event.values[2])*11);
		if (zColor > 255)
			zColor = 255;
		if (zColor < 0)
			zColor = 0;

		xPos = xPos + -1*(event.values[0])*5;
		yPos = yPos + event.values[1]*5;

		if (xPos < 50)
			xPos = 50;
		if (xPos > screenWidth - 50)
			xPos = screenWidth - 50;
		if (yPos < 50)
			yPos = 50;
		if (yPos > screenHeight - 50)
			yPos = screenHeight - 50;

		if ((oldYPos == yPos) && (oldXPos == xPos))
		{
			invalidate();
		}

	}

	public void pause() {
		mSensorManager.unregisterListener(this);

                //This actually kills the application.  I am running WidgetLocker, and the onResume()
                //method fails to run correctly, so I kill the app for testing purposes.
		thread.setRunning(false);
		((Activity)getContext()).finish();
	}

	public void resume(Context context) {
		mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);

		mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

		mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
	}

}

MainThread.java

package com.tornquist.nathan;

import com.tornquist.nathan.MainGamePanel;
import android.graphics.Canvas;
import android.view.SurfaceHolder;

public class MainThread extends Thread {

	private SurfaceHolder surfaceHolder;
	private MainGamePanel gamePanel;
	private boolean running;
	public void setRunning(boolean running) {
		this.running = running;
	}

	public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) {
		super();
		this.surfaceHolder = surfaceHolder;
		this.gamePanel = gamePanel;
	}

	@Override
	public void run()
	{
		Canvas canvas;
		while (running) {
			canvas = null;
			// try locking the canvas for exclusive pixel editing on the surface
			try {
				canvas = this.surfaceHolder.lockCanvas();
				synchronized (surfaceHolder) {
					// update game state
					this.gamePanel.update();

					// draws the canvas on the panel
					this.gamePanel.onDraw(canvas);
				}
			} finally {
				// in case of an exception the surface is not left in
				// an inconsistent state
				if (canvas != null) {
					surfaceHolder.unlockCanvasAndPost(canvas);
				}
			}	// end finally
		}
	}
}