Фреймворк Android поддерживает различные камеры и их функции, доступные на устройствах. Это позволяет делать снимки и записывать видео в приложениях. В этом документе рассматривается быстрый и простой подход к съемке изображений и видео, а также описывается расширенный подход к созданию пользовательских возможностей камеры для ваших пользователей.
Примечание. На этой странице описан класс Camera, который больше не поддерживается. Рекомендуем использовать библиотеку Jetpack CameraX или, в определенных случаях, класс camera2. Оба API CameraX и Camera2 работают на устройствах с Android 5.0 (уровень API 21) и более поздними версиями.
Ознакомьтесь со следующей информацией по теме:
Что нужно учесть
Прежде чем разрешить приложению использовать камеры на устройствах Android, подумайте, как именно оно будет это делать.
- Требования к камере. Насколько важно наличие камеры для работы вашего приложения? Хотите ли вы, чтобы оно не устанавливалось на устройства без камеры? Если да, то вам нужно указать в манифесте, что для работы приложения требуется камера.
- Быстрая съемка или настраиваемая камера. Как ваше приложение будет использовать камеру? Вы просто хотите сделать быстрый снимок или видеоклип или ваше приложение предоставит новый способ использования камер? Если вам нужно быстро сделать снимок или записать видео, используйте существующие приложения камеры. Чтобы узнать, как разработать собственную функцию камеры, ознакомьтесь с разделом Создание приложения камеры.
- Требования к активным службам. Когда приложение взаимодействует с камерой? В Android 9 (уровень API 28) и более поздних версиях приложения, работающие в фоновом режиме, не могут получить доступ к камере. Поэтому используйте камеру, только когда приложение активно или в рамках активной службы.
- Хранилище. Должны ли изображения и видео, создаваемые вашим приложением, быть доступны только в нем или же ими можно делиться с другими приложениями, например Галереей, социальными приложениями и медиаприложениями? Должны ли фотографии и видео оставаться доступными, даже если приложение удалено? Подробнее о том, как реализовать эти варианты, рассказывается в разделе Сохранение медиафайлов.
Основные сведения
Фреймворк Android поддерживает съемку фото и видео с помощью android.hardware.camera2 API или Intent камеры. Вот соответствующие классы:
android.hardware.camera2- Этот пакет является основным API для управления камерами устройства. Его можно использовать для съемки фотографий или видео при создании приложения камеры.
Camera- Этот класс представляет собой устаревший API для управления камерами устройств.
SurfaceView- Этот класс используется для показа пользователю изображения с камеры в реальном времени.
MediaRecorder- Этот класс используется для записи видео с камеры.
Intent- Тип действия intent
MediaStore.ACTION_IMAGE_CAPTUREилиMediaStore.ACTION_VIDEO_CAPTUREможно использовать для съемки фото или видео без прямого использования объектаCamera.
Декларации в манифесте
Прежде чем начать разработку приложения с помощью Camera API, убедитесь, что в манифесте есть соответствующие объявления, разрешающие использование аппаратного обеспечения камеры и других связанных с ней функций.
- Разрешение на доступ к камере. Приложение должно запрашивать разрешение на использование камеры устройства.
<uses-permission android:name="android.permission.CAMERA" />
Примечание. Если вы используете камеру, вызывая существующее приложение камеры, вашему приложению не нужно запрашивать это разрешение.
- Функции камеры. В приложении также должно быть объявлено использование функций камеры, например:
<uses-feature android:name="android.hardware.camera" />
Список функций камеры можно найти в справочнике по функциям.
Если вы добавите функции камеры в манифест, Google Play не позволит установить ваше приложение на устройства, у которых нет камеры или которые не поддерживают указанные функции. Подробнее о фильтрации по функциям в Google Play…
Если для работы приложения может использоваться камера или ее функция, но это не обязательно, укажите это в манифесте, добавив атрибут
android:requiredи задав для него значениеfalse:<uses-feature android:name="android.hardware.camera" android:required="false" />
- Разрешение на доступ к хранилищу. Если приложение предназначено для Android 10 (уровень API 29) или более ранней версии и в его манифесте указано следующее разрешение, оно может сохранять изображения и видео на внешнем накопителе устройства (SD-карте):
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- Разрешение на запись аудио. Чтобы записывать аудио вместе с видео, приложение должно запрашивать разрешение на запись аудио.
<uses-permission android:name="android.permission.RECORD_AUDIO" />
-
Доступ к данным о местоположении. Если ваше приложение добавляет к изображениям теги с данными о местоположении, полученными по GPS, вы должны запросить разрешение
ACCESS_FINE_LOCATION. Если ваше приложение предназначено для Android 5.0 (уровень API 21) или более поздней версии, вам также нужно указать, что оно использует GPS-модуль устройства:<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> ... <!-- Needed only if your app targets Android 5.0 (API level 21) or higher. --> <uses-feature android:name="android.hardware.location.gps" />
Подробнее о том, как получить данные о местоположении пользователя, читайте в статье Стратегии определения местоположения.
Использование существующих приложений камеры
Чтобы быстро включить в приложении возможность снимать фото и видео без написания большого количества дополнительного кода, используйте Intent для вызова существующего приложения камеры Android.
Подробности описаны в уроках Простая фотосъемка и Простая видеосъемка.
Создание приложения камеры
Некоторым разработчикам может потребоваться пользовательский интерфейс камеры, который соответствует внешнему виду их приложения или предоставляет специальные функции. Написание собственного кода для фотосъемки может обеспечить более привлекательный опыт для ваших пользователей.
Примечание. Ниже приведено руководство по устаревшему API Camera. Для новых или продвинутых приложений камеры рекомендуется использовать более новый API android.hardware.camera2.
Ниже приведены общие инструкции по созданию собственного интерфейса камеры для приложения.
- Обнаружение камеры и доступ к ней. Создайте код, который будет проверять наличие камер и запрашивать доступ к ним.
- Создайте класс предварительного просмотра. Создайте класс предварительного просмотра камеры, который расширяет
SurfaceViewи реализует интерфейсSurfaceHolder. Этот класс позволяет просматривать изображения с камеры в реальном времени. - Создание макета предварительного просмотра. После создания класса предварительного просмотра камеры создайте макет представления, который включает предварительный просмотр и нужные элементы управления пользовательского интерфейса.
- Настройка прослушивателей для съемки. Подключите прослушиватели для элементов управления интерфейсом, чтобы начать съемку фото или видео в ответ на действия пользователя, например нажатие кнопки.
- Съемка и сохранение файлов. Настройте код для съемки фото или видео и сохранения результатов.
- Освобождение камеры. После использования камеры приложение должно освободить ее, чтобы она стала доступна для других приложений.
Камера – это общий ресурс, которым нужно управлять так, чтобы ваше приложение не конфликтовало с другими приложениями, которые также могут использовать камеру. В следующих разделах рассказывается, как обнаружить камеру, запросить доступ к ней, сделать снимок или записать видео и как освободить камеру, когда приложение закончит ее использовать.
Внимание! Не забудьте освободить объект Camera, вызвав Camera.release(), когда приложение закончит его использовать. Если приложение не освободит камеру должным образом, все последующие попытки получить доступ к ней, в том числе со стороны вашего приложения, будут неудачными и могут привести к завершению работы вашего или других приложений.
Обнаружение камеры
Если в манифесте приложения не указано, что для его работы требуется камера, то во время выполнения необходимо проверять, доступна ли она. Для этого используйте метод PackageManager.hasSystemFeature(), как показано в примере кода ниже.
Kotlin
/** Check if this device has a camera */ private fun checkCameraHardware(context: Context): Boolean { if (context.packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)) { // this device has a camera return true } else { // no camera on this device return false } }
Java
/** Check if this device has a camera */ private boolean checkCameraHardware(Context context) { if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){ // this device has a camera return true; } else { // no camera on this device return false; } }
На устройствах Android может быть несколько камер, например задняя камера для фотосъемки и фронтальная камера для видеовызовов. В Android 2.3 (уровень API 9) и более поздних версиях можно проверить количество камер на устройстве с помощью метода Camera.getNumberOfCameras().
Доступ к камерам
Если вы определили, что на устройстве, на котором запущено ваше приложение, есть камера, вы должны запросить доступ к ней, получив экземпляр Camera (если вы не используете намерение для доступа к камере).
Чтобы получить доступ к основной камере, используйте метод Camera.open() и обязательно перехватывайте все исключения, как показано в коде ниже.
Kotlin
/** A safe way to get an instance of the Camera object. */ fun getCameraInstance(): Camera? { return try { Camera.open() // attempt to get a Camera instance } catch (e: Exception) { // Camera is not available (in use or does not exist) null // returns null if camera is unavailable } }
Java
/** A safe way to get an instance of the Camera object. */ public static Camera getCameraInstance(){ Camera c = null; try { c = Camera.open(); // attempt to get a Camera instance } catch (Exception e){ // Camera is not available (in use or does not exist) } return c; // returns null if camera is unavailable }
Внимание! При использовании Camera.open() всегда проверяйте наличие исключений. Если не проверить наличие исключений, когда камера используется или отсутствует, система закроет приложение.
На устройствах с Android 2.3 (уровень API 9) или более поздней версии можно получить доступ к определенным камерам с помощью метода Camera.open(int). Приведенный выше пример кода обращается к первой задней камере на устройстве с несколькими камерами.
Проверка функций камеры
Получив доступ к камере, вы можете узнать больше о ее возможностях с помощью метода Camera.getParameters() и проверки возвращенного объекта Camera.Parameters на наличие поддерживаемых возможностей. При использовании API уровня 9 или выше используйте Camera.getCameraInfo(), чтобы определить, какая камера используется (фронтальная или основная) и какова ориентация изображения.
Создание курса для предварительного просмотра
Чтобы пользователи могли эффективно делать снимки или записывать видео, они должны видеть, что видит камера устройства. Класс предварительного просмотра камеры – это SurfaceView, который может отображать данные изображения, поступающие с камеры, чтобы пользователи могли кадрировать и снимать изображение или видео.
В следующем примере кода показано, как создать базовый класс предварительного просмотра камеры, который можно включить в макет View. Этот класс реализует SurfaceHolder.Callback, чтобы фиксировать события обратного вызова для создания и удаления представления, которые необходимы для назначения входных данных предварительного просмотра камеры.
Kotlin
/** A basic Camera preview class */ class CameraPreview( context: Context, private val mCamera: Camera ) : SurfaceView(context), SurfaceHolder.Callback { private val mHolder: SurfaceHolder = holder.apply { // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. addCallback(this@CameraPreview) // deprecated setting, but required on Android versions prior to 3.0 setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS) } override fun surfaceCreated(holder: SurfaceHolder) { // The Surface has been created, now tell the camera where to draw the preview. mCamera.apply { try { setPreviewDisplay(holder) startPreview() } catch (e: IOException) { Log.d(TAG, "Error setting camera preview: ${e.message}") } } } override fun surfaceDestroyed(holder: SurfaceHolder) { // empty. Take care of releasing the Camera preview in your activity. } override fun surfaceChanged(holder: SurfaceHolder, format: Int, w: Int, h: Int) { // 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.surface == null) { // preview surface does not exist return } // stop preview before making changes try { mCamera.stopPreview() } catch (e: Exception) { // 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 mCamera.apply { try { setPreviewDisplay(mHolder) startPreview() } catch (e: Exception) { Log.d(TAG, "Error starting camera preview: ${e.message}") } } } }
Java
/** A basic Camera preview class */ public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder mHolder; private 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) { Log.d(TAG, "Error setting camera preview: " + e.getMessage()); } } 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){ Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } } }
Если вы хотите задать определенный размер для окна предварительного просмотра камеры, укажите его в методе surfaceChanged(), как описано в комментариях выше. При настройке размера для предпросмотра необходимо использовать значения из getSupportedPreviewSizes().
Не задавайте произвольные значения в методе setPreviewSize().
Примечание. В Android 7.0 (API уровня 24) и более поздних версиях появился
многооконный режим. Поэтому даже после вызова setDisplayOrientation() соотношение сторон в окне предварительного просмотра может не совпадать с соотношением сторон в объекте activity.
В зависимости от размера окна и соотношения сторон вам может потребоваться вписать широкое окно предварительного просмотра камеры в макет с портретной ориентацией или наоборот, используя макет почтового ящика.
Размещение предварительного просмотра в макете
Класс предварительного просмотра камеры, такой как в примере из предыдущего раздела, должен быть размещен в макете действия вместе с другими элементами управления пользовательского интерфейса для съемки фото или видео. В этом разделе показано, как создать базовый макет и действие для предварительного просмотра.
В следующем коде макета показан очень простой вид, который можно использовать для отображения предварительного просмотра камеры. В этом примере элемент FrameLayout предназначен для контейнера класса предварительного просмотра камеры. Этот тип макета используется для того, чтобы накладывать на изображение с камеры дополнительную информацию или элементы управления.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" > <FrameLayout android:id="@+id/camera_preview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" /> <Button android:id="@+id/button_capture" android:text="Capture" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" /> </LinearLayout>
На большинстве устройств по умолчанию используется альбомная ориентация предварительного просмотра камеры. В этом примере макета задается горизонтальный (альбомный) макет, а приведенный ниже код фиксирует ориентацию приложения на альбомную. Чтобы упростить рендеринг предварительного просмотра камеры, измените ориентацию предварительного просмотра приложения на альбомную, добавив в манифест следующее:
<activity android:name=".CameraActivity" android:label="@string/app_name" android:screenOrientation="landscape"> <!-- configure this activity to use landscape orientation --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
Примечание. Предпросмотр камеры не обязательно должен быть в горизонтальном режиме.
Начиная с Android 2.2 (уровень API 8), вы можете использовать метод setDisplayOrientation(), чтобы задать поворот изображения предварительного просмотра. Чтобы изменить ориентацию предварительного просмотра при изменении ориентации телефона пользователем, в методе surfaceChanged() класса предварительного просмотра сначала остановите предварительный просмотр с помощью Camera.stopPreview(), измените ориентацию, а затем снова запустите предварительный просмотр с помощью Camera.startPreview().
В операции для просмотра камеры добавьте класс предварительного просмотра в элемент FrameLayout, показанный в примере выше. Кроме того, в коде операции необходимо предусмотреть освобождение камеры при приостановке или завершении работы. В примере ниже показано, как изменить операцию камеры, чтобы подключить класс предварительного просмотра, описанный в разделе Создание класса предварительного просмотра.
Kotlin
class CameraActivity : Activity() { private var mCamera: Camera? = null private var mPreview: CameraPreview? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Create an instance of Camera mCamera = getCameraInstance() mPreview = mCamera?.let { // Create our Preview view CameraPreview(this, it) } // Set the Preview view as the content of our activity. mPreview?.also { val preview: FrameLayout = findViewById(R.id.camera_preview) preview.addView(it) } } }
Java
public class CameraActivity extends Activity { private Camera mCamera; private CameraPreview mPreview; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Create an instance of Camera mCamera = getCameraInstance(); // Create our Preview view and set it as the content of our activity. mPreview = new CameraPreview(this, mCamera); FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); preview.addView(mPreview); } }
Примечание. Метод getCameraInstance() в примере выше относится к примеру метода, показанному в разделе Доступ к камерам.
Фотосъемка
После создания класса предварительного просмотра и макета представления, в котором он будет отображаться, вы можете начать захват изображений с помощью своего приложения. В коде приложения необходимо настроить прослушиватели для элементов управления пользовательского интерфейса, чтобы они реагировали на действия пользователя, делая снимок.
Чтобы получить изображение, используйте метод Camera.takePicture(). Этот метод принимает три параметра, которые получают данные от камеры.
Чтобы получать данные в формате JPEG, необходимо реализовать интерфейс Camera.PictureCallback, который будет получать данные изображения и записывать их в файл. В коде ниже показана базовая реализация интерфейса Camera.PictureCallback для сохранения изображения, полученного с камеры.
Kotlin
private val mPicture = Camera.PictureCallback { data, _ -> val pictureFile: File = getOutputMediaFile(MEDIA_TYPE_IMAGE) ?: run { Log.d(TAG, ("Error creating media file, check storage permissions")) return@PictureCallback } try { val fos = FileOutputStream(pictureFile) fos.write(data) fos.close() } catch (e: FileNotFoundException) { Log.d(TAG, "File not found: ${e.message}") } catch (e: IOException) { Log.d(TAG, "Error accessing file: ${e.message}") } }
Java
private PictureCallback mPicture = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE); if (pictureFile == null){ Log.d(TAG, "Error creating media file, check storage permissions"); return; } try { FileOutputStream fos = new FileOutputStream(pictureFile); fos.write(data); fos.close(); } catch (FileNotFoundException e) { Log.d(TAG, "File not found: " + e.getMessage()); } catch (IOException e) { Log.d(TAG, "Error accessing file: " + e.getMessage()); } } };
Запустите съемку изображения, вызвав метод Camera.takePicture(). В примере кода ниже показано, как вызвать этот метод с помощью кнопки View.OnClickListener.
Kotlin
val captureButton: Button = findViewById(R.id.button_capture) captureButton.setOnClickListener { // get an image from the camera mCamera?.takePicture(null, null, picture) }
Java
// Add a listener to the Capture button Button captureButton = (Button) findViewById(R.id.button_capture); captureButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { // get an image from the camera mCamera.takePicture(null, null, picture); } } );
Примечание. Элемент mPicture в примере ниже относится к коду выше.
Внимание! Не забудьте освободить объект Camera, вызвав Camera.release(), когда приложение закончит его использовать. Инструкции приведены в разделе Как разблокировать камеру.
Видеосъемка
Запись видео с помощью фреймворка Android требует тщательного управления объектом Camera и координации с классом MediaRecorder. При записи видео с помощью Camera необходимо управлять вызовами Camera.lock() и Camera.unlock(), чтобы разрешить MediaRecorder доступ к камере, в дополнение к вызовам Camera.open() и Camera.release().
Примечание. Начиная с Android 4.0 (уровень API 14) вызовы Camera.lock() и Camera.unlock() обрабатываются автоматически.
В отличие от фотосъемки, для записи видео требуется определенный порядок вызовов. Чтобы успешно подготовить и записать видео с помощью приложения, необходимо соблюдать определенный порядок действий, описанный ниже.
- Откройте камеру. Используйте
Camera.open(), чтобы получить экземпляр объекта камеры. - Подключить предпросмотр. Подготовьте предпросмотр изображения с камеры, подключив
SurfaceViewк камере с помощьюCamera.setPreviewDisplay(). - Начать предварительный просмотр. Вызовите
Camera.startPreview(), чтобы начать показ изображений с камеры. - Начните запись видео. Чтобы успешно записать видео, выполните следующие действия в указанном порядке:
- Разблокировать камеру. Разблокируйте камеру для использования в
MediaRecorder, вызвавCamera.unlock(). - Настройте MediaRecorder. Вызовите следующие методы
MediaRecorderв указанном порядке. Подробную информацию вы найдете в справочной документации поMediaRecorder.setCamera()– задайте камеру, которая будет использоваться для записи видео, используя текущий экземплярCameraвашего приложения.setAudioSource()– задать источник аудио. ИспользуйтеMediaRecorder.AudioSource.CAMCORDER.setVideoSource()– задать источник видео, использоватьMediaRecorder.VideoSource.CAMERA.- Задайте формат и кодировку видео. Для Android 2.2 (уровень API 8) и более поздних версий используйте метод
MediaRecorder.setProfileи получите экземпляр профиля с помощьюCamcorderProfile.get(). Для версий Android до 2.2 необходимо задать формат вывода видео и параметры кодирования:setOutputFormat()– задать формат вывода, указать настройки по умолчанию илиMediaRecorder.OutputFormat.MPEG_4.setAudioEncoder()– задайте тип кодирования звука, укажите значение по умолчанию илиMediaRecorder.AudioEncoder.AMR_NB.setVideoEncoder()– задайте тип кодирования видео, укажите значение по умолчанию илиMediaRecorder.VideoEncoder.MPEG_4_SP.
setOutputFile()– задайте выходной файл, используяgetOutputMediaFile(MEDIA_TYPE_VIDEO).toString()из примера в разделе Сохранение медиафайлов.setPreviewDisplay()– укажите элемент макета предварительного просмотраSurfaceViewдля своего приложения. Используйте тот же объект, который вы указали для Connect Preview.
Внимание! Вы должны вызвать эти методы конфигурации
MediaRecorderв указанном порядке, иначе в приложении возникнут ошибки и запись не удастся. - Подготовка MediaRecorder. Подготовьте
MediaRecorderс заданными настройками конфигурации, вызвавMediaRecorder.prepare(). - Запуск MediaRecorder. Начните запись видео, вызвав
MediaRecorder.start().
- Разблокировать камеру. Разблокируйте камеру для использования в
- Остановка записи видео. Чтобы успешно завершить запись видео, вызовите следующие методы в указанном порядке:
- Остановка MediaRecorder. Остановите запись видео, вызвав
MediaRecorder.stop(). - Сброс MediaRecorder. При необходимости удалите настройки конфигурации из рекордера, вызвав
MediaRecorder.reset(). - Освободите MediaRecorder. Освободите
MediaRecorder, вызвавMediaRecorder.release(). - Заблокировать камеру. Заблокируйте камеру, чтобы будущие сеансы
MediaRecorderмогли использовать ее, вызываяCamera.lock(). Начиная с Android 4.0 (уровень API 14), этот вызов не требуется, если только не произойдет сбой вызоваMediaRecorder.prepare().
- Остановка MediaRecorder. Остановите запись видео, вызвав
- Остановка предварительного просмотра. Когда действие завершит использование камеры, остановите предварительный просмотр с помощью метода
Camera.stopPreview(). - Освобождение камеры. Освободите камеру, чтобы другие приложения могли использовать ее, вызвав
Camera.release().
Примечание. Вы можете использовать MediaRecorder, не создавая предварительный просмотр камеры, и пропустить первые несколько шагов этого процесса. Однако, поскольку пользователи обычно предпочитают видеть предварительный просмотр перед началом записи, этот процесс здесь не обсуждается.
Совет. Если ваше приложение обычно используется для записи видео, перед запуском предварительного просмотра установите для setRecordingHint(boolean) значение true. Это поможет сократить время, необходимое для начала записи.
Настройка MediaRecorder
При использовании класса MediaRecorder для записи видео необходимо выполнить действия по настройке в определенном порядке, а затем вызвать метод MediaRecorder.prepare(), чтобы проверить и применить конфигурацию. В примере кода ниже показано, как правильно настроить и подготовить класс MediaRecorder для записи видео.
Kotlin
private fun prepareVideoRecorder(): Boolean { mediaRecorder = MediaRecorder() mCamera?.let { camera -> // Step 1: Unlock and set camera to MediaRecorder camera?.unlock() mediaRecorder?.run { setCamera(camera) // Step 2: Set sources setAudioSource(MediaRecorder.AudioSource.CAMCORDER) setVideoSource(MediaRecorder.VideoSource.CAMERA) // Step 3: Set a CamcorderProfile (requires API Level 8 or higher) setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)) // Step 4: Set output file setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString()) // Step 5: Set the preview output setPreviewDisplay(mPreview?.holder?.surface) setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT) setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT) // Step 6: Prepare configured MediaRecorder return try { prepare() true } catch (e: IllegalStateException) { Log.d(TAG, "IllegalStateException preparing MediaRecorder: ${e.message}") releaseMediaRecorder() false } catch (e: IOException) { Log.d(TAG, "IOException preparing MediaRecorder: ${e.message}") releaseMediaRecorder() false } } } return false }
Java
private boolean prepareVideoRecorder(){ mCamera = getCameraInstance(); mediaRecorder = new MediaRecorder(); // Step 1: Unlock and set camera to MediaRecorder mCamera.unlock(); mediaRecorder.setCamera(mCamera); // Step 2: Set sources mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // Step 3: Set a CamcorderProfile (requires API Level 8 or higher) mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)); // Step 4: Set output file mediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString()); // Step 5: Set the preview output mediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface()); // Step 6: Prepare configured MediaRecorder try { mediaRecorder.prepare(); } catch (IllegalStateException e) { Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage()); releaseMediaRecorder(); return false; } catch (IOException e) { Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage()); releaseMediaRecorder(); return false; } return true; }
В версиях до Android 2.2 (уровень API 8) необходимо задавать параметры формата вывода и кодирования напрямую, а не с помощью CamcorderProfile. Этот подход показан в следующем коде:
Kotlin
// Step 3: Set output format and encoding (for versions prior to API Level 8) mediaRecorder?.apply { setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT) setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT) }
Java
// Step 3: Set output format and encoding (for versions prior to API Level 8) mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
Для следующих параметров видеозаписи в MediaRecorder заданы настройки по умолчанию, но вы можете изменить их для своего приложения:
setVideoEncodingBitRate()setVideoSize()setVideoFrameRate()setAudioEncodingBitRate()setAudioChannels()setAudioSamplingRate()
Запуск и остановка MediaRecorder
При запуске и остановке записи видео с помощью класса MediaRecorder необходимо соблюдать определенный порядок, описанный ниже.
- Разблокировать камеру с помощью:
Camera.unlock() - Настройте
MediaRecorder, как показано в примере кода выше. - Начать запись с помощью
MediaRecorder.start() - Запишите видео
- Остановить запись с помощью приложения "
MediaRecorder.stop()" - Освободите устройство записи мультимедиа с помощью
MediaRecorder.release() - Заблокировать камеру с помощью
Camera.lock()
В примере кода ниже показано, как настроить кнопку, чтобы правильно запускать и останавливать запись видео с помощью камеры и класса MediaRecorder.
Примечание. При записи видео не отпускайте камеру, иначе предварительный просмотр будет остановлен.
Kotlin
var isRecording = false val captureButton: Button = findViewById(R.id.button_capture) captureButton.setOnClickListener { if (isRecording) { // stop recording and release camera mediaRecorder?.stop() // stop the recording releaseMediaRecorder() // release the MediaRecorder object mCamera?.lock() // take camera access back from MediaRecorder // inform the user that recording has stopped setCaptureButtonText("Capture") isRecording = false } else { // initialize video camera if (prepareVideoRecorder()) { // Camera is available and unlocked, MediaRecorder is prepared, // now you can start recording mediaRecorder?.start() // inform the user that recording has started setCaptureButtonText("Stop") isRecording = true } else { // prepare didn't work, release the camera releaseMediaRecorder() // inform user } } }
Java
private boolean isRecording = false; // Add a listener to the Capture button Button captureButton = (Button) findViewById(id.button_capture); captureButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { if (isRecording) { // stop recording and release camera mediaRecorder.stop(); // stop the recording releaseMediaRecorder(); // release the MediaRecorder object mCamera.lock(); // take camera access back from MediaRecorder // inform the user that recording has stopped setCaptureButtonText("Capture"); isRecording = false; } else { // initialize video camera if (prepareVideoRecorder()) { // Camera is available and unlocked, MediaRecorder is prepared, // now you can start recording mediaRecorder.start(); // inform the user that recording has started setCaptureButtonText("Stop"); isRecording = true; } else { // prepare didn't work, release the camera releaseMediaRecorder(); // inform user } } } } );
Примечание. В примере выше метод prepareVideoRecorder() относится к примеру кода, показанному в разделе Настройка MediaRecorder. Этот метод блокирует камеру, настраивает и подготавливает экземпляр MediaRecorder.
Как отпустить камеру
Камеры – это ресурс, который используется приложениями на устройстве. Приложение может использовать камеру после получения экземпляра Camera. При этом необходимо освободить объект камеры, когда приложение перестанет его использовать или будет приостановлено (Activity.onPause()). Если приложение не освободит камеру должным образом, все последующие попытки получить доступ к ней, в том числе со стороны вашего приложения, будут неудачными и могут привести к завершению работы вашего или других приложений.
Чтобы освободить экземпляр объекта Camera, используйте метод Camera.release(), как показано в примере кода ниже.
Kotlin
class CameraActivity : Activity() { private var mCamera: Camera? private var preview: SurfaceView? private var mediaRecorder: MediaRecorder? override fun onPause() { super.onPause() releaseMediaRecorder() // if you are using MediaRecorder, release it first releaseCamera() // release the camera immediately on pause event } private fun releaseMediaRecorder() { mediaRecorder?.reset() // clear recorder configuration mediaRecorder?.release() // release the recorder object mediaRecorder = null mCamera?.lock() // lock camera for later use } private fun releaseCamera() { mCamera?.release() // release the camera for other applications mCamera = null } }
Java
public class CameraActivity extends Activity { private Camera mCamera; private SurfaceView preview; private MediaRecorder mediaRecorder; ... @Override protected void onPause() { super.onPause(); releaseMediaRecorder(); // if you are using MediaRecorder, release it first releaseCamera(); // release the camera immediately on pause event } private void releaseMediaRecorder(){ if (mediaRecorder != null) { mediaRecorder.reset(); // clear recorder configuration mediaRecorder.release(); // release the recorder object mediaRecorder = null; mCamera.lock(); // lock camera for later use } } private void releaseCamera(){ if (mCamera != null){ mCamera.release(); // release the camera for other applications mCamera = null; } } }
Внимание! Если приложение не освободит камеру, все последующие попытки получить доступ к ней, в том числе со стороны вашего приложения, будут неудачными и могут привести к закрытию вашего или других приложений.
Сохранение медиафайлов
Медиафайлы, созданные пользователями, например фотографии и видео, следует сохранять в каталог внешнего хранилища устройства (SD-карту), чтобы экономить место в системе и позволить пользователям получать доступ к этим файлам без устройства. На устройстве есть много каталогов, в которых можно сохранять медиафайлы, но разработчикам следует учитывать только два стандартных:
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) – этот метод возвращает стандартное, общее и рекомендуемое местоположение для сохранения изображений и видео. Этот каталог является общим (общедоступным), поэтому другие приложения могут легко находить, читать, изменять и удалять файлы, сохраненные в этом месте. Если пользователь удалит ваше приложение, медиафайлы, сохраненные в этом каталоге, удалены не будут. Чтобы не мешать пользователям работать с их фотографиями и видео, создайте в этом каталоге подкаталог для медиафайлов вашего приложения, как показано в примере кода ниже. Этот метод доступен в Android 2.2 (уровень API 8). Эквивалентные вызовы в более ранних версиях API описаны в разделе Сохранение общих файлов.Context.getExternalFilesDir(Environment.DIRECTORY_PICTURES) – этот метод возвращает стандартное местоположение для сохранения изображений и видео, связанных с вашим приложением. Если приложение будет удалено, все файлы в этой папке также будут удалены. Безопасность файлов в этом месте не обеспечивается, и другие приложения могут читать, изменять и удалять их.
В следующем примере кода показано, как создать местоположение File или Uri для медиафайла, которое можно использовать при вызове камеры устройства с помощью Intent или в рамках создания приложения камеры.
Kotlin
val MEDIA_TYPE_IMAGE = 1 val MEDIA_TYPE_VIDEO = 2 /** Create a file Uri for saving an image or video */ private fun getOutputMediaFileUri(type: Int): Uri { return Uri.fromFile(getOutputMediaFile(type)) } /** Create a File for saving an image or video */ private fun getOutputMediaFile(type: Int): File? { // To be safe, you should check that the SDCard is mounted // using Environment.getExternalStorageState() before doing this. val mediaStorageDir = File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyCameraApp" ) // This location works best if you want the created images to be shared // between applications and persist after your app has been uninstalled. // Create the storage directory if it does not exist mediaStorageDir.apply { if (!exists()) { if (!mkdirs()) { Log.d("MyCameraApp", "failed to create directory") return null } } } // Create a media file name val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date()) return when (type) { MEDIA_TYPE_IMAGE -> { File("${mediaStorageDir.path}${File.separator}IMG_$timeStamp.jpg") } MEDIA_TYPE_VIDEO -> { File("${mediaStorageDir.path}${File.separator}VID_$timeStamp.mp4") } else -> null } }
Java
public static final int MEDIA_TYPE_IMAGE = 1; public static final int MEDIA_TYPE_VIDEO = 2; /** Create a file Uri for saving an image or video */ private static Uri getOutputMediaFileUri(int type){ return Uri.fromFile(getOutputMediaFile(type)); } /** Create a File for saving an image or video */ private static File getOutputMediaFile(int type){ // To be safe, you should check that the SDCard is mounted // using Environment.getExternalStorageState() before doing this. File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES), "MyCameraApp"); // This location works best if you want the created images to be shared // between applications and persist after your app has been uninstalled. // Create the storage directory if it does not exist if (! mediaStorageDir.exists()){ if (! mediaStorageDir.mkdirs()){ Log.d("MyCameraApp", "failed to create directory"); return null; } } // Create a media file name String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); File mediaFile; if (type == MEDIA_TYPE_IMAGE){ mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_"+ timeStamp + ".jpg"); } else if(type == MEDIA_TYPE_VIDEO) { mediaFile = new File(mediaStorageDir.getPath() + File.separator + "VID_"+ timeStamp + ".mp4"); } else { return null; } return mediaFile; }
Примечание. Класс Environment.getExternalStoragePublicDirectory() доступен в Android 2.2 (уровень API 8) и более поздних версиях. Если вы настраиваете таргетинг на устройства с более ранними версиями Android, используйте Environment.getExternalStorageDirectory(). Подробнее о сохранении общих файлов…
Чтобы URI поддерживал рабочие профили, сначала
преобразуйте URI файла в URI контента. Затем добавьте URI контента в EXTRA_OUTPUT объекта Intent.
Подробнее о сохранении файлов на устройстве Android…
Возможности камеры
Android поддерживает широкий спектр функций камеры, которыми можно управлять с помощью приложения камеры, например формат изображения, режим вспышки, настройки фокуса и многое другое. В этом разделе перечислены основные функции камеры и кратко описано, как ими пользоваться. Большинство функций камеры можно настроить с помощью объекта Camera.Parameters. Однако для работы некоторых важных функций недостаточно просто задать настройки в Camera.Parameters. Эти функции описаны в следующих разделах:
Общие сведения о том, как использовать функции, управляемые через Camera.Parameters, можно найти в разделе Возможности камеры. Чтобы узнать больше о том, как использовать функции, управляемые через объект параметров камеры, перейдите по ссылкам в списке функций ниже к справочной документации по API.
Таблица 1. Распространенные функции камеры, отсортированные по уровню Android API, в котором они были представлены.
| Функция | Уровень API | Описание |
|---|---|---|
| Распознавание лиц | 14 | Распознавание лиц на снимке и использование их для фокусировки, замера экспозиции и баланса белого. |
| Области замера | 14 | Укажите одну или несколько областей на изображении для расчета баланса белого |
| Области знаний | 14 | Укажите одну или несколько областей на изображении, которые нужно использовать для фокусировки. |
White Balance Lock |
14 | Как включить или отключить автоматическую настройку баланса белого |
Exposure Lock |
14 | Как включить или отключить автоматическую настройку экспозиции |
Video Snapshot |
14 | Как сделать снимок во время видеосъемки (захват кадра) |
| Ускоренное видео | 11 | Запись кадров с задержкой для создания ускоренного видео. |
Multiple Cameras |
9 | Поддержка нескольких камер на устройстве, включая фронтальную и основную. |
Focus Distance |
9 | Сообщает расстояние между камерой и объектами, которые находятся в фокусе. |
Zoom |
8 | Как настроить увеличение изображения |
Exposure
Compensation |
8 | Увеличить или уменьшить уровень экспозиции |
GPS Data |
5 | Включать или не включать в изображение данные о географическом местоположении. |
White Balance |
5 | Задайте режим баланса белого, который влияет на значения цветов на снимке. |
Focus Mode |
5 | Укажите, как камера фокусируется на объекте, например автоматически, фиксированно, в режиме макросъемки или бесконечности. |
Scene Mode |
5 | Применяйте предустановленные режимы для определенных типов съемки, например ночной, пляжной, снежной или при свечах. |
JPEG Quality |
5 | Установите уровень сжатия для изображения JPEG, который увеличивает или уменьшает качество и размер выходного файла изображения. |
Flash Mode |
5 | Как включить или отключить вспышку или использовать автоматический режим |
Color Effects |
5 | Примените к изображению цветовой эффект, например черно-белый, сепию или негатив. |
Anti-Banding |
5 | Уменьшает эффект полос в цветовых градиентах из-за сжатия JPEG |
Picture Format |
1 | Укажите формат файла для изображения. |
Picture Size |
1 | Укажите размеры сохраненного изображения в пикселях. |
Примечание. Эти функции поддерживаются не на всех устройствах из-за различий в аппаратном и программном обеспечении. Информацию о том, как проверить доступность функций на устройстве, на котором запущено ваше приложение, можно найти в разделе Проверка доступности функций.
Проверка доступности функции
Первое, что нужно понять, когда вы собираетесь использовать функции камеры на устройствах Android, это то, что не все функции камеры поддерживаются на всех устройствах. Кроме того, устройства, поддерживающие определенную функцию, могут поддерживать ее на разных уровнях или с разными параметрами. Поэтому при разработке приложения для камеры вам нужно решить, какие функции камеры вы хотите поддерживать и на каком уровне. После этого вам нужно будет добавить в приложение код, который проверяет, поддерживает ли устройство эти функции, и корректно обрабатывает ошибки, если они недоступны.
Чтобы проверить доступность функций камеры, получите экземпляр объекта параметров камеры и проверьте соответствующие методы. В приведенном ниже примере кода показано, как получить объект Camera.Parameters и проверить, поддерживает ли камера автофокусировку.
Kotlin
val params: Camera.Parameters? = camera?.parameters val focusModes: List<String>? = params?.supportedFocusModes if (focusModes?.contains(Camera.Parameters.FOCUS_MODE_AUTO) == true) { // Autofocus mode is supported }
Java
// get Camera parameters Camera.Parameters params = camera.getParameters(); List<String> focusModes = params.getSupportedFocusModes(); if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) { // Autofocus mode is supported }
Описанный выше способ подходит для большинства функций камеры. Объект Camera.Parameters предоставляет метод getSupported...(), is...Supported() или getMax...(), позволяющий определить, поддерживается ли функция и в какой степени.
Если для работы приложения требуются определенные функции камеры, вы можете указать их в манифесте. Если вы укажете, что в приложении используются определенные функции камеры, например вспышка и автофокус, Google Play не позволит устанавливать его на устройства, которые не поддерживают эти функции. Список функций камеры, которые можно объявить в манифесте приложения, приведен в справочнике по функциям.
Как использовать функции камеры
Большинство функций камеры активируются и управляются с помощью объекта Camera.Parameters. Чтобы получить этот объект, сначала получите экземпляр объекта Camera, вызовите метод getParameters(), измените возвращенный объект параметра и затем снова установите его в объект камеры, как показано в следующем примере кода:
Kotlin
val params: Camera.Parameters? = camera?.parameters params?.focusMode = Camera.Parameters.FOCUS_MODE_AUTO camera?.parameters = params
Java
// get Camera parameters Camera.Parameters params = camera.getParameters(); // set the focus mode params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); // set Camera parameters camera.setParameters(params);
Этот метод работает почти для всех функций камеры, и большинство параметров можно изменить в любое время после получения экземпляра объекта Camera. Изменения параметров обычно сразу видны пользователю в окне предварительного просмотра камеры приложения.
На программном уровне изменения параметров могут вступить в силу через несколько кадров, поскольку аппаратное обеспечение камеры обрабатывает новые инструкции, а затем отправляет обновленные данные изображения.
Важно! Некоторые функции камеры нельзя изменить по желанию. В частности, чтобы изменить размер или ориентацию предварительного просмотра камеры, необходимо сначала остановить предварительный просмотр, изменить размер предварительного просмотра, а затем перезапустить предварительный просмотр. Начиная с Android 4.0 (уровень API 14), ориентацию предварительного просмотра можно менять без перезапуска.
Для реализации других функций камеры требуется больше кода, в том числе:
- Области замера и фокусировки
- Распознавание лица
- Ускоренное видео
Ниже приведены краткие инструкции по реализации этих функций.
Области замера и фокусировки
В некоторых случаях автоматическая фокусировка и экспозамер могут не дать желаемых результатов. Начиная с Android 4.0 (уровень API 14), приложение камеры может предоставлять дополнительные элементы управления, позволяющие приложению или пользователям указывать области на изображении, которые будут использоваться для определения настроек фокуса или уровня освещенности, и передавать эти значения на аппаратное обеспечение камеры для использования при съемке изображений или видео.
Области экспозамера и фокусировки работают так же, как и другие функции камеры, и управляются с помощью методов объекта Camera.Parameters. В следующем примере кода показано, как задать две области экспозамера для экземпляра Camera:
Kotlin
// Create an instance of Camera camera = getCameraInstance() // set Camera parameters val params: Camera.Parameters? = camera?.parameters params?.apply { if (maxNumMeteringAreas > 0) { // check that metering areas are supported meteringAreas = ArrayList<Camera.Area>().apply { val areaRect1 = Rect(-100, -100, 100, 100) // specify an area in center of image add(Camera.Area(areaRect1, 600)) // set weight to 60% val areaRect2 = Rect(800, -1000, 1000, -800) // specify an area in upper right of image add(Camera.Area(areaRect2, 400)) // set weight to 40% } } camera?.parameters = this }
Java
// Create an instance of Camera camera = getCameraInstance(); // set Camera parameters Camera.Parameters params = camera.getParameters(); if (params.getMaxNumMeteringAreas() > 0){ // check that metering areas are supported List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>(); Rect areaRect1 = new Rect(-100, -100, 100, 100); // specify an area in center of image meteringAreas.add(new Camera.Area(areaRect1, 600)); // set weight to 60% Rect areaRect2 = new Rect(800, -1000, 1000, -800); // specify an area in upper right of image meteringAreas.add(new Camera.Area(areaRect2, 400)); // set weight to 40% params.setMeteringAreas(meteringAreas); } camera.setParameters(params);
Объект Camera.Area содержит два параметра данных: объект Rect для указания области в поле зрения камеры и значение веса, которое сообщает камере, какой уровень важности следует присвоить этой области при расчете экспозиции или фокусировки.
Поле Rect в объекте Camera.Area описывает прямоугольную фигуру, нанесенную на сетку размером 2000 x 2000 единиц. Координаты -1000, -1000 соответствуют верхнему левому углу изображения, а 1000, 1000 – нижнему правому, как показано на рисунке ниже.
Рисунок 1. Красные линии иллюстрируют систему координат для указания Camera.Area в предварительном просмотре камеры. Синий прямоугольник показывает расположение и форму области камеры со значениями Rect 333,333,667,667.
Границы этой системы координат всегда соответствуют внешнему краю изображения, видимого в окне предварительного просмотра камеры, и не уменьшаются и не расширяются в зависимости от уровня масштабирования. Аналогично, поворот предварительного просмотра изображения с помощью Camera.setDisplayOrientation() не меняет систему координат.
Распознавание лица
Если на снимке есть люди, то лица обычно являются самой важной частью изображения. При съемке они должны использоваться для определения фокуса и баланса белого. Фреймворк Android 4.0 (уровень API 14) предоставляет API для распознавания лиц и расчета настроек изображения с помощью технологии распознавания лиц.
Примечание. Пока работает функция распознавания лиц, setWhiteBalance(String), setFocusAreas(List<Camera.Area>) и setMeteringAreas(List<Camera.Area>) не действуют.
Чтобы использовать функцию распознавания лиц в приложении камеры, выполните следующие действия:
- Проверьте, поддерживается ли на устройстве распознавание лиц
- Создайте прослушиватель распознавания лиц.
- Добавьте прослушиватель распознавания лиц в объект камеры
- Запускайте распознавание лиц после предварительного просмотра (и после каждого перезапуска предварительного просмотра).
Функция распознавания лиц поддерживается не на всех устройствах. Чтобы проверить, поддерживается ли эта функция, вызовите getMaxNumDetectedFaces(). Пример такой проверки показан в методе startFaceDetection() ниже.
Чтобы получать уведомления и реагировать на обнаружение лица, в приложении камеры необходимо настроить прослушиватель событий распознавания лиц. Для этого создайте класс прослушивателя, который реализует интерфейс Camera.FaceDetectionListener, как показано в примере кода ниже.
Kotlin
internal class MyFaceDetectionListener : Camera.FaceDetectionListener { override fun onFaceDetection(faces: Array<Camera.Face>, camera: Camera) { if (faces.isNotEmpty()) { Log.d("FaceDetection", ("face detected: ${faces.size}" + " Face 1 Location X: ${faces[0].rect.centerX()}" + "Y: ${faces[0].rect.centerY()}")) } } }
Java
class MyFaceDetectionListener implements Camera.FaceDetectionListener { @Override public void onFaceDetection(Face[] faces, Camera camera) { if (faces.length > 0){ Log.d("FaceDetection", "face detected: "+ faces.length + " Face 1 Location X: " + faces[0].rect.centerX() + "Y: " + faces[0].rect.centerY() ); } } }
После создания этого класса вы устанавливаете его в объект Camera вашего приложения, как показано в примере кода ниже:
Kotlin
camera?.setFaceDetectionListener(MyFaceDetectionListener())
Java
camera.setFaceDetectionListener(new MyFaceDetectionListener());
Приложение должно запускать функцию распознавания лиц каждый раз, когда вы запускаете (или перезапускаете) предварительный просмотр камеры. Создайте метод для запуска распознавания лиц, чтобы вы могли вызывать его по мере необходимости, как показано в примере кода ниже.
Kotlin
fun startFaceDetection() { // Try starting Face Detection val params = mCamera?.parameters // start face detection only *after* preview has started params?.apply { if (maxNumDetectedFaces > 0) { // camera supports face detection, so can start it: mCamera?.startFaceDetection() } } }
Java
public void startFaceDetection(){ // Try starting Face Detection Camera.Parameters params = mCamera.getParameters(); // start face detection only *after* preview has started if (params.getMaxNumDetectedFaces() > 0){ // camera supports face detection, so can start it: mCamera.startFaceDetection(); } }
Распознавание лиц необходимо запускать каждый раз, когда вы начинаете (или перезапускаете) предварительный просмотр камеры. Если вы используете класс предварительного просмотра, показанный в разделе Создание класса предварительного просмотра, добавьте метод startFaceDetection() в методы surfaceCreated() и surfaceChanged() в классе предварительного просмотра, как показано в примере кода ниже.
Kotlin
override fun surfaceCreated(holder: SurfaceHolder) { try { mCamera.setPreviewDisplay(holder) mCamera.startPreview() startFaceDetection() // start face detection feature } catch (e: IOException) { Log.d(TAG, "Error setting camera preview: ${e.message}") } } override fun surfaceChanged(holder: SurfaceHolder, format: Int, w: Int, h: Int) { if (holder.surface == null) { // preview surface does not exist Log.d(TAG, "holder.getSurface() == null") return } try { mCamera.stopPreview() } catch (e: Exception) { // ignore: tried to stop a non-existent preview Log.d(TAG, "Error stopping camera preview: ${e.message}") } try { mCamera.setPreviewDisplay(holder) mCamera.startPreview() startFaceDetection() // re-start face detection feature } catch (e: Exception) { // ignore: tried to stop a non-existent preview Log.d(TAG, "Error starting camera preview: ${e.message}") } }
Java
public void surfaceCreated(SurfaceHolder holder) { try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); startFaceDetection(); // start face detection feature } catch (IOException e) { Log.d(TAG, "Error setting camera preview: " + e.getMessage()); } } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { if (holder.getSurface() == null){ // preview surface does not exist Log.d(TAG, "holder.getSurface() == null"); return; } try { mCamera.stopPreview(); } catch (Exception e){ // ignore: tried to stop a non-existent preview Log.d(TAG, "Error stopping camera preview: " + e.getMessage()); } try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); startFaceDetection(); // re-start face detection feature } catch (Exception e){ // ignore: tried to stop a non-existent preview Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } }
Примечание. Не забудьте вызвать этот метод после вызова startPreview(). Не пытайтесь запустить распознавание лиц в методе onCreate() основного действия приложения камеры, так как предварительный просмотр недоступен на этом этапе выполнения приложения.
Ускоренное видео
Ускоренное видео позволяет пользователям создавать видеоклипы, объединяющие снимки, сделанные с интервалом в несколько секунд или минут. Эта функция использует MediaRecorder для записи изображений для последовательности ускорения.
Чтобы записать ускоренное видео с помощью MediaRecorder, настройте объект записи так же, как для обычного видео, но задайте низкое количество кадров в секунду и используйте одну из настроек качества ускоренного видео, как показано в примере кода ниже.
Kotlin
mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH)) mediaRecorder.setCaptureRate(0.1) // capture a frame every 10 seconds
Java
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher) mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH)); ... // Step 5.5: Set the video capture rate to a low number mediaRecorder.setCaptureRate(0.1); // capture a frame every 10 seconds
Эти настройки необходимо задать в рамках более крупной процедуры настройки для MediaRecorder. Полный пример кода конфигурации приведен в разделе Настройка MediaRecorder. После завершения настройки вы начинаете видеозапись, как если бы вы записывали обычный видеоклип. Подробную информацию о настройке и запуске MediaRecorder можно найти в статье Запись видео.
Примеры Camera2Video и HdrViewfinder демонстрируют использование API, описанных на этой странице.
Поля камеры, для которых требуется разрешение
Приложениям для Android 10 (уровень API 29) или более поздней версии требуется разрешение CAMERA, чтобы получать доступ к значениям следующих полей, возвращаемых методом getCameraCharacteristics():
LENS_POSE_ROTATIONLENS_POSE_TRANSLATIONLENS_INTRINSIC_CALIBRATIONLENS_RADIAL_DISTORTIONLENS_POSE_REFERENCELENS_DISTORTIONLENS_INFO_HYPERFOCAL_DISTANCELENS_INFO_MINIMUM_FOCUS_DISTANCESENSOR_REFERENCE_ILLUMINANT1SENSOR_REFERENCE_ILLUMINANT2SENSOR_CALIBRATION_TRANSFORM1SENSOR_CALIBRATION_TRANSFORM2SENSOR_COLOR_TRANSFORM1SENSOR_COLOR_TRANSFORM2SENSOR_FORWARD_MATRIX1SENSOR_FORWARD_MATRIX2
Дополнительные примеры кода
Чтобы скачать примеры приложений, перейдите по ссылкам Camera2Basic sample и Official CameraX sample app.