Lesson 131. Camera. We use a system application

Lesson 131. Camera. We use a system application


In this lesson:

– Get photos and videos using the system app

We open a series of lessons on working with the camera. And let’s start with the simplest. If you need to take a picture or take a video in the application, it is not necessary to create a separate Activity and work with it in the Camera object. You can use an existing application on the system.

To do this, your application must send Intent with action = MediaStore.ACTION_IMAGE_CAPTURE (photo) or MediaStore.ACTION_VIDEO_CAPTURE (video) and wait for a response. That is, the methods startActivityForResult and onActivityResult should be used.

Also, in this Intent you can put the desired file path and the result of the camera operation will be saved there. To do this, add Intri to Intent with the MediaStore.EXTRA_OUTPUT key.

Let’s write a simple application that demonstrates these capabilities.

Let’s create a project:

Project name: P1311_CameraIntent
Build Target: Android 2.3.3
Application name: CameraIntent
Package name: en.startandroid.develop.p1311cameraintent
Create Activity: MainActivity

Add rows to strings.xml:

Photo
Video

screen main.xml:



    
    
    
    

Only the buttons for receiving photos and videos are displayed on the screen, and ImageView in which we will display the received photo.

MainActivity.java:

package ru.startandroid.develop.p1311cameraintent;

import java.io.File;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
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.ImageView;

public class MainActivity extends Activity {

  File directory;
  final int TYPE_PHOTO = 1;
  final int TYPE_VIDEO = 2;

  final int REQUEST_CODE_PHOTO = 1;
  final int REQUEST_CODE_VIDEO = 2;

  final String TAG = "myLogs";

  ImageView ivPhoto;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    createDirectory();
    ivPhoto = (ImageView) findViewById(R.id.ivPhoto);
  }

  public void onClickPhoto(View view) {
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, generateFileUri(TYPE_PHOTO));
    startActivityForResult(intent, REQUEST_CODE_PHOTO);
  }

  public void onClickVideo(View view) {
    Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, generateFileUri(TYPE_VIDEO));
    startActivityForResult(intent, REQUEST_CODE_VIDEO);
  }

  @Override
  protected void onActivityResult(int requestCode, int resultCode,
      Intent intent) {
    if (requestCode == REQUEST_CODE_PHOTO) {
      if (resultCode == RESULT_OK) {
        if (intent == null) {
          Log.d(TAG, "Intent is null");
        } else {
          Log.d(TAG, "Photo uri: " + intent.getData());
          Bundle bndl = intent.getExtras();
          if (bndl != null) {
            Object obj = intent.getExtras().get("data");
            if (obj instanceof Bitmap) {
              Bitmap bitmap = (Bitmap) obj;
              Log.d(TAG, "bitmap " + bitmap.getWidth() + " x "
                  + bitmap.getHeight());
              ivPhoto.setImageBitmap(bitmap);
            }
          }
        }
      } else if (resultCode == RESULT_CANCELED) {
        Log.d(TAG, "Canceled");
      }
    }

    if (requestCode == REQUEST_CODE_VIDEO) {
      if (resultCode == RESULT_OK) {
        if (intent == null) {
          Log.d(TAG, "Intent is null");
        } else {
          Log.d(TAG, "Video uri: " + intent.getData());
        }
      } else if (resultCode == RESULT_CANCELED) {
        Log.d(TAG, "Canceled");
      }
    }
  }

  private Uri generateFileUri(int type) {
    File file = null;
    switch (type) {
    case TYPE_PHOTO:
      file = new File(directory.getPath() + "https://startandroid.ru/" + "photo_"
          + System.currentTimeMillis() + ".jpg");
      break;
    case TYPE_VIDEO:
      file = new File(directory.getPath() + "https://startandroid.ru/" + "video_"
          + System.currentTimeMillis() + ".mp4");
      break;
    }
    Log.d(TAG, "fileName = " + file);
    return Uri.fromFile(file);
  }

  private void createDirectory() {
    directory = new File(
        Environment
            .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
        "MyFolder");
    if (!directory.exists())
      directory.mkdirs();
  }

}

IN onCreate we call our createDirectory method, which in the Pictures folder will create a folder for our files and place the corresponding File object in the directory variable.

IN onClickPhoto and onClickVideo create an Intent with the appropriate action, add the desired file path to this Intent, and send the method startActivityForResult.

IN onActivityResult we catch the result from the camera program. The code is cumbersome because there are a bunch of null checks. For photos and videos, I try to extract the path to the received file using Intent.getData. In addition, for the photo, I’m still trying to extract Bitmap with the resulting image.

method generateFileUri generates the path to the file. To do this, it takes a directory path, defines a prefix and extension depending on the type (photo or video), and uses system time as the bulk of the file name. All this is then converted to Uri and returned as a result of the method.

It remains to add a couple of settings to the manifest.

– write to SD card

– Your app in the market will only be visible to devices with a camera

We save everything and launch the application.

press Photo – opens the system camera application. We take a photo and confirm that we are satisfied with the picture. We are returned to our application.

We look at the logs:

fileName = /storage/emulated/0/Pictures/MyFolder/photo_1376465721626.jpg
Intent is null

We received nothing in response, Intent = null. But we did indicate where to save the photo. We go to the Pictures / MyFolder folder and look for our file, it should be there.

Let’s try to get a video. press the button Video, We shoot the video and confirm that it suits us.

We look at the logs:

fileName = /storage/emulated/0/Pictures/MyFolder/video_1376466182087.mp4
Video Clock: file: ///storage/emulated/0/Pictures/MyFolder/video_1376466182087.mp4

In the case of Intent video is NOT null. And his getData method returned us the file path info. We go to the folder and look for our file.

Now, let’s not explicitly specify the path to save, and see how the camera app behaves.

We comment on the corresponding lines of code:

  public void onClickPhoto(View view) {
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    //intent.putExtra(MediaStore.EXTRA_OUTPUT, generateFileUri(TYPE_PHOTO));
    startActivityForResult(intent, REQUEST_CODE_PHOTO);
  }

  public void onClickVideo(View view) {
    Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
    //intent.putExtra(MediaStore.EXTRA_OUTPUT, generateFileUri(TYPE_VIDEO));
    startActivityForResult(intent, REQUEST_CODE_VIDEO);
  }

Save, launch the application.

press Photo, We take a photo and confirm it, our application opens and ImageView shows the photo you just made.

We look at the logs:

Photo hours: null
bitmap 120 x 160

getData returned null, though help promised that there would be a path to the file. But at Intent we got Bitmap. But, as we can see, the size of it leaves much to be desired. It turns out that at all there is no access to the full made photo. It does not even exist in the folder where the camera keeps the default photos.

Most likely, it depends on the version of Android and the system application of the camera. And you may have a different behavior on the system.

Let’s try with the video. press Video, We shoot and confirm the movie.

In the logs:

Video hours: content: // media / external / video / media / 8018

From the video everything is ok. The camera saved the video to the default folder and returned the Uri to Intent.

In addition to your preferred video path, you can specify some other options in intent:

MediaStore.EXTRA_VIDEO_QUALITY – Video quality. 0 (bad) or 1 (good).

MediaStore.EXTRA_DURATION_LIMIT – The video duration limit is in seconds

MediaStore.EXTRA_SIZE_LIMIT – Limit the size of the received video in bytes

In the next lesson:

– Use the Camera object to get an image from the camera
– Customize the image to fit the screen size
– take into account the rotation of the device




Discuss in the forum [39 replies]

Leave a Comment