Руководство Android Camera
View more Tutorials:
Camera (Камера) это устройство позволяющее вам делать фотографии или снимать видео. в Android есть 2 cпособа работы с Camera.
Способ 1:
В системе Android имеется приложения для работы с Камерой, ваше приложение можетт вызвать это приложение через неявное намерение (Implicit Intent), чтобы дать запрос на действие для Камеры, например запрос открыть Камеру и сделать фото, или открыть Камеру чтобы снять видео, и получить возвращенный результат.
Способ 2:
Android предоставляет вам API чтобы работать напрямую с Камерой.
С Android Level < 21 вы можете работать напрямую с Камерой через android.hardware.Camera, но этот класс уже устарел (Deprected) и больше не используется в Android Level >= 21, рекомендуем вам использовать Camera2 API.
С Android Level < 21 вы можете работать напрямую с Камерой через android.hardware.Camera, но этот класс уже устарел (Deprected) и больше не используется в Android Level >= 21, рекомендуем вам использовать Camera2 API.

В этом документе я покажу вам ка использовать Неявное намерение для вызова приложения Камера имеющийся в системе для открытия Камера, чтобы сфотографировать или снять видео.
Можете посмотреть инструкцию использования Camera2 API по ссылке:
- TODO Link!
В системе Android имеется приложение для работы с Камерой, в приложении вы можете создать Intent намерение чтобы вызвать данное приложение, запросить открытие Камеры для снятия видео или сделать фото.
// 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 | Описание |
---|---|
ACTION_IMAGE_CAPTURE_SECURE | Возвращает Image сфотографированный с Camera, когда устройство защищено |
ACTION_VIDEO_CAPTURE | Вызывает video приложение в Android чтобы снять video из Camera. |
EXTRA_SCREEN_ORIENTATION | Используется для настройки направления экрана "vertical" или "landscape" |
EXTRA_FULL_SCREEN | Используется для управления интерфейсом пользователя в ViewImage |
INTENT_ACTION_VIDEO_CAMERA | Используется для старта Camera в моде video. |
EXTRA_SIZE_LIMIT | Используется для определения самого большого значения для размера файла изображения и видео |
В том случае, если вы хотите сохранить фото или видео снятые устройством, вам нужно настроить разрешение на чтение и записи данных в устройство. Конфигурация на 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; } } }
Создать новый project с названием AndroidCameraDemo:
- File > New > New Project > Empty Activity
- Name: AndroidCameraDemo
- Package name: org.o7planning.androidcamerademo
- Language: Java
Добавить настройки, позволяющие читать и записывать данные в устройстве.
<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:roundIcon="@mipmap/ic_launcher_round" 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"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <ImageView android:id="@+id/imageView" android:layout_width="0dp" android:layout_height="175dp" android:layout_marginStart="16dp" android:layout_marginLeft="16dp" android:layout_marginTop="21dp" android:layout_marginEnd="16dp" android:layout_marginRight="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:srcCompat="@drawable/ic_launcher_foreground" tools:ignore="VectorDrawableCompat" /> <VideoView android:id="@+id/videoView" android:layout_width="0dp" android:layout_height="175dp" android:layout_marginStart="16dp" android:layout_marginLeft="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:layout_marginRight="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/imageView" /> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginLeft="16dp" android:layout_marginTop="8dp" android:layout_marginEnd="16dp" android:layout_marginRight="16dp" android:orientation="horizontal" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/videoView"> <Button android:id="@+id/button_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="0" android:text="Capture Image" /> <Button android:id="@+id/button_video" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="0" android:text="Capture Video" /> </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
package org.o7planning.androidcamerademo; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import android.os.Bundle; import android.Manifest; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.net.Uri; import android.os.Environment; import android.os.StrictMode; import android.provider.MediaStore; 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() { try { // 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); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // ================================================================================================ // To Fix Error (**) // ================================================================================================ StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder(); StrictMode.setVmPolicy(builder.build()); // ================================================================================================ // You may get an Error (**) If your app targets API 24+ // "android.os.FileUriExposedException: file:///storage/emulated/0/xxx exposed beyond app through.." // Explanation: https://stackoverflow.com/questions/38200282 // ================================================================================================ // Start camera and wait for the results. this.startActivityForResult(intent, REQUEST_ID_VIDEO_CAPTURE); // (**) } catch(Exception e) { Toast.makeText(this, "Error capture video: " +e.getMessage(), Toast.LENGTH_LONG).show(); e.printStackTrace(); } } // 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(); } } } }
Приложение сохранит video в SD Card эмулятора (Emulator), поэтому удостоверьтесь, что вы создали SD Card.
OK, теперь вы можете запустить приложение. Здесь я запускаю приложении эмулятора с Камерой эмулятор.

Добавить ImageView, VideoView в интерфейс.


Добавить Button в интерфейс.


Настроить ID, Text для компонентов на интерфейсе.
