Taking Picture in App

Shubham Mishra
Aug 23, 2017 · 5 min read

Sometime in our app we want to take picture for some feature of our app. We can take picture in 2 ways in android:

1)By opening camera app of phone getting result back

2)By opening camera within app

By Opening Camera App

For Opening camera app from the App, we can do by firing the intent of camera app from the app. Before that we need permission for the camera, which needs to be specified in the Manifest file of App. And we also need permission for storing the picture taken.

Example:

<uses-feature android:name="android.hardware.camera" android:required="true" />

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

Next Step is, we need to do Take picture from camera we do this by calling the intent for camera:

static final int REQUEST_TAKE_PHOTO = 1;

private void dispatchTakePictureIntent() {

Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

// Ensure that there's a camera activity to handle the intent

if (takePictureIntent.resolveActivity(getPackageManager()) != null) {

// Create the File where the photo should go

File photoFile = null;

try {

photoFile = createImageFile();

} catch (IOException ex) {

// Error occurred while creating the File

e.printStackTrace();

}

// Continue only if the File was successfully created

if (photoFile != null) {

takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoURI);

startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);

}

}

}

String mCurrentPhotoPath;

private File createImageFile() throws IOException {

// Create an image file name

String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")

.format(new Date());

String imageFileName = "JPEG_" + timeStamp + "_";

File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);

File image = File.createTempFile(

imageFileName, /* prefix */

".jpg", /* suffix */

storageDir /* directory */

);

// Save a file: path for use with ACTION_VIEW intents

mCurrentPhotoPath = image.getAbsolutePath();

return image;

}

Now we have to add the image in gallery that is we have to add the image file in media provider of the phone.

When you create a photo through an intent, you should know where your image is located, because you said where to save it in the first place. For everyone else, perhaps the easiest way to make your photo accessible is to make it accessible from the system's Media Provider.

/**

*Add image in gallery

*/

private void galleryAddPic() {

Intent mediaScanIntent =

new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);

File f = new File(mCurrentPhotoPath);

Uri contentUri = Uri.fromFile(f);

mediaScanIntent.setData(contentUri);

this.sendBroadcast(mediaScanIntent);

}

Next Step, managing multiple full-sized images can be tricky with limited memory. If you find your application running out of memory after displaying just a few images, you can dramatically reduce the amount of dynamic heap used by expanding the JPEG into a memory array that's already scaled to match the size of the destination view. The following example method demonstrates this technique.

In simple words we have to show the image in image view of app.

private void setPicture() {

// Get the dimensions of the View

int targetWidth = mImageView.getWidth();

int targetHeight = mImageView.getHeight();

// Get the dimensions of the bitmap

BitmapFactory.Options bmOptions = new BitmapFactory.Options();

bmOptions.inJustDecodeBounds = true;

BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);

int photoWidth = bmOptions.outWidth;

int photoHeight = bmOptions.outHeight;

// Determine how much to scale down the image

int scaleFactor = Math.min(photoWidth/targetWidth, photoHeight/targetHeight);

// Decode the image file into a Bitmap sized to fill the View

bitmapOptions.inJustDecodeBounds = false;

bitmapOptions.inSampleSize = scaleFactor;

bitmapOptions.inPurgeable = true;

Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);

mImageView.setImageBitmap(bitmap);

}

So Now image is shown in imageView .

By Opening Camera Within App

If your application revolves around photography, it may need custom functionality that the stock camera doesn't support. When you need to create a custom camera, you can use Android's Camera object. The Camera object has many options and features, but this makes it much more complex to use than the built-in camera application.

So, it is done in following way:

Step 1: First you have to specify the permission as above and check the camera first the device has or not.

Context context = getActivity();

PackageManager packageManager= context.getPackageManager();

if(packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA) == false)

{

Toast.makeText(getActivity(), "This device does not have a camera.", Toast.LENGTH_SHORT) . show( );

return;

}

Step 2:

On some Android devices you may also have to worry about a front and rear facing camera. You can check for various camera capabilities using the package manager like this:

context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)

Common checks you may want to perform are...

  1. FEATURE_CAMERA_FRONT (checks for a FRONT facing camera)
  2. FEATURE_CAMERA (checks for a REAR facing camera)
  3. FEATURE_CAMERA_ANY (checks for ANY camera)

You can decide which camera to open if you have many cameras in the phone.

Step 3:

Now we open the camera in the fragment as it is created. We have to open camera in safe mode that is it may be possible that camera is still in use of another application.

For getting the preview of camera, create a surface view inside a frame layout that is create a custom surfaceView first then open the camera .

/**

* Surface on which the camera projects it's capture results.

*/

class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { SurfaceHolder mHolder;

Camera mCamera;

public CameraPreview(Context context, Camera camera)

{

super(context);

mCamera = camera;

// Install a SurfaceHolder.Callback so we get notified when the

// underlying surface is created and destroyed.

mHolder = getHolder();

mHolder.addCallback(this);

// deprecated setting, but required on Android versions prior to 3.0 mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

}

public void surfaceCreated(SurfaceHolder holder) {

// The Surface has been created, now tell the camera where to draw the preview. try {

mCamera.setPreviewDisplay(holder);

mCamera.startPreview();

} catch (IOException e)

{

e.printStackTrace();

}

}

public void surfaceDestroyed(SurfaceHolder holder) {

// empty. Take care of releasing the Camera preview in your activity.

}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {

// If your preview can change or rotate, take care of those events here.

// Make sure to stop the preview before resizing or reformatting it.

if (mHolder.getSurface() == null){

// preview surface does not exist

return;

}

// stop preview before making changes

try {

mCamera.stopPreview();

} catch (Exception e) {

// ignore: tried to stop a non-existent preview

}

// set preview size and make any resize, rotate or

// reformatting changes here

// start preview with new settings

try {

mCamera.setPreviewDisplay(mHolder);

mCamera.startPreview();

} catch (Exception e){

e.printStackTrace();

}

}

}

Now we open the camera safely

private boolean safeCameraOpenInView(View view)

{

boolean qOpened = false;

releaseCameraAndPreview();

mCamera = getCameraInstance();

qOpened = (mCamera != null);

mPreview = new CameraPreview(getActivity().getBaseContext(), mCamera); FrameLayout preview = (FrameLayout) view.findViewById(R.id.camera_preview); preview.addView(mPreview); return qOpened;

}

Step 4: Next, we will create callback for getting the image data back when the picture is taken. Camera.PictureCallback is Android's method for figuring out when the native camera has been used to snap a photo and get the output results

private Camera.PictureCallback mPicture = new Camera.PictureCallback() {

@Override

public void onPictureTaken(byte[] data, Camera camera) {

File pictureFile = getOutputMediaFile();

if (pictureFile == null){

Toast.makeText(getActivity(), "Image retrieval failed.", Toast.LENGTH_SHORT).show();

return;

}

try {

FileOutputStream fos = new FileOutputStream(pictureFile);

fos.write(data);

fos.close();

} catch (FileNotFoundException |IOException e) {

e.printStackTrace();

} catch ( e) {

e.printStackTrace();

}

}

};

In the above the file is saved in the storage section of app. For preview of image, open the image from storage location in imageView of another fragment.

That's it for this time.

Until then

Happy Coding

find the Code of Sample App in this link .

)
Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade