Friday, 28 June 2013

Get images from Camera using FileContentProvider in Android

Today I am posting a tutorial for save the captured image to application's local directory. Suppose you are developing an application in which you are capturing an Image and uploading that image to the server. For this normally you will save the captured image to sd-card and then you will upload that image to the server and this is fine. Now assume that in your device there is no sd-card present. ohh no, Your application will not work.

Do not worry there are two ways to solve this problem.
1. You can get the bitmap from the onActivityResult if you start the camera  activity using       ACTION_IMAGE-CAPTURE.

2. Using content provider you can save the image to the phone's internal memory(File directory of your application) from the camera activity.

here is the sample code for camera.

main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/RelativeLayout1"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/button1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:text="Capture" />

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button1"
        android:layout_centerHorizontal="true" />


</RelativeLayout>

MyFileContentProvider.Class
import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;


public class MyFileContentProvider extends ContentProvider
{
       public static final Uri CONTENT_URI = Uri.parse("content://com.example.camerademo/");
       private static final HashMap<String, String> MIME_TYPES = new HashMap<String, String>();
       static
       {
              MIME_TYPES.put(".jpg""image/jpeg");
              MIME_TYPES.put(".jpeg""image/jpeg");
       }

       @Override

       public boolean onCreate()
       {
              try
              {
                     File mFile = new File(getContext().getFilesDir(), "newImage.jpg");
                     if(!mFile.exists())
                     {
                           mFile.createNewFile();
                     }
                     getContext().getContentResolver().notifyChange(CONTENT_URInull);
                     return (true);

              }
              catch (Exception e)
              {
                     e.printStackTrace();
                     return false;
              }

       }

       @Override

       public String getType(Uri uri)
       {
              String path = uri.toString();
              for (String extension : MIME_TYPES.keySet())
              {

                     if (path.endsWith(extension))
                     {
                           return (MIME_TYPES.get(extension));
                     }
              }

              return (null);
       }

       @Override

       public ParcelFileDescriptor openFile(Uri uri, String mode)throwsFileNotFoundException
       {

              File f = new File(getContext().getFilesDir(), "newImage.jpg");

              if (f.exists())
              {
                     return(ParcelFileDescriptor.open(f,ParcelFileDescriptor.MODE_READ_WRITE));
              }
              throw new FileNotFoundException(uri.getPath());
       }

       @Override

       public Cursor query(Uri url, String[] projection, String selection,String[] selectionArgs, String sort)
       {
              throw new RuntimeException("Operation not supported");
       }

       @Override

       public Uri insert(Uri uri, ContentValues initialValues)
       {
              throw new RuntimeException("Operation not supported");
       }

       @Override

       public int update(Uri uri, ContentValues values, String where,String[] whereArgs)
       {
              throw new RuntimeException("Operation not supported");
       }

       @Override

       public int delete(Uri uri, String where, String[] whereArgs)
       {
              throw new RuntimeException("Operation not supported");
       }

}

 MainActivity.Class:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener
{
       private final int CAMERA_RESULT = 1;
       private final String Tag = getClass().getName();
       Button button1;
       ImageView imageView1;

       @Override

       protected void onDestroy()
       {
              super.onDestroy();
              imageView1 = null;

       }
       @Override

       public void onCreate(Bundle savedInstanceState)
       {

              super.onCreate(savedInstanceState);
              setContentView(R.layout.main);

              button1 = (Button)findViewById(R.id.button1);
              imageView1 = (ImageView)findViewById(R.id.imageView1);
              button1.setOnClickListener(this);

       }

       public void onClick(View v)
       {
              PackageManager pm = getPackageManager();
              if (pm.hasSystemFeature(PackageManager.FEATURE_CAMERA))
              {
                     Intent i = newIntent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                     i.putExtra(MediaStore.EXTRA_OUTPUT, MyFileContentProvider.CONTENT_URI);
                     startActivityForResult(i, CAMERA_RESULT);
              }
              else
              {
                     Toast.makeText(getBaseContext(), "Camera is not available", Toast.LENGTH_LONG).show();
              }
       }



       @Override

       protected void onActivityResult(int requestCode, int resultCode, Intent data)
       {

              super.onActivityResult(requestCode, resultCode, data);

              Log.i(Tag"Receive the camera result");

              if (resultCode == RESULT_OK && requestCode == CAMERA_RESULT)
              {
                     Bitmap correctBmp=null;
                     File out = new File(getFilesDir(), "newImage.jpg");

                     if(!out.exists())
                     {
                           Toast.makeText(getBaseContext(),"Error while capturing image", Toast.LENGTH_LONG).show();
                           return;
                     }
                     //Bitmap bmp = BitmapFactory.decodeFile(out.getAbsolutePath());

                     try
                     {
                           File f = new File(out.getAbsolutePath());
                           ExifInterface exif = new ExifInterface(f.getPath());
                           int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);

                           int angle = 0;

                           if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
                                  angle = 90;
                           }
                           else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
                                  angle = 180;
                           }
                           else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
                                  angle = 270;
                           }

                           Matrix mat = new Matrix();
                           mat.postRotate(angle);

                           Bitmap bmp1 = BitmapFactory.decodeStream(newFileInputStream(f), nullnull);
                           correctBmp = Bitmap.createBitmap(bmp1, 0, 0, bmp1.getWidth(), bmp1.getHeight(), mat, true);                
                     }
                     catch (IOException e) {
                           Log.w("TAG""-- Error in setting image");
                     }  
                     catch(OutOfMemoryError oom) {
                           Log.w("TAG""-- OOM Error in setting image");
                     }
                     imageView1.setImageBitmap(correctBmp);

              }

       }

}

AndroidManifest.xml

here is the some property which need to set in AndroidManifest file.
  <uses-feature
        android:name="android.hardware.camera"
        android:required="false" />

    <uses-permission android:name="android.permission.CAMERA" />
<application
        <provider
            android:name=".MyFileContentProvider"
            android:authorities="com.example.camerademo"
            android:enabled="true"
            android:exported="true" />
    </application>

i will be happy if you will provide your feedback or follow this blog. Any suggestion and help will be appreciated.
Thank you :)