A couple of students need to take pictures, and store their pictures in the database.  This allowed them to easily associate (tag) other data to the each picture, and manage their pictures, access and remove them easily.  We store binary data in a database record using a BLOB.

The database helper class looks like this:-

package com.danielfreeman.android.classes;

import android.content.Context;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase;

public class MyDBHelper extends SQLiteOpenHelper {

	final protected static String DATABASE_NAME="pictures";

	public MyDBHelper(Context context) {
		super(context, DATABASE_NAME, null, 4);
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL("DROP TABLE storedImages;");
		db.execSQL("CREATE TABLE storedImages (_id INTEGER PRIMARY KEY, image BLOB, tag TEXT);");
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		if (oldVersion >= newVersion)
			return;

	    onCreate(db);
	}
}

I put the application inside a TabActivity. Although the camera preview gets a bit squashed up this way.  So the UI needs a bit of thought.  Nevertheless, here is the main Activity code, based on Marakana’s camera tutorial:-

package com.danielfreeman.android;

import com.danielfreeman.android.classes.Preview;
import com.danielfreeman.android.classes.MyDBHelper;

import android.app.TabActivity;
import android.content.ContentValues;
import android.content.pm.ActivityInfo;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TabHost;
import android.widget.TextView;
import android.widget.TabHost.TabSpec;

public class HelloCamera extends TabActivity {

  protected Preview preview;
  protected Button buttonClick;
  protected MyDBHelper myDBHelper;
  protected TabHost tabHost;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

    tabHost = getTabHost();
    newTab("gallery", null, R.id.tab0);
    newTab("camera", null, R.id.tab1);

    preview = new Preview(this);
    ((FrameLayout) findViewById(R.id.preview)).addView(preview);

    buttonClick = (Button) findViewById(R.id.buttonClick);
    buttonClick.setOnClickListener(new OnClickListener() {
      public void onClick(View v) {
        preview.camera.takePicture(shutterCallback, rawCallback, jpegCallback);
      }
    });

    myDBHelper = new MyDBHelper(this);
    readDatabase();
  }

  protected void newTab(String label, Drawable icon, int page) {
  	TabSpec tabSpec = tabHost.newTabSpec(label);
  	tabSpec.setIndicator(label,icon);
  	tabSpec.setContent(page);
  	tabHost.addTab(tabSpec);
  }

  // Called when shutter is opened
  ShutterCallback shutterCallback = new ShutterCallback() {
    public void onShutter() {
    }
  };

  // Handles data for raw picture
  PictureCallback rawCallback = new PictureCallback() {
    public void onPictureTaken(byte[] data, Camera camera) {
    }
  };

  // Handles data for jpeg picture
  PictureCallback jpegCallback = new PictureCallback() {
    public void onPictureTaken(byte[] data, Camera camera) {

    SQLiteDatabase db = myDBHelper.getReadableDatabase();
    ContentValues values = new ContentValues();
    values.put("image", data);
    db.insert("storedImages", "tag", values);
    preview.camera.startPreview();
    }
  };

  protected void readDatabase() {
	  TextView info = (TextView) findViewById(R.id.info);
	  info.setText("Integer.toString(cursor.getCount())");
	  SQLiteDatabase db = myDBHelper.getReadableDatabase();
	  Cursor cursor = db.rawQuery("SELECT * FROM storedImages ;", null);

	  info.setText(Integer.toString(cursor.getCount()));

	  if (cursor.getCount()>0) {
		  cursor.moveToNext();
		  ImageView image = (ImageView) findViewById(R.id.image);
		  byte[] data = cursor.getBlob(cursor.getColumnIndex("image"));
		  image.setImageBitmap(BitmapFactory.decodeByteArray(data, 0, data.length));
	  }
  }

}

I use a db.insert() method to put the jpeg data into the database.  Note that the readDatabase() class is very simple.  Although it retrieves the entire database, it only displays one image.

Finally, here is the Preview class:-

package com.danielfreeman.android.classes;

import java.io.IOException;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class Preview extends SurfaceView implements SurfaceHolder.Callback {

  SurfaceHolder mHolder;
  public Camera camera;

public Preview(Context context) {
    super(context);

    // Install a SurfaceHolder.Callback so we get notified when the
    // underlying surface is created and destroyed.
    mHolder = getHolder();
    mHolder.addCallback(this);
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
  }

  // Called once the holder is ready
  public void surfaceCreated(SurfaceHolder holder) {
    // The Surface has been created, acquire the camera and tell it where
    // to draw.
    camera = Camera.open();
    try {
      camera.setPreviewDisplay(holder);

      camera.setPreviewCallback(new PreviewCallback() {
        // Called for each frame previewed
        public void onPreviewFrame(byte[] data, Camera camera) {
          Preview.this.invalidate();
        }
      });
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  // Called when the holder is destroyed
  public void surfaceDestroyed(SurfaceHolder holder) {
    camera.stopPreview();
    camera = null;
  }

  // Called when holder has changed
  public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    camera.startPreview();
  }

}

I haven’t included the layout file, as it probably needs rethinking, so you can probably come up with a better UI.  At the moment it’s wrapped up in a TabHost, a preview area (FrameLayout), and includes a Button called ‘buttonClick’.

Advertisements