Руководство Android Camera

1- Android Camera

Камера это устройство позволяющее вам делать фотографии или снимать видео. в Android есть 2 cпособа работы с  Камерой.

Method 1:

В системе  Android имеется приложения для работы с Камерой, ваше приложение можетт вызвать это приложение через неявное намерение (Implicit Intent), чтобы дать запрос на действие для Камеры, например запрос открыть  Камеру и сделать фото, или открыть  Камеру чтобы снять видео, и получить возвращенный результат.

Method 2:

Android предоставляет вам API чтобы работать напрямую с Камерой.

С Android Level < 21 вы можете работать напрямую с Камерой через  android.hardware.Camera, но этот класс уже устарел (Deprected) и больше не используется в   Android Level >= 21, рекомендуем вам использовать camera2 API.
В этом документе я покажу вам ка использовать Н еявное намерение для вызова приложения  Камера имеющийся в системе для открытия  Камера, чтобы сфотографировать или снять видео.
Можете посмотреть инструкцию использования  Camera2 API по ссылке:
  • TODO Link? 11471

2- Overview

В системе Android имеется приложение для работы с Камерой, в приложении вы можете создать Неявное намерение чтобы вызвать данное приложение, запросить открытие Камеры для снятия видео или сделать фото.
// Create an implicit intent, for image capture.
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

int REQUEST_ID_IMAGE_CAPTURE = 100;

// Start camera and wait for the results.
this.startActivityForResult(intent, REQUEST_ID_IMAGE_CAPTURE);
Вид намерений для Камеры:
Intent Type Description
ACTION_IMAGE_CAPTURE_SECURE

It returns the image captured from the camera , when the device is secured

ACTION_VIDEO_CAPTURE

It calls the existing video application in android to capture video

EXTRA_SCREEN_ORIENTATION

It is used to set the orientation of the screen to vertical or landscape

EXTRA_FULL_SCREEN

It is used to control the user interface of the ViewImage

INTENT_ACTION_VIDEO_CAMERA

This intent is used to launch the camera in the video mode

EXTRA_SIZE_LIMIT

It is used to specify the size limit of video or image capture size

В том случае, если вы хотите сохранить фото или видео снятые устройством, вам нужно настроить разрешение на чтение и записи данных в устройство. Конфигурация на  AndroidManifest.xml.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
С  Android Level >= 23, вам нужно использовать код, чтобы попросить пользователя разрешения прочитать и записать данные в устройство.
// With Android Level >= 23, you have to ask the user
// for permission to read/write data on the device.
if (android.os.Build.VERSION.SDK_INT >= 23) {

    // Check if we have read/write permission
    // Kiểm tra quyền đọc/ghi dữ liệu vào thiết bị lưu trữ ngoài.
    int readPermission = ActivityCompat.checkSelfPermission(this,
                                   Manifest.permission.READ_EXTERNAL_STORAGE);
    int writePermission = ActivityCompat.checkSelfPermission(this,
                                   Manifest.permission.WRITE_EXTERNAL_STORAGE);

   if (writePermission != PackageManager.PERMISSION_GRANTED ||
           readPermission != PackageManager.PERMISSION_GRANTED) {
       // If don't have permission so prompt the user.
       this.requestPermissions(
               new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
                       Manifest.permission.READ_EXTERNAL_STORAGE},
               REQUEST_ID_READ_WRITE_PERMISSION
       );
   }
}
Обработка при ответе пользователя.
// When you have the request results
@Override
public void onRequestPermissionsResult(int requestCode,
                                   String permissions[], int[] grantResults) {

    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    //
    switch (requestCode) {
        case REQUEST_ID_READ_WRITE_PERMISSION: {

            // Note: If request is cancelled, the result arrays are empty.
            // Permissions granted (read/write).
            if (grantResults.length > 1
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED
                    && grantResults[1] == PackageManager.PERMISSION_GRANTED) {

                Toast.makeText(this, "Permission granted!", Toast.LENGTH_LONG).show();

                this.captureVideo();

            }
            // Cancelled or denied.
            else {
                Toast.makeText(this, "Permission denied!", Toast.LENGTH_LONG).show();
            }
            break;
        }
    }
}

3- Camera for Emulator

Если вы работаете с Эмулятором, вам нужно настроить Камеру, есть два варианта:
  1. Использовать Камеру эмулятор.
  2. Или использовать Webcam компьютера как Камеру телефона для эмулятора.
Если вы не настроили  Камера, вы получите ошибку:
java.lang.RuntimeException: Fail to connect to camera service
Здесь я настраиваю Камеру эмулятор.
Используем Камеру эмулятор.

4- Example

Создать новый project с названием  AndroidCameraDemo:
Добавить настройки, позволяющие читать и записывать данные в устройстве.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.o7planning.androidcamerademo">


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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
Дизайн интерфейса:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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="org.o7planning.androidcamerademo.MainActivity">

    <ImageView
        android:layout_width="fill_parent"
        android:layout_height="180dp"
        android:id="@+id/imageView"
        android:layout_alignParentTop="true" />

    <VideoView
        android:layout_width="wrap_content"
        android:layout_height="180dp"
        android:id="@+id/videoView"
        android:layout_below="@+id/imageView"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <Button
        style="?android:attr/buttonStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Capture Image"
        android:id="@+id/button_image"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <Button
        style="?android:attr/buttonStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Capture Video"
        android:id="@+id/button_video"
        android:layout_alignTop="@+id/button_image"
        android:layout_toRightOf="@+id/button_image"
        android:layout_toEndOf="@+id/button_image" />

</RelativeLayout>
MainActivity.java
package org.o7planning.androidcamerademo;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import android.widget.VideoView;

import java.io.File;

public class MainActivity extends AppCompatActivity {

   private Button buttonImage;
   private Button buttonVideo;

   private VideoView videoView;
   private ImageView imageView;

   private static final int REQUEST_ID_READ_WRITE_PERMISSION = 99;
   private static final int REQUEST_ID_IMAGE_CAPTURE = 100;
   private static final int REQUEST_ID_VIDEO_CAPTURE = 101;

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

       this.buttonImage = (Button) this.findViewById(R.id.button_image);
       this.buttonVideo = (Button) this.findViewById(R.id.button_video);
       this.videoView = (VideoView) this.findViewById(R.id.videoView);
       this.imageView = (ImageView) this.findViewById(R.id.imageView);

       this.buttonImage.setOnClickListener(new Button.OnClickListener() {
           @Override
           public void onClick(View v) {
               captureImage();
           }
       });

       this.buttonVideo.setOnClickListener(new Button.OnClickListener() {
           @Override
           public void onClick(View v) {
               askPermissionAndCaptureVideo();
           }
       });
   }

   private void captureImage() {
       // Create an implicit intent, for image capture.
       Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

       // Start camera and wait for the results.
       this.startActivityForResult(intent, REQUEST_ID_IMAGE_CAPTURE);
   }

   private void askPermissionAndCaptureVideo() {

       // With Android Level >= 23, you have to ask the user
       // for permission to read/write data on the device.
       if (android.os.Build.VERSION.SDK_INT >= 23) {

           // Check if we have read/write permission
           int readPermission = ActivityCompat.checkSelfPermission(this,
                                          Manifest.permission.READ_EXTERNAL_STORAGE);
           int writePermission = ActivityCompat.checkSelfPermission(this,
                                          Manifest.permission.WRITE_EXTERNAL_STORAGE);

           if (writePermission != PackageManager.PERMISSION_GRANTED ||
                   readPermission != PackageManager.PERMISSION_GRANTED) {
               // If don't have permission so prompt the user.
               this.requestPermissions(
                       new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
                               Manifest.permission.READ_EXTERNAL_STORAGE},
                       REQUEST_ID_READ_WRITE_PERMISSION
               );
               return;
           }
       }
       this.captureVideo();
   }

   private void captureVideo() {

       // Create an implicit intent, for video capture.
       Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);

       // The external storage directory.
       File dir = Environment.getExternalStorageDirectory();
       if (!dir.exists()) {
           dir.mkdirs();
       }
       // file:///storage/emulated/0/myvideo.mp4
       String savePath = dir.getAbsolutePath() + "/myvideo.mp4";
       File videoFile = new File(savePath);
       Uri videoUri = Uri.fromFile(videoFile);

       // Specify where to save video files.
       intent.putExtra(MediaStore.EXTRA_OUTPUT, videoUri);

       // Start camera and wait for the results.
       this.startActivityForResult(intent, REQUEST_ID_VIDEO_CAPTURE);
   }


   // When you have the request results
   @Override
   public void onRequestPermissionsResult(int requestCode,
                                          String permissions[], int[] grantResults) {

       super.onRequestPermissionsResult(requestCode, permissions, grantResults);
       //
       switch (requestCode) {
           case REQUEST_ID_READ_WRITE_PERMISSION: {

               // Note: If request is cancelled, the result arrays are empty.
               // Permissions granted (read/write).
               if (grantResults.length > 1
                       && grantResults[0] == PackageManager.PERMISSION_GRANTED
                       && grantResults[1] == PackageManager.PERMISSION_GRANTED) {

                   Toast.makeText(this, "Permission granted!", Toast.LENGTH_LONG).show();

                   this.captureVideo();

               }
               // Cancelled or denied.
               else {
                   Toast.makeText(this, "Permission denied!", Toast.LENGTH_LONG).show();
               }
               break;
           }
       }
   }

   // When results returned
   @Override
   protected void onActivityResult(int requestCode, int resultCode, Intent data) {
       super.onActivityResult(requestCode, resultCode, data);

       if (requestCode == REQUEST_ID_IMAGE_CAPTURE) {
           if (resultCode == RESULT_OK) {
               Bitmap bp = (Bitmap) data.getExtras().get("data");
               this.imageView.setImageBitmap(bp);
           } else if (resultCode == RESULT_CANCELED) {
               Toast.makeText(this, "Action canceled", Toast.LENGTH_LONG).show();
           } else {
               Toast.makeText(this, "Action Failed", Toast.LENGTH_LONG).show();
           }
       } else if (requestCode == REQUEST_ID_VIDEO_CAPTURE) {
           if (resultCode == RESULT_OK) {
               Uri videoUri = data.getData();
               Log.i("MyLog", "Video saved to: " + videoUri);
               Toast.makeText(this, "Video saved to:\n" +
                       videoUri, Toast.LENGTH_LONG).show();
               this.videoView.setVideoURI(videoUri);
               this.videoView.start();
           } else if (resultCode == RESULT_CANCELED) {
               Toast.makeText(this, "Action Cancelled.",
                       Toast.LENGTH_LONG).show();
           } else {
               Toast.makeText(this, "Action Failed",
                       Toast.LENGTH_LONG).show();
           }
       }
   }

}
OK, теперь вы можете запустить приложение. Здесь я запускаю приложении эмулятора с Камерой эмулятор.

5- Problem with Emulator

Note: When you run the app for the first time click the "Capture Video", the application will ask for the right to read and write on the storage device.
After the user grant permission to read/write data on external storage devices, but it still does not work (This is the issue of simulation equipment).
You can rerun applications from Android Studio. Application has been allowed in previous running time and do not ask again. You also do not get the error as illustrated above.