Technology

MLK Dream utilizes OpenGL ES 2.0 with custom vertex and fragment shaders. Rajawali is an awesome library used in Earth 3D.

Smart Devices

Android sensors can tell you almost any information about a device. The newest phones have more than 20 sensors!

Native Apps

100% Android. Applications use native SDK packages to blend seamlessly and follow Android UI/UX design guidelines.

Applications Portfolio

DroidSense Sensor Tool Box

A utility that provides direct access to device sensors. Uses OpenGL ES graphics to demo sensor properties and AndroidPlot to graph in real-time.

RideX Trip Tracker

Uses GPS and the accelerometer to monitor movement and calculate GForce. Google Maps v2 API is integrated to easily display trip summary.

Specter Sense

A tool to help detect paranormal activity. Record and share videos with freinds. The camera preview is customized with EMF meter and flashlight.

Jac Mobile Blog

Gallery ? HorizontalScrollView : ViewPager

The Android team decided to streamline the SDK by cutting out large tools like Gallery in favor of a more customizable toolbox. Two options are often presented as alternatives to Gallery: HorizontalScrollView and ViewPager. In order to reproduce the functionality of Gallery it would take A LOT of work. Here's a sample that can get you moving in the right direction in no time. Just use PerspectiveView as the child of your HorizontalScrollView.

public class PerspectiveView extends LinearLayout {
    private static final float FACTOR = 0.7f;
    private static final float X_ANCHOR = 0.5f;
    private static final float Y_ANCHOR = 1.0f;

//    Constructors omitted for brevity. Include init() in each.
    private void init() {
        setStaticTransformationsEnabled(true);
    }
    @Override
    protected boolean getChildStaticTransformation(View child, Transformation t) {
        HorizontalScrollView scrollView = null;
        if (getParent() instanceof HorizontalScrollView) {
            scrollView = (HorizontalScrollView) getParent();
        }
        if (scrollView == null) {
            return false;
        }
        int childCenter = getXCenter(child);
        int xCenter = getXCenter(scrollView);
        float delta = Math.min(1.0f, Math.abs(childCenter - xCenter)/(float) xCenter);
        float scale = SCALE_FACTOR * delta;
        float xTrans = child.getWidth() * ANCHOR_X;
        float yTrans = child.getHeight() * ANCHOR_Y;
        t.clear();
        t.getMatrix().setScale(scale, scale, xTrans, yTrans);
        child.invalidate();
        return true;
    }
    private int getXCenter(View view) {
        int[] childCoords = new int[2];
        view.getLocationOnScreen(childCoords);
        int childCenter = childCoords[0] + (view.getWidth() / 2);
        return childCenter;
    }
}

Rajawali library is amazing!

If you've ever studied OpenGL, you know that just to render a sphere you could easily write one thousand lines of code. Rajawali is an OpenGL framework for Android that simplifies a lot of tasks. To create a sphere with Rajawali the code is reduced to something like this:

DiffuseMaterial material = new DiffuseMaterial();
material.addTexture(new TextureInfo(R.drawable.texture));
Object3d mSphere = new Sphere(1, 24, 24);
mSphere.setMaterial(material);
mSphere.addLight(mLight);
addChild(mSphere);

Of course there's some additional boiler-plate code to set up your Fragment or Activity and renderer, but Rajawali even has helper classes for this. I strongly encourage anyone who uses OpenGL for Android to check this out!

Android Rotation Vector Sensor Exception

If you follow the Android API guide for the rotation sensor, you will run into an error. Specifically: java.lang.IllegalArgumentException, because some devices return an array with four or even FIVE values. You can probably fix this now that you know this, but anyway here's a solution:

private int rotateVectLength;
private float[] jRotateVectValues = null;
public void onSensorChanged(SensorEvent event) {
    // It's good practice to check that we received the proper event
    if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) {
        // Convert the rotation vector to a 4x4 matrix. The matrix is interpreted by
        // OpenGL as the inverse of the rotation vector, which is what we want.
        if(jRotateVectValues == null) {
            rotateVectLength = event.values.length;
            jRotateVectValues = new float[rotateVectLength];
        }
        for (float element :  event.values)
            jRotateVectValues[i] = element;
        SensorManager.getRotationMatrixFromVector(mRotationMatrix, event.values);
    }
}