Click here to Skip to main content
15,112,232 members
Articles / Mobile Apps / Android
Technical Blog
Posted 2 Dec 2014

Tagged as

Stats

29.6K views
17 bookmarked

Using Camera in Android Application

Rate me:
Please Sign up or sign in to vote.
4.64/5 (12 votes)
2 Dec 2014CPOL4 min read
How to use camera in Android application

In this post, we will take a look at how to integrate camera with our Android application. Android provides you with 2 options while working with Camera:

  1. Use an existing Camera application
  2. Work with Camera hardware API directly

If you are developing a full fledged camera application, then you need to work with the Camera API directly as it gives you more control but it involves a lot more coding. If you just want to integrate the camera with your app, the first option is better and simpler. In this tutorial, we will learn how to use an existing camera app with our application. We will create a simple application that will take pictures and display the same in a ListView. The application will display a Camera button, clicking which will open the existing camera app present on the device. Once the user takes a picture, he will be redirected back to our application and the picture that he has taken will be displayed in a listview and it will be saved to a permanent location.

Getting Started

I am using Eclipse for development, however the steps will be similar for other software as well.

Open Eclipse -> Create a New Android Application project called “CameraAppDemo” with the options as selected below and leave the rest of the options as default.

Note: I am currently using Android API 19 but you can target the latest version if you have that installed.

Since we will be displaying the result in a listview, we will add a listview to the activity_main.xml file in the layout folder.

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="com.example.cameraappdemo.MainActivity" >

<ListView
android:id="@+id/android:list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" >

</ListView>

</RelativeLayout>

Since our main layout contains a listview, it is better to extend our MainActivity class from “ListActivity” instead of Activity as it will be simpler to handle listview events.

Java
public class MainActivity extends ListActivity {

To take a picture, we will display the camera icon in the ActionBar. Modify the main.xml file in the res/menu directory as shown below:

XML
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.dailyselfieapp.MainActivity" >

<item
android:id="@+id/action_camera"
android:orderInCategory="100"
android:showAsAction="ifRoom"
android:icon="@drawable/ic_action_camera"
android:title="@string/action_settings"/>

</menu>

You can find the “ic_action_camera” icon inside the drawable folders in the attached solution. On click of the Camera button, the following functions are called:

Java
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_camera) {
startCapture();
return true;
}
return super.onOptionsItemSelected(item);
}

private void startCapture() {

Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
if (cameraIntent.resolveActivity(getPackageManager()) != null) {

File photoFile = null;
try {
photoFile = CreateImageFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

if(photoFile != null)
{
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
startActivityForResult(cameraIntent, CAMERA_CAPTURE);
}
}
}

private File CreateImageFile() throws IOException
{
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "Image_" + timeStamp + "_";

File storageDirectory = getExternalFilesDir("");
File image = File.createTempFile(imageFileName, ".jpg",storageDirectory);
return image;

}

On click of camera button, we call the “StartCapture” function which defines an intent with “android.provider.MediaStore.ACTION_IMAGE_CAPTURE” which specifies that we want to capture an image. This will start the default camera application present on the device.

In the “CreateImageFile()” function, we create an image file which will store the actual image which has been captured. In that method, we first create a file name using the current timestamp. We then specify the directory using the “getExternalFilesDir()“. This method returns a directory which is private to our app. If you want to store the images in the public images directory, you can use the “Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);” method.

We then pass this extra information along with the intent using “cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));“. This will save the captured image in the following path which we have passed. We then start the activity passing the Intent using “startActivityForResult(cameraIntent, CAMERA_CAPTURE);” . The “CAMERA_CAPTURE” is an integer value which I have used which can be any value.

This will start the camera application. Once you capture an image and confirm, the code will return back to the application and we will handle it in the onActivityResult() method as shown below:

Java
@Override
public void onActivityResult(final int requestCode, int resultCode, Intent data) {

switch(requestCode)
{
case CAMERA_CAPTURE:
if(resultCode == RESULT_OK)
{
DisplayImages();
}
break;
}

}

private void DisplayImages() {
// TODO Auto-generated method stub
File myPath = getExternalFilesDir(null);
listOfImages = new ArrayList<String>();

try
{

for(File f: myPath.listFiles()) {
listOfImages.add(f.getAbsolutePath());
}

MyCustomAdapter adapter = new MyCustomAdapter(MainActivity.this,listOfImages);
setListAdapter(adapter);
}
catch(Exception ex)
{
Log.w("Error", ex.getMessage());
}
} 

In the function, we check for requestCode and then check if the resultCode is OK. If that is the case, we then call the DisplayImages() function which displays all the captured images in the ListView.

In the “DisplayImages()” function, we again get the path to the storage directory, iterate through the directory and add the AbsolutePath() of all the images in an Arraylist. We then pass that to the CustomAdapter which we have created.

Here is the code for out CustomAdapter layout file.

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="horizontal" >

<ImageView
android:id="@+id/selfie"
android:layout_width="60dp"
android:layout_height="60dp"
android:padding="5dp" />

<LinearLayout android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">

<TextView
android:id="@+id/fileName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:padding="2dp"
android:textColor="#33CC33" />

</LinearLayout>
</LinearLayout>

We are using the above layout in our custom adapter for displaying the image along with the file name.

XML
package com.example.cameraappdemo;

import java.io.File;
import java.util.ArrayList;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class MyCustomAdapter extends ArrayAdapter<String> {

    private final Activity context;

    private final ArrayList<String> listOfImages;

    public MyCustomAdapter(Activity context, ArrayList<String> listOfImages) {
        super(context, R.layout.mylist, listOfImages);
        // TODO Auto-generated constructor stub

        this.context=context;
        this.listOfImages = listOfImages;
    }

    public View getView(int position,View view,ViewGroup parent) {

        ViewHolder holder;

        if(view == null)
        {        
        LayoutInflater inflater=context.getLayoutInflater();
        view =inflater.inflate(R.layout.mylist, null,true);

        holder = new ViewHolder();
        holder.imageView = (ImageView) view.findViewById(R.id.selfie);
        holder.txtTitle = (TextView) view.findViewById(R.id.fileName);
        view.setTag(holder);
        }
        else
        {
            holder = (ViewHolder) view.getTag();
        }

        Bitmap bitmap = BitmapFactory.decodeFile(listOfImages.get(position));        
        File f = new File(listOfImages.get(position));    

        holder.txtTitle.setText(f.getName());
        holder.imageView.setImageBitmap(bitmap);

        return view;
    };
}

 class ViewHolder {
     TextView txtTitle;
     ImageView imageView;
}

In the adapter, we are passing an ArrayList containing the path of all the files. In the “GetView()” method, we read the Bitmap from the file location and then display the same in the imageview along with the name of the file.

Now let's write some code that will display the selected image in a popup window when clicking on any image in the main ListView. Let's create a custom Dialog for the same. Add a new layout file in the res/layout called “cust_dialog.xml“. This will be the layout of our Dialog, the code for which is shown below:

XML
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="5dp" />

     <Button
        android:id="@+id/dialogButtonOK"
        android:layout_width="100px"
        android:layout_height="wrap_content"
        android:text=" Close "
        android:layout_marginTop="5dp"
        android:layout_marginRight="5dp"
        android:layout_below="@+id/image"

        />

</RelativeLayout>

Our custom layout contains an imageview displaying the selected image and a button which will close the dialog.

We will now handle the ListItem Click event in our MainActivity as shown below:

Java
@Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        // TODO Auto-generated method stub
        super.onListItemClick(l, v, position, id);

        // custom dialog
                    final Dialog dialog = new Dialog(MainActivity.this);
                    dialog.setContentView(R.layout.cust_dialog);
                    dialog.setTitle("Image ");

                    Bitmap bitmap = BitmapFactory.decodeFile(listOfImages.get(position));

                    // set the custom dialog components - text, image and button
                    ImageView image = (ImageView) dialog.findViewById(R.id.image);
                    image.setImageBitmap(bitmap);

                    Button dialogButton = (Button) dialog.findViewById(R.id.dialogButtonOK);
                    // if button is clicked, close the custom dialog

                    dialogButton.setOnClickListener(new View.OnClickListener() {

                        @Override
                        public void onClick(View arg0) {

                            dialog.dismiss();

                        }
                    });

                    dialog.show();    
    }

In the above code, the position will gives us the position of the element which was clicked. We get the absolute path of the selected image from our ‘listOfImagesarraylist. We then create the dialog from our custom layout and assign the image in the same.

Below is our complete MainActivity.java code:

Java
package com.example.cameraappdemo;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import android.app.Dialog;
import android.app.ListActivity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;

public class MainActivity extends ListActivity {

    private static final int CAMERA_CAPTURE = 20;
    ArrayList<String> listOfImages;

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

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_camera) {
            startCapture();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    private void startCapture() {

        Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);        
         if (cameraIntent.resolveActivity(getPackageManager()) != null) {

             File photoFile = null;
                try {
                     photoFile = CreateImageFile();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                if(photoFile != null)
                {
                    cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
                    startActivityForResult(cameraIntent, CAMERA_CAPTURE);                                    
                }                
            }        
    }

    private File CreateImageFile() throws IOException
    {
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "Image_" + timeStamp + "_";

        File storageDirectory = getExternalFilesDir("");    
        File image = File.createTempFile(imageFileName, ".jpg",storageDirectory);        
        return image;
    }

    @Override
    public void onActivityResult(final int requestCode, int resultCode, Intent data) {

        switch(requestCode)
        {
        case CAMERA_CAPTURE:
            if(resultCode == RESULT_OK)
            {
                DisplayImages();                
            }
            break;
        }
    }

    private void DisplayImages() {
        // TODO Auto-generated method stub
        File myPath = getExternalFilesDir(null);
        listOfImages = new ArrayList<String>();

         try
         {

        for(File f: myPath.listFiles()) {
            listOfImages.add(f.getAbsolutePath());
        }

        MyCustomAdapter adapter = new MyCustomAdapter(MainActivity.this,listOfImages);
        setListAdapter(adapter);
         }
         catch(Exception ex)
         {
             Log.w("Error", ex.getMessage());
         }
    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        // TODO Auto-generated method stub
        super.onListItemClick(l, v, position, id);

        // custom dialog
                    final Dialog dialog = new Dialog(MainActivity.this);
                    dialog.setContentView(R.layout.cust_dialog);
                    dialog.setTitle("Image ");

                    Bitmap bitmap = BitmapFactory.decodeFile(listOfImages.get(position));

                    // set the custom dialog components - text, image and button
                    ImageView image = (ImageView) dialog.findViewById(R.id.image);
                    image.setImageBitmap(bitmap);

                    Button dialogButton = (Button) dialog.findViewById(R.id.dialogButtonOK);
                    // if button is clicked, close the custom dialog

                    dialogButton.setOnClickListener(new View.OnClickListener() {

                        @Override
                        public void onClick(View arg0) {

                            dialog.dismiss();

                        }
                    });

                    dialog.show();    
    }

}

Below is the screenshot of how our application will behave when running on emulator:

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Madhur Kapoor
Technical Lead Infosys
India India
Madhur is Technology Lead by profession having around 9+ yrs of experience in IT industry working on Microsoft Technologies. Apart from Microsoft Technologies, he also likes to work on Mobile Development in Android.

His Technical expertise include .Net technologies including MVC, WebAPI, Azure.

Apart from coding, he like to play Xbox Games, strum guitar or read books.

My Blog : http://www.codingparadox.com

Comments and Discussions

 
QuestionConvert from Eclipse to Android Developer Pin
charles9227-Aug-15 21:04
Membercharles9227-Aug-15 21:04 
This looks like a really interesting program. Thanks for posting it. I opened the project in Android Developer Studio (ADS) 1.2.2 and it builds OK, but I am unable to download it to my Samsung Android phone. I've been able to download other Android apps from ADS. Could someone post this project as an ADS project or explain what has to be done to enable running and debugging on an actual device? thanks
AnswerRe: Convert from Eclipse to Android Developer Pin
charles9227-Aug-15 21:27
Membercharles9227-Aug-15 21:27 
QuestionImage Size and Memory Allocation Pin
Larry M025-Dec-14 9:54
MemberLarry M025-Dec-14 9:54 
AnswerRe: Image Size and Memory Allocation Pin
Madhur Kapoor6-Dec-14 1:35
MemberMadhur Kapoor6-Dec-14 1:35 
GeneralRe: Image Size and Memory Allocation Pin
Larry M0216-Dec-14 11:15
MemberLarry M0216-Dec-14 11:15 
QuestionNeeds formatting Pin
Richard MacCutchan4-Dec-14 3:33
mveRichard MacCutchan4-Dec-14 3:33 
AnswerRe: Needs formatting Pin
Member 1133542425-Dec-14 20:39
MemberMember 1133542425-Dec-14 20:39 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.