Version 1.3
Copyright © 2011, 2012 Lars Vogel
02.01.2013
| Revision History | |||
|---|---|---|---|
| Revision 0.1 | 06.12.2011 | Lars Vogel |
Created |
| Revision 0.2 - 1.3 | 06.12.2011 - 02.01.2013 | Lars Vogel |
bug fixes and enhancements |
Table of Contents
Most Android devices have a camera. Some devices have a front and a back camera.
Using the camera on the Android device can be done via
integration of
the existing Camera application. In this case you would start the
existing Camera application via an
Intent
and to get the data after the user returns to our application.
You can also directly integrate the camera into your application via
the
Camera
API.
Create a new Android project
de.vogella.android.imagepick
with an
activity
called
ImagePickActivity.
Change the
ImagePickActivity
class to the following.
package de.vogella.android.imagepick; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.view.View; import android.widget.ImageView; public class ImagePickActivity extends Activity { private static final int REQUEST_CODE = 1; private Bitmap bitmap; private ImageView imageView;/** Called when the activity is first created. */@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); imageView = (ImageView) findViewById(R.id.result); } public void pickImage(View View) { Intent intent = new Intent(); intent.setType("image/*"); intent.setAction(Intent.ACTION_GET_CONTENT); intent.addCategory(Intent.CATEGORY_OPENABLE); startActivityForResult(intent, REQUEST_CODE); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) try { // We need to recyle unused bitmaps if (bitmap != null) { bitmap.recycle(); } InputStream stream = getContentResolver().openInputStream(data.getData()); bitmap = BitmapFactory.decodeStream(stream); stream.close(); imageView.setImageBitmap(bitmap); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } super.onActivityResult(requestCode, resultCode, data); } }
In this example we will an application which allow to make a photo via the front camera and to save it on the SD card. If you using the Android emulator make sure you added space for the SD card during the creation of the your Android virtual device.
Create a new Android project
de.vogella.camera.api
with an
activity
called
MakePhotoActivity .
Add the
android.permission.CAMERA
permission to access your camera and the
android.permission.WRITE_EXTERNAL_STORAGE
to be able to write to the SD card to your AndroidManifest.xml file.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="de.vogella.cameara.api" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="15" /> <uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name="de.vogella.camera.api.MakePhotoActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
Change the main.xml file in the res/layout folder to the
following
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <Button android:id="@+id/captureFront" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:onClick="onClick" android:text="Make Photo" /> </RelativeLayout>
Create the following
PhotoHandler
class which will be responsible for saving the photo the SD card.
package de.vogella.camera.api; import java.io.File; import java.io.FileOutputStream; import java.text.SimpleDateFormat; import java.util.Date; import android.content.Context; import android.hardware.Camera; import android.hardware.Camera.PictureCallback; import android.os.Environment; import android.util.Log; import android.widget.Toast; public class PhotoHandler implements PictureCallback { private final Context context; public PhotoHandler(Context context) { this.context = context; } @Override public void onPictureTaken(byte[] data, Camera camera) { File pictureFileDir = getDir(); if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) { Log.d(MakePhotoActivity.DEBUG_TAG, "Can't create directory to save image."); Toast.makeText(context, "Can't create directory to save image.", Toast.LENGTH_LONG).show(); return; } SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss"); String date = dateFormat.format(new Date()); String photoFile = "Picture_" + date + ".jpg"; String filename = pictureFileDir.getPath() + File.separator + photoFile; File pictureFile = new File(filename); try { FileOutputStream fos = new FileOutputStream(pictureFile); fos.write(data); fos.close(); Toast.makeText(context, "New Image saved:" + photoFile, Toast.LENGTH_LONG).show(); } catch (Exception error) { Log.d(MakePhotoActivity.DEBUG_TAG, "File" + filename + "not saved: " + error.getMessage()); Toast.makeText(context, "Image could not be saved.", Toast.LENGTH_LONG).show(); } } private File getDir() { File sdDir = Environment .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); return new File(sdDir, "CameraAPIDemo"); } }
Change the
MakePhotoActivity
class to the following.
package de.vogella.camera.api; import android.app.Activity; import android.content.pm.PackageManager; import android.hardware.Camera; import android.hardware.Camera.CameraInfo; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Toast; import de.vogella.cameara.api.R; public class MakePhotoActivity extends Activity { private final static String DEBUG_TAG = "MakePhotoActivity"; private Camera camera; private int cameraId = 0; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // do we have a camera? if (!getPackageManager() .hasSystemFeature(PackageManager.FEATURE_CAMERA)) { Toast.makeText(this, "No camera on this device", Toast.LENGTH_LONG) .show(); } else { cameraId = findFrontFacingCamera(); if (cameraId < 0) { Toast.makeText(this, "No front facing camera found.", Toast.LENGTH_LONG).show(); } else { camera = Camera.open(cameraId); } } } public void onClick(View view) { camera.takePicture(null, null, new PhotoHandler(getApplicationContext())); } private int findFrontFacingCamera() { int cameraId = -1; // Search for the front facing camera int numberOfCameras = Camera.getNumberOfCameras(); for (int i = 0; i < numberOfCameras; i++) { CameraInfo info = new CameraInfo(); Camera.getCameraInfo(i, info); if (info.facing == CameraInfo.CAMERA_FACING_FRONT) { Log.d(DEBUG_TAG, "Camera found"); cameraId = i; break; } } return cameraId; } @Override protected void onPause() { if (camera != null) { camera.release(); camera = null; } super.onPause(); } }
Before posting questions, please see the vogella FAQ. If you have questions or find an error in this article please use the www.vogella.com Google Group. I have created a short list how to create good questions which might also help you.
vogella Training Android and Eclipse Training from the vogella team
Android Tutorial Introduction to Android Programming
GWT Tutorial Program in Java and compile to JavaScript and HTML
Eclipse RCP Tutorial Create native applications in Java
JUnit Tutorial Test your application
Git Tutorial Put everything you have under distributed version control system