Monday, December 30, 2013

Making Beautiful Android App Icons


For most users, the launcher icon (sometimes referred to as the app icon) is the first impression of your app. As higher density screens on both phones and tablets gain popularity, it's important to make sure your launcher icon is crisp and high quality. To do this, make sure you’re including XHDPI (320dpi) and XXHDPI (480dpi) versions of the icon in your app.
In addition to the current launcher icon guidelines, please also refer to these additional important guidelines when creating your icons:
  • Launcher icons are 48dp square and should be provided for MDPI, HDPI, XHDPI, and XXHDPI densities—at the very least XHDPI and XXHDPI.
  • The 512px Google Play listing icon should have the same content as the launcher icon, except for minor additional badging.
  • Launcher icons should be designed specifically for Android. As per the Pure Android design guidelines, avoid mimicking visual elements and styles from other platforms.
  • Launcher icons should be three-dimensional, front view, with a slight perspective as if viewed from above, so that users perceive some depth.
  • Launcher icons should have a distinct silhouette, meaning that you should avoid simple square/circle icons and instead opt for unique shapes.
  • Launcher icons should be simple at the macro level but still detailed at the micro level (e.g. include subtle edge effects, gradients and textures).
  • Launcher icons should employ lightweight background protection such as a subtle drop shadow, but it should not be too dark or visually prominent.
  • Launcher icons should include between 0dp and 3dp of padding. Vary the padding for optical alignment and weight normalization purposes (e.g. thinner icons can use smaller padding and thicker icons can use less padding for a more consistent icon mass across icons).
Note that tablets and other large screen devices request a launcher icon that is one density size larger than the device's actual density, so you should provide your launcher icon at the highest density possible. For example, if a tablet has an XHDPI screen, it will request the XXHDPI version of the launcher icon

The Beautiful Design Summer 2013 Collection on Google Play

Attention to detail makes an app truly beautiful: transitions are fast and clear, layout and typography are crisp and meaningful, and design touches that delight you in surprising ways are sprinkled throughout. Today, we’re publishing a new Beautiful Design collection on Google Play, which highlights 11 beautiful apps with these kinds of masterfully crafted design details.
The collection, which we’ll refresh with new apps every so often, currently includes:
  • Pattrn (by Lucas Rocha), a beautifully focused app for discovering and sharing unique wallpapers on any size screen device.
  • Pocket (by Read It Later), an article keeper and reader app with a beautiful queue browsing interface and a remarkably comfortable and pleasing reading experience on phones and tablets.
  • Timer (by Opoloo), a timer app with an elegant and deeply satisfying timer-creation interface and simple, beautiful theme choices.
  • Eye in Sky Weather, NY Times, Grand St., Pinterest, Press, Expedia, Flipboard and TED… each with delightful design details.
If you’re an Android developer, make sure to play with some of these apps to get a sense for the types of design details that can separate good apps from great ones.
Lastly, remember that this new Beautiful Design collection is just one of a number of unique collections on Google Play that are front and center in the new Google Play Store app client.

SearchableDictionary - Searchable Dictionary

A sample application that demonstrates Android's search framework.
This application includes a dictionary of words. By invoking a search inside the app (via the device search button or Menu > Search), a local search will be performed across the dictionary. As you type, suggestions will appear, which you can select to view the full definition. You can also execute the search to view all word definitions that match the entered text.
The application also grants content provider privileges to Quick Search Box, Android's system-wide search tool. This means that the dictionary definitions can be offered as search suggestions outside of the application, when text is entered into Quick Search Box.
See also:


You can find the source code for this sample in your SDK at:
<sdk>/platforms/android-<version>/samples/

Android working with Camera


Now a days lot of apps offer users to take pictures and record videos for various kind of purposes. This tutorial describes how to do the same in your applications.
Integrating camera can be done in two ways. One is to use android inbuilt camera app which is very easy process. This method won’t give you much control over camera as everything is taken care by inbuilt camera app. This way will be appropriate when your app need just a picture or video from camera.
Second way is to build a custom camera interface and adding the functionality. This needs higher effort as we have to do everything by our own. Building custom camera interface will be useful when you are building an app which mainly deals with images and videos like Instagram.
This tutorial covers the first scenario which is using android in build camera app in your application.

Let’s start by creating a new project
1. Create a new project in Eclipse from File ⇒ New ⇒ Android ⇒ Application Project and fill all the required information. I left my main activity as MainActivity.java

Adding Permissions / Features

2. Working with camera needs set of permissions and features in the AndroidManifest.xml file. Add following in your AndroidManifest.xml
android.hardware.camera – Required to use camera hardware
WRITE_EXTERNAL_STORAGE – Required to store images / video in external storage
RECORD_AUDIO – Needed when recording video with audio
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="info.androidhive.androidcameraapi"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

    <!-- Accessing camera hardware -->
    <uses-feature android:name="android.hardware.camera" />

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="info.androidhive.androidcameraapi.MainActivity"
            android:label="@string/app_name"
            android:configChanges="orientation|keyboard|keyboardHidden"
            android:screenOrientation="landscape">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
3. For demo purpose I have created a simple layout with two Buttons, ImageView andVideoView. Open your layout file of your main activity activity_main.xml and paste the following code.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal"
    android:baselineAligned="false"
    tools:context=".MainActivity" >

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="fill_parent"
        android:layout_weight="1"
        android:gravity="center"
        android:orientation="vertical" >

        <!-- Capture picture button -->
        <Button
            android:id="@+id/btnCapturePicture"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Take a Picture"
            android:layout_marginBottom="10dp"/>

        <!-- Record video button -->
        <Button
            android:id="@+id/btnRecordVideo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Record a Video" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="fill_parent"
        android:layout_weight="1"
        android:orientation="vertical"
        android:padding="10dp">

        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Preview" 
            android:padding="10dp"
            android:textSize="15dp"/>

        <!-- To display picture taken -->
        <ImageView
            android:id="@+id/imgPreview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="gone" />

        <!-- To preview video recorded -->
        <VideoView
            android:id="@+id/videoPreview"
            android:layout_width="wrap_content"
            android:layout_height="400dp"
            android:visibility="gone" />
    </LinearLayout>

</LinearLayout>
4. In MainActivity.java I started with adding code like declaring required variables, referencing the xml UI elements and adding button click listeners.
I kept default location to store images and videos in “Hello Camera” directory which will be created under SD card Pictures/Hello Camera
public class MainActivity extends Activity {

	// Activity request codes
	private static final int CAMERA_CAPTURE_IMAGE_REQUEST_CODE = 100;
	private static final int CAMERA_CAPTURE_VIDEO_REQUEST_CODE = 200;
	public static final int MEDIA_TYPE_IMAGE = 1;
	public static final int MEDIA_TYPE_VIDEO = 2;

	// directory name to store captured images and videos
	private static final String IMAGE_DIRECTORY_NAME = "Hello Camera";

	private Uri fileUri; // file url to store image/video

	private ImageView imgPreview;
	private VideoView videoPreview;
	private Button btnCapturePicture, btnRecordVideo;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		imgPreview = (ImageView) findViewById(R.id.imgPreview);
		videoPreview = (VideoView) findViewById(R.id.videoPreview);
		btnCapturePicture = (Button) findViewById(R.id.btnCapturePicture);
		btnRecordVideo = (Button) findViewById(R.id.btnRecordVideo);

		/**
		 * Capture image button click event
		 * */
		btnCapturePicture.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// capture picture
				captureImage();
			}
		});

		/**
		 * Record video button click event
		 */
		btnRecordVideo.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// record video
				recordVideo();
			}
		});
	}
}

Checking Camera Availability

5. You might think about the scenario if the device does’t have the camera. So before using any camera feature, it is better to check availability of the camera. This can be done in two ways
a. Defining the camera feature in AndroidManifest.xml
By adding android.hardware.camera feature in manifest file, Google Play prevents the app to be installed on devices those doesn’t have camera.
b. Checking in code manually
You can also do a check in the code.
/**
	 * Checking device has camera hardware or not
	 * */
	private boolean isDeviceSupportCamera() {
		if (getApplicationContext().getPackageManager().hasSystemFeature(
				PackageManager.FEATURE_CAMERA)) {
			// this device has a camera
			return true;
		} else {
			// no camera on this device
			return false;
		}
	}

Taking a Picture

6. As we are using android’s inbuilt camera app, launching the camera and taking the picture can done with very few lines of code using the power of Intent.
MediaStore.ACTION_IMAGE_CAPTURE – Requesting camera app to capture image
MediaStore.EXTRA_OUTPUT – Specifying a path where the image has to be stored
captureImage() function will launch the camera to snap a picture.
	 /*
	 * Capturing Camera Image will lauch camera app requrest image capture
	 */
	private void captureImage() {
		Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

		fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);

		intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);

		// start the image capture Intent
		startActivityForResult(intent, CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
	}

7. As we are starting an activity using startActivityForResult(), we can expect some result inonActivityResult() method. Override this method in your activity like below. We also can check whether the user successfully took the picture or cancelled the camera.
	/**
	 * Receiving activity result method will be called after closing the camera
	 * */
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		// if the result is capturing Image
		if (requestCode == CAMERA_CAPTURE_IMAGE_REQUEST_CODE) {
			if (resultCode == RESULT_OK) {
				// successfully captured the image
				// display it in image view
				previewCapturedImage();
			} else if (resultCode == RESULT_CANCELED) {
				// user cancelled Image capture
				Toast.makeText(getApplicationContext(),
						"User cancelled image capture", Toast.LENGTH_SHORT)
						.show();
			} else {
				// failed to capture image
				Toast.makeText(getApplicationContext(),
						"Sorry! Failed to capture image", Toast.LENGTH_SHORT)
						.show();
			}
		}
	}





Displaying Captured Image

As we used inbuilt camera app to capture the picture we won’t get the image in onActivityResult()method. In this case data parameter will be always null. We have to use fileUri to get the file path and display the image
8. onActivityResult() we use CAMERA_CAPTURE_IMAGE_REQUEST_CODE to check whether response came from Image Capture activity or Video Capture acivity. Call previewCapturedImage() in onActivityResult after doing this check.
/*
	 * Display image from a path to ImageView
	 */
	private void previewCapturedImage() {
		try {
			// hide video preview
			videoPreview.setVisibility(View.GONE);

			imgPreview.setVisibility(View.VISIBLE);

			// bimatp factory
			BitmapFactory.Options options = new BitmapFactory.Options();

			// downsizing image as it throws OutOfMemory Exception for larger
			// images
			options.inSampleSize = 8;

			final Bitmap bitmap = BitmapFactory.decodeFile(fileUri.getPath(),
					options);

			imgPreview.setImageBitmap(bitmap);
		} catch (NullPointerException e) {
			e.printStackTrace();
		}
	}





Recording a Video

9. Launching camera to record video is same as capturing image. But instead ofMediaStore.ACTION_IMAGE_CAPTURE we use MediaStore.ACTION_VIDEO_CAPTURE.
Here we also define video quality using MediaStore.EXTRA_VIDEO_QUALITY flag. Keeping this value as 1 records video at high quality with higher file size and keeping 0 records the video at lower quality and lower file size.
Call following function on record video button click event
	 /*
	 * Recording video
	 */
	private void recordVideo() {
		Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);

		fileUri = getOutputMediaFileUri(MEDIA_TYPE_VIDEO);

		// set video quality
		// 1- for high quality video
		intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);

		intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);

		// start the video capture Intent
		startActivityForResult(intent, CAMERA_CAPTURE_VIDEO_REQUEST_CODE);
	}
And in onActivityResult() method check the success of recording.
/**
	 * Receiving activity result method will be called after closing the camera
	 * */
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		// if the result is capturing Image
		if (requestCode == CAMERA_CAPTURE_IMAGE_REQUEST_CODE) {
			// code to check capture image response
		} else if (requestCode == CAMERA_CAPTURE_VIDEO_REQUEST_CODE) {
			if (resultCode == RESULT_OK) {
				// video successfully recorded
				// preview the recorded video
				previewVideo();
			} else if (resultCode == RESULT_CANCELED) {
				// user cancelled recording
				Toast.makeText(getApplicationContext(),
						"User cancelled video recording", Toast.LENGTH_SHORT)
						.show();
			} else {
				// failed to record video
				Toast.makeText(getApplicationContext(),
						"Sorry! Failed to record video", Toast.LENGTH_SHORT)
						.show();
			}
		}
	}

Previewing Recorded Video

10. Following function will play recorded video in VideoView. Call this method in onActivityResult method after checking RESULT_OK for camera response
/*
	 * Previewing recorded video
	 */
	private void previewVideo() {
		try {
			// hide image preview
			imgPreview.setVisibility(View.GONE);

			videoPreview.setVisibility(View.VISIBLE);
			videoPreview.setVideoPath(fileUri.getPath());
			// start playing
			videoPreview.start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

Avoiding NullPointerException after taking camera picture

11. It is known issue that everybody faces a NullPointerException while working with inbuilt camera application. When we launch the camera it actually restarts our activity which causes fileUri to be null. So when we use fileUri to display captured image or recorded video, we will get NullPointerException.
So in order to fix it we have to use onSaveInstanceState() and onRestoreInstanceState() to retain fileUri value. Add following code in MainActivity.java
	/**
	 * Here we store the file url as it will be null after returning from camera
	 * app
	 */
	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);

		// save file url in bundle as it will be null on scren orientation
		// changes
		outState.putParcelable("file_uri", fileUri);
	}

	/*
	 * Here we restore the fileUri again
	 */
	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		super.onRestoreInstanceState(savedInstanceState);

		// get the file url
		fileUri = savedInstanceState.getParcelable("file_uri");
	}

Helper Methods

12. Add following methods in your main activity class. These methods helps in creating and getting files from SD card.
	 /**
	 * Creating file uri to store image/video
	 */
	public Uri getOutputMediaFileUri(int type) {
		return Uri.fromFile(getOutputMediaFile(type));
	}

	/*
	 * returning image / video
	 */
	private static File getOutputMediaFile(int type) {

		// External sdcard location
		File mediaStorageDir = new File(
				Environment
						.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
				IMAGE_DIRECTORY_NAME);

		// Create the storage directory if it does not exist
		if (!mediaStorageDir.exists()) {
			if (!mediaStorageDir.mkdirs()) {
				Log.d(IMAGE_DIRECTORY_NAME, "Oops! Failed create "
						+ IMAGE_DIRECTORY_NAME + " directory");
				return null;
			}
		}

		// Create a media file name
		String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
				Locale.getDefault()).format(new Date());
		File mediaFile;
		if (type == MEDIA_TYPE_IMAGE) {
			mediaFile = new File(mediaStorageDir.getPath() + File.separator
					+ "IMG_" + timeStamp + ".jpg");
		} else if (type == MEDIA_TYPE_VIDEO) {
			mediaFile = new File(mediaStorageDir.getPath() + File.separator
					+ "VID_" + timeStamp + ".mp4");
		} else {
			return null;
		}

		return mediaFile;
	}
It is advisable to use a real device and test the application.

Final Code

Here is the complete code of MainActivity.java
package info.androidhive.androidcameraapi;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import android.widget.VideoView;

public class MainActivity extends Activity {

	// Activity request codes
	private static final int CAMERA_CAPTURE_IMAGE_REQUEST_CODE = 100;
	private static final int CAMERA_CAPTURE_VIDEO_REQUEST_CODE = 200;
	public static final int MEDIA_TYPE_IMAGE = 1;
	public static final int MEDIA_TYPE_VIDEO = 2;

	// directory name to store captured images and videos
	private static final String IMAGE_DIRECTORY_NAME = "Hello Camera";

	private Uri fileUri; // file url to store image/video

	private ImageView imgPreview;
	private VideoView videoPreview;
	private Button btnCapturePicture, btnRecordVideo;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		imgPreview = (ImageView) findViewById(R.id.imgPreview);
		videoPreview = (VideoView) findViewById(R.id.videoPreview);
		btnCapturePicture = (Button) findViewById(R.id.btnCapturePicture);
		btnRecordVideo = (Button) findViewById(R.id.btnRecordVideo);

		/**
		 * Capture image button click event
		 */
		btnCapturePicture.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// capture picture
				captureImage();
			}
		});

		/**
		 * Record video button click event
		 */
		btnRecordVideo.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// record video
				recordVideo();
			}
		});

		// Checking camera availability
		if (!isDeviceSupportCamera()) {
			Toast.makeText(getApplicationContext(),
					"Sorry! Your device doesn't support camera",
					Toast.LENGTH_LONG).show();
			// will close the app if the device does't have camera
			finish();
		}
	}

	/**
	 * Checking device has camera hardware or not
	 * */
	private boolean isDeviceSupportCamera() {
		if (getApplicationContext().getPackageManager().hasSystemFeature(
				PackageManager.FEATURE_CAMERA)) {
			// this device has a camera
			return true;
		} else {
			// no camera on this device
			return false;
		}
	}

	/**
	 * Capturing Camera Image will lauch camera app requrest image capture
	 */
	private void captureImage() {
		Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

		fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);

		intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);

		// start the image capture Intent
		startActivityForResult(intent, CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
	}

	/**
	 * Here we store the file url as it will be null after returning from camera
	 * app
	 */
	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);

		// save file url in bundle as it will be null on scren orientation
		// changes
		outState.putParcelable("file_uri", fileUri);
	}

	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		super.onRestoreInstanceState(savedInstanceState);

		// get the file url
		fileUri = savedInstanceState.getParcelable("file_uri");
	}

	/**
	 * Recording video
	 */
	private void recordVideo() {
		Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);

		fileUri = getOutputMediaFileUri(MEDIA_TYPE_VIDEO);

		// set video quality
		intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);

		intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file
															// name

		// start the video capture Intent
		startActivityForResult(intent, CAMERA_CAPTURE_VIDEO_REQUEST_CODE);
	}

	/**
	 * Receiving activity result method will be called after closing the camera
	 * */
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		// if the result is capturing Image
		if (requestCode == CAMERA_CAPTURE_IMAGE_REQUEST_CODE) {
			if (resultCode == RESULT_OK) {
				// successfully captured the image
				// display it in image view
				previewCapturedImage();
			} else if (resultCode == RESULT_CANCELED) {
				// user cancelled Image capture
				Toast.makeText(getApplicationContext(),
						"User cancelled image capture", Toast.LENGTH_SHORT)
						.show();
			} else {
				// failed to capture image
				Toast.makeText(getApplicationContext(),
						"Sorry! Failed to capture image", Toast.LENGTH_SHORT)
						.show();
			}
		} else if (requestCode == CAMERA_CAPTURE_VIDEO_REQUEST_CODE) {
			if (resultCode == RESULT_OK) {
				// video successfully recorded
				// preview the recorded video
				previewVideo();
			} else if (resultCode == RESULT_CANCELED) {
				// user cancelled recording
				Toast.makeText(getApplicationContext(),
						"User cancelled video recording", Toast.LENGTH_SHORT)
						.show();
			} else {
				// failed to record video
				Toast.makeText(getApplicationContext(),
						"Sorry! Failed to record video", Toast.LENGTH_SHORT)
						.show();
			}
		}
	}

	/**
	 * Display image from a path to ImageView
	 */
	private void previewCapturedImage() {
		try {
			// hide video preview
			videoPreview.setVisibility(View.GONE);

			imgPreview.setVisibility(View.VISIBLE);

			// bimatp factory
			BitmapFactory.Options options = new BitmapFactory.Options();

			// downsizing image as it throws OutOfMemory Exception for larger
			// images
			options.inSampleSize = 8;

			final Bitmap bitmap = BitmapFactory.decodeFile(fileUri.getPath(),
					options);

			imgPreview.setImageBitmap(bitmap);
		} catch (NullPointerException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Previewing recorded video
	 */
	private void previewVideo() {
		try {
			// hide image preview
			imgPreview.setVisibility(View.GONE);

			videoPreview.setVisibility(View.VISIBLE);
			videoPreview.setVideoPath(fileUri.getPath());
			// start playing
			videoPreview.start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * ------------ Helper Methods ---------------------- 
	 * */

	/**
	 * Creating file uri to store image/video
	 */
	public Uri getOutputMediaFileUri(int type) {
		return Uri.fromFile(getOutputMediaFile(type));
	}

	/**
	 * returning image / video
	 */
	private static File getOutputMediaFile(int type) {

		// External sdcard location
		File mediaStorageDir = new File(
				Environment
						.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
				IMAGE_DIRECTORY_NAME);

		// Create the storage directory if it does not exist
		if (!mediaStorageDir.exists()) {
			if (!mediaStorageDir.mkdirs()) {
				Log.d(IMAGE_DIRECTORY_NAME, "Oops! Failed create "
						+ IMAGE_DIRECTORY_NAME + " directory");
				return null;
			}
		}

		// Create a media file name
		String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
				Locale.getDefault()).format(new Date());
		File mediaFile;
		if (type == MEDIA_TYPE_IMAGE) {
			mediaFile = new File(mediaStorageDir.getPath() + File.separator
					+ "IMG_" + timeStamp + ".jpg");
		} else if (type == MEDIA_TYPE_VIDEO) {
			mediaFile = new File(mediaStorageDir.getPath() + File.separator
					+ "VID_" + timeStamp + ".mp4");
		} else {
			return null;
		}

		return mediaFile;
	}
}
 




Monday, September 23, 2013

Face Detection example in andoid from Gallery and by Camera capure image

Hello Every one ,

I recently learn face detection  in android by searching in google and other blogger i found below code and i have made some change in it .

Hope you will like my code and also shared your information in image processing and your expose in face detection in android.


Below is my android Activity code :



public class FaceDetectActivity extends Activity  implements OnClickListener{

        private static final int TAKE_PICTURE_CODE = 100;
        private static final int MAX_FACES = 5;
        
        private static final int SELECT_PICTURE = 6;
       
        private Bitmap cameraBitmap = null;
        private Button btn_TakePhoto;
       
        private Button btn_select_image;
       
        private Button btn_facedetect;
        
        private ImageView imageView;
       
        private int mWidth;
        private int mHeight;
       
        private ProgressDialog mProgressDialog;
       
        private Button btn_select_img;
       
      
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_face_detect);
       
        initDisplay();
       
        btn_TakePhoto=(Button)findViewById(R.id.take_picture);
        btn_TakePhoto.setOnClickListener(this);
        btn_select_img=(Button)findViewById(R.id.btn_select_gallary);
        btn_select_img.setOnClickListener(this);
       
       
       
    }


   
   
    private void initDisplay(){
       
        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);

        mHeight=metrics.heightPixels;
        mWidth=metrics.widthPixels;
       
        Log.v("LOG_TAG", "Wdith is "+ mWidth +"Height is "+ mHeight);
    }
   
   
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.face_detect, menu);
        return true;
    }

   
   
    private void openCamera(){
        Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
        
        startActivityForResult(intent, TAKE_PICTURE_CODE);
    }
    
    private void processCameraImage(Intent intent){
        setContentView(R.layout.face_detect_layout);
        
        btn_facedetect=(Button)findViewById(R.id.detect_face);
        btn_facedetect.setOnClickListener(this);
        
       
       
        btn_select_image=(Button)findViewById(R.id.btn_pickimag);
       
        btn_select_image.setOnClickListener(this);
       
       
        imageView= (ImageView)findViewById(R.id.image_view);
        
        cameraBitmap = (Bitmap)intent.getExtras().get("data");
        
        imageView.setImageBitmap(cameraBitmap);
    }

    @Override
    public void onClick(View v) {
       
        switch(v.getId()){
       
        case R.id.take_picture:
           
            openCamera();
            break;
           
        case R.id.detect_face:
           
            //detectFaces();
           
            new FaceDetectAsyncTask().execute(cameraBitmap);
           
            break;
           
        case R.id.btn_pickimag:
           
            startImagePicker();
           
            break;
       
           
        case R.id.btn_select_gallary:
           
            startImagePicker();
           
            break;
       
        }
       
    }
   
   
   
    private Object[] detectFaces(Bitmap mBitmap){
      
        Object[] mObject = new Object[2];
       
        if(null != mBitmap){
               
               int width = mBitmap.getWidth();
                int height = mBitmap.getHeight();
                
                FaceDetector detector = new FaceDetector(width, height,FaceDetectActivity.MAX_FACES);
                Face[] faces = new Face[FaceDetectActivity.MAX_FACES];
                
                Bitmap bitmap565 = Bitmap.createBitmap(width, height, Config.RGB_565);
                Paint ditherPaint = new Paint();
                Paint drawPaint = new Paint();
                
                ditherPaint.setDither(true);
                drawPaint.setColor(Color.GREEN);
                drawPaint.setStyle(Paint.Style.STROKE);
                drawPaint.setStrokeWidth(2);
                
                Canvas canvas = new Canvas();
                canvas.setBitmap(bitmap565);
                canvas.drawBitmap(mBitmap, 0, 0, ditherPaint);
                
                int facesFound = detector.findFaces(bitmap565, faces);
                PointF midPoint = new PointF();
                float eyeDistance = 0.0f;
                float confidence = 0.0f;
                
                Log.i("FaceDetector", "Number of faces found: " + facesFound);
                
                if(facesFound > 0)
                {
                        for(int index=0; index<facesFound; ++index){
                                faces[index].getMidPoint(midPoint);
                                eyeDistance = faces[index].eyesDistance();
                                confidence = faces[index].confidence();
                                
                                Log.i("FaceDetector",
                                                "Confidence: " + confidence +
                                                ", Eye distance: " + eyeDistance +
                                                ", Mid Point: (" + midPoint.x + ", " + midPoint.y + ")");
                                
                                canvas.drawRect((int)midPoint.x - eyeDistance ,
                                                                (int)midPoint.y - eyeDistance ,
                                                                (int)midPoint.x + eyeDistance,
                                                                (int)midPoint.y + eyeDistance, drawPaint);
                        }
                }else{
                    //Toast.makeText(this, "No Face Detect", Toast.LENGTH_SHORT).show();
                }
                
                /*String filepath = Environment.getExternalStorageDirectory() + "/facedetect" + System.currentTimeMillis() + ".jpg";
                
                        try {
                                FileOutputStream fos = new FileOutputStream(filepath);
                                
                                bitmap565.compress(CompressFormat.JPEG, 90, fos);
                                
                                fos.flush();
                                fos.close();
                        } catch (FileNotFoundException e) {
                                e.printStackTrace();
                        } catch (IOException e) {
                                e.printStackTrace();
                        }*/
                        
                       /* ImageView imageView = (ImageView)findViewById(R.id.image_view);
                        
                        imageView.setImageBitmap(bitmap565);*/
               
                mObject[0]=facesFound;
                mObject[1]=bitmap565;
               
                        return mObject;
        }
       
        return mObject;
    }
   
   
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
    
            if(TAKE_PICTURE_CODE == requestCode){
                   
                if(Activity.RESULT_OK==resultCode){
                    processCameraImage(data);
                }else{
                    Toast.makeText(this, "You have not capture Image", Toast.LENGTH_SHORT).show();
                   
                     setContentView(R.layout.face_detect_layout);
                    
                        btn_facedetect=(Button)findViewById(R.id.detect_face);
                        btn_facedetect.setOnClickListener(this);
                        
                       
                       
                        btn_select_image=(Button)findViewById(R.id.btn_pickimag);
                       
                        btn_select_image.setOnClickListener(this);
                       
                       
                        imageView= (ImageView)findViewById(R.id.image_view);
                }
               
            }else if(SELECT_PICTURE==requestCode){
               
               
                if(Activity.RESULT_OK==resultCode){
                   
                    Uri selectedImageUri = data.getData();
                    String selectedImagePath = getPath(selectedImageUri);
                   
                   
                    setContentView(R.layout.face_detect_layout);
                   
                    btn_facedetect=(Button)findViewById(R.id.detect_face);
                    btn_facedetect.setOnClickListener(this);
                    
                   
                   
                    btn_select_image=(Button)findViewById(R.id.btn_pickimag);
                   
                    btn_select_image.setOnClickListener(this);
                   
                   
                    imageView= (ImageView)findViewById(R.id.image_view);
                   
                    updateImageFromGallary(selectedImagePath);
                   
                   
                   
                   
                   
                }else{
                   
                }
               
            }
           
           
    }
   
   
    private void updateImageFromGallary(String imgPath){
       
        try{
           
            cameraBitmap=null;
           
            //cameraBitmap=BitmapFactory.decodeFile(imgPath);
           
            cameraBitmap=decodeSampledBitmapFromResource(getResources(),imgPath,mWidth,mHeight);
           
            imageView.setImageBitmap(cameraBitmap);
           
            Toast.makeText(this, "Press Face detect for Face Detection", Toast.LENGTH_SHORT).show();
           
        }catch(OutOfMemoryError outMemeoryError){
           
            Toast.makeText(this, "Unable to Load Image", Toast.LENGTH_SHORT).show();
           
        }
       
       
       
       
    }
   
   
    private void startImagePicker(){
       
        // in onCreate or any event where your want the user to
        // select a file
        /*Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);*/
        Intent intent = new Intent(Intent.ACTION_PICK,
                   android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
       
        startActivityForResult(Intent.createChooser(intent,
                "Select Picture"), SELECT_PICTURE);
       
    }
   
   
    public String getPath(Uri uri) {
       
       
       
         Uri selectedImage = uri;
         String[] filePathColumn = {MediaStore.Images.Media.DATA};

         Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
        
         cursor.moveToFirst();

         int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
         String filePath = cursor.getString(columnIndex);
       
         return filePath;
       
       /* String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = managedQuery(uri, projection, null, null, null);
        int column_index = cursor
                .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);*/
    }
   
   
    public static int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        // Calculate ratios of height and width to requested height and width
        final int heightRatio = Math.round((float) height / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);

        // Choose the smallest ratio as inSampleSize value, this will guarantee
        // a final image with both dimensions larger than or equal to the
        // requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }

    return inSampleSize;
}
   
   
    public static Bitmap decodeSampledBitmapFromResource(Resources res, String path,
            int reqWidth, int reqHeight) {

        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
       // BitmapFactory.decodeResource(res, resId, options);
       // BitmapFactory.decodeFile(path);
       
        BitmapFactory.decodeFile(path, options);
        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
       //return BitmapFactory.decodeResource(res, resId, options);
       
        return  BitmapFactory.decodeFile(path, options);
    }
   
   
   
    public class FaceDetectAsyncTask extends AsyncTask<Bitmap, Void, Object[]>{

       
       
        @Override
        protected void onPostExecute(Object[] result) {
            // TODO Auto-generated method stub
            super.onPostExecute(result);
           
           
           
            dismissProgressDialog();
           
            if(result!=null){
               
                if(result[0]!=null){
                   
                    int faceDetect=(Integer) result[0];
                    if(faceDetect>0){
                       
                        ImageView imageView = (ImageView)findViewById(R.id.image_view);
                        
                        imageView.setImageBitmap((Bitmap) result[1]);
                    }else{
                        Toast.makeText(FaceDetectActivity.this, "No Face Detect", Toast.LENGTH_SHORT).show();
                    }
                }else{
                    Toast.makeText(FaceDetectActivity.this, "No Face Detect", Toast.LENGTH_SHORT).show();
                }
               
               
            }
           
           
           
           
           
        }

        /*@Override
        protected void onPostExecute(Bitmap result) {
            // TODO Auto-generated method stub
            super.onPostExecute(result);
           
             dismissProgressDialog();
           
             ImageView imageView = (ImageView)findViewById(R.id.image_view);
            
             imageView.setImageBitmap(result);
            
           
        }
*/
        @Override
        protected void onPreExecute() {
           
            super.onPreExecute();
           
            showProgressDialog();
        }

        @Override
        protected Object[] doInBackground(Bitmap... params) {
            // TODO Auto-generated method stub
           
            Bitmap mBitmap=params[0];
            Object [] mObjArray;
           
            mObjArray=detectFaces(mBitmap);
           
            return mObjArray;
        }

       
    }
   
   
    private void showProgressDialog(){
       
        if(mProgressDialog!=null && mProgressDialog.isShowing()){
            return ;
        }else{
            mProgressDialog=new ProgressDialog(this);
           
            mProgressDialog.setTitle("Please wait...");
           
            mProgressDialog.setMessage("Detecting face from image");
           
            mProgressDialog.setCancelable(false);
           
            mProgressDialog.show();
        }
    }
   
    private void dismissProgressDialog(){
   
        if(mProgressDialog!=null && mProgressDialog.isShowing()){
            mProgressDialog.dismiss();
            mProgressDialog=null;
        }
    }
   
   
}


Here are my layout files  code:

activity_face_detection.xml


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".FaceDetectActivity"
    android:gravity="center"
     >

     <!-- <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/app_info"
        android:gravity="center_horizontal"
        android:layout_weight="1.0"
        android:id="@+id/txt_appinfo"
        /> -->
        
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/take_picture"
        android:layout_margin="5dip"
        android:text="@string/take_picture"
        android:layout_gravity="center_horizontal"
        android:layout_centerHorizontal="true"
       
       
        />
   
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn_select_gallary"
        android:layout_margin="5dip"
        android:text="@string/select_image_from_gallary"
        android:layout_gravity="center_horizontal"
        android:layout_centerHorizontal="true"
        android:layout_below="@+id/take_picture"
        />

</RelativeLayout>

face_detect_layout.xml



<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/image_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1.0"
         />
   
   
   
   
    <LinearLayout
       
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
         >
       
         <Button
        android:id="@+id/detect_face"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
       
        android:text="@string/detect_face"
        android:layout_gravity="center_vertical"
         />
        
          <Button
        android:id="@+id/btn_pickimag"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
       android:layout_gravity="center_vertical"
        android:text="@string/select_image_from_gallary" />
       
    </LinearLayout>
</LinearLayout>