Thursday, 19 April 2012

Save captured image to application's local file directory.

This post is little old and I would not advise to use this solution instead you should use android.support.v4.content.FileProvider of  Support v4 library.

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 :P.

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.
1. The first solution is very easy. start the camera activity using this code


Intent cameraIntent=new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(cameraIntent, CAMERA_REQUEST);

After capturing image you will get the result in the ActivtyResult.


 if (requestCode == CAMERA_REQUEST) {             Bitmap photo = (Bitmap) data.getExtras().get("data");  }

Note:: This first solution is working fine but the bitmap you are getting in onActivityResult() is of low resolution. If you want high resolution image then you should prefer a second solution.

2. Second solution is little bit long but it is very important.

In this case you will have to create a content provider which will use to share your local (Application's internal) file to the camera activity.

Here I am sharing my demo application for content provider to share the local file to camera activity.

Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.camera"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk android:minSdkVersion="7" />
    <uses-feature
        android:name="android.hardware.camera"
        android:required="false" />
    <uses-permission android:name="android.permission.CAMERA" />
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".Home"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <provider
            android:name=".MyFileContentProvider"
            android:authorities="com.example.camerademo"
            android:enabled="true"
            android:exported="true" />
    </application>
</manifest>

Layout file 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="Button" />
    <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>

Content provider class


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_URI, null);
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)
throws FileNotFoundException {
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");
}

Activity class Home.java


public class Home extends Activity implements OnClickListener{
    /** Called when the activity is first created. */
private final int CAMERA_RESULT = 1;
private final String Tag = getClass().getName();
Button button1;
ImageView imageView1;
    @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 = new Intent(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) {
File out = new File(getFilesDir(), "newImage.jpg");
if(!out.exists()) {
Toast.makeText(getBaseContext(),
"Error while capturing image", Toast.LENGTH_LONG)
.show();
return;
}
Bitmap mBitmap = BitmapFactory.decodeFile(out.getAbsolutePath());
imageView1.setImageBitmap(mBitmap);
}
}
 
@Override
protected void onDestroy() {
super.onDestroy();
imageView1 = null;
}

In this tutorial  if you find any mistake then please comment me to correct it. Hope it will helpful to you.
Enjoy coding :)

Note :: Test this is real device. In emulator possible it not work.

36 comments:

  1. WHOOOP WHOOOP!!!!! DUDE THANK YOU SOOOOO MUCH!!!!

    I'VE BEEN THROUGH EVERY POST ON GOOGLE, NOTHING BUT YOUR SOLUTION WORKS BEST!!! SAMSUNG/NON-SAMSUNG/ANY_ANDROID... TESTED 9 DIFFERENT MODELS

    THANK YOU ONCE AGAIN!!!

    ReplyDelete
    Replies
    1. I am happy to know that you are using my solution. :)

      Delete
    2. i have a problem in your second solution.. it allows only to take only a single image.. when i try to take image again it creates problem to go forward... please reply me

      Delete
  2. Thank you and thank you so much!! That really helps!!!

    ReplyDelete
  3. where it will store the captured image.could you please reply me

    ReplyDelete
    Replies
    1. If you will use second option the image will be saved in application's file directory.

      Delete
    2. If your device is rooted, you can find it in /data/data/[package name]/files

      Delete
  4. Really it is nice post it will work in devices as well as tab also. but there is one issue in it, when i capture image its rotate in tablets(Galaxy tab 2,7inch). Please add this one also.
    Thank you, Dharmesh.

    ReplyDelete
  5. is there other option to store images into our choice folder name?

    ReplyDelete
    Replies
    1. If your device have SDCARD, you can save the image any where on SDCARD, otherwise, you only can save it in your internal memory and then share it like 2rd sollution in this post.
      //Your image will be save in: /data/data/[package name]/files

      Delete
  6. Hi, I have a question. Why the image can not display.

    ReplyDelete
  7. I want to save the capture image in specific folder instead of gallery..how?

    ReplyDelete
    Replies
    1. You can easily do it by passing the file uri in MediaStore.EXTRA_OUTPUT parameter where you want to save file.
      and in onActivityResult you can check same file it will be saved with captured image. You can not use option-2 as it is to store image into internal storage incase you want to save image to private storage.

      Delete
    2. hello dharmendra your second solution works fine with high quality images but it keeps rotated potratit image into landscape mode ..landscape mode is fine..please help me on this thanks

      Delete
    3. You need to rotate image manually after you get file in your local directory.

      Delete
  8. Nice post, But i want to save captured image in specific sd card folder with using current time and data format....How? Plz help me...

    ReplyDelete
  9. sir it is working properly but i want to set that image in that perticular image view which is declare in our main.xml
    help me as soon as possible.

    ReplyDelete
  10. it is also not working on samsung galaxy note2 gt-n7100

    ReplyDelete
  11. THANK YOU SOOOOOOOO MUCH. YOU HELPED OUT A WHOLE LOT!!!!!

    ReplyDelete
  12. would like to move the capured image to a remote server. can u please help?

    ReplyDelete
  13. Hello Dharmendra, i am using your example, when i am capturing image, it is captured but i am not able to retrieve it back and display on ImageView.

    ReplyDelete
  14. Hi Dharmendra, I have done the application....
    But my doubt is : How to store images (captured by camera) with default names ? (Eg. If I am taking 5 pict, then in SD card folder it should be like
    image1.jpg, image2.jpg etc...,

    ReplyDelete
    Replies
    1. Can you please share the answer of this query of yours with me also.

      Delete
    2. I'm interesting too! please write me!

      Delete
  15. Will this approach work for Capturing videos as well?

    ReplyDelete
  16. Hi Dharmendra,
    It a very good tutorial,
    I need help in two things
    1.) How to capture multiple images minimum 4 , maximum as per user request.

    2.) Get the URI of all the images so that i can store the images to Amazon S3

    I wish some one could help me in this

    ReplyDelete
  17. hello.. :-)
    thank you soooo much as your solution works..
    but once i close the app and reopen it the image will not be there in the app..
    can u plzzz tel me how to store it permanently in the app??

    ReplyDelete
  18. How do I get the address i.e., path of the directory where that image is stored in the string form so that i can enter that string in my image encrypting func.

    ReplyDelete
  19. Hi, thanks for your tutorial, One question, if I want to do the same for a video. How I do it?
    Thanks again

    ReplyDelete
  20. hey,i tried this code
    it's showing :
    Bitmap too large to be uploaded into a texture (3120x4160, max=4096x4096)
    can someone please help me here

    ReplyDelete
  21. I liked the content on this site. Would like to visit again.
    Camera memory Documents

    ReplyDelete
  22. How can I set another name to photos? All photos call "newImage.jpg", i'd want to call them with a Date Format.
    Thank for your replay

    ReplyDelete
  23. Nao funcionou o botão nao abre a camera

    ReplyDelete
  24. This comment has been removed by the author.

    ReplyDelete