Interfejs API aparatu

Platforma Androida zapewnia obsługę różnych aparatów i funkcji aparatu dostępnych urządzeń, dzięki czemu możesz robić zdjęcia i nagrywać filmy w aplikacjach. W tym dokumencie omówiono szybkie i proste podejście do robienia zdjęć i nagrywania filmów. z aparatem dostosowanym do potrzeb użytkowników.

Uwaga: Na tej stronie dowiesz się: Camera klasa, która została wycofana. Zalecamy użycie metody CameraX; z biblioteki Jetpack lub, w określonych przypadkach, camera2, zajęcia. Zarówno AparatX, jak i Aparat2 działają na Androidzie 5.0 (poziom interfejsu API 21) oraz wyżej.

Zapoznaj się z tymi powiązanymi materiałami:

co należy wziąć pod uwagę

Zanim pozwolisz aplikacji na korzystanie z aparatów na urządzeniach z Androidem, rozważ kilka pytania na temat tego, w jaki sposób aplikacja będzie korzystać z tej funkcji sprzętowej.

  • Wymagania dotyczące aparatu – czy korzystanie z kamery jest tak ważne Aplikacja, której nie chcesz instalować na urządzeniu bez aparat? Jeśli tak, musisz zadeklarować wymagania dotyczące aparatu na swoim pliku manifestu.
  • Szybki obraz lub niestandardowy aparat – w jaki sposób aplikacja będzie korzystać z funkcji aparat? Chcesz zrobić krótkie zdjęcie lub klip wideo? A może Twoja aplikacja a my stworzyła nowy sposób korzystania z aparatów? Aby szybko zrobić zdjęcie lub klip, zastanów się: Korzystanie z istniejących aplikacji aparatu. Aby opracować niestandardową funkcję aparatu, zapoznaj się z artykułem zapoznaj się z sekcją Tworzenie aplikacji aparatu.
  • Wymagania dotyczące usług działających na pierwszym planie – kiedy Twoja aplikacja wchodzi w interakcję z przez kamerę? Na Androidzie 9 (poziom interfejsu API 28) i nowszych aplikacje działające w Tło nie może uzyskać dostępu do aparatu. Dlatego należy używać aparatu gdy aplikacja działa na pierwszym planie lub usługę działającą na pierwszym planie.
  • Pamięć wewnętrzna – czy obrazy lub filmy mają być generowane przez aplikację widoczne tylko dla aplikacji lub udostępniane, aby inne aplikacje, takie jak media i aplikacje społecznościowe mogą z nich korzystać? Czy chcesz, aby zdjęcia i filmy były dostępne, nawet jeśli aplikacja została odinstalowana? Zapoznaj się z sekcją Zapisywanie plików multimedialnych, aby zobacz, jak wdrożyć te opcje.

Podstawy

Platforma Androida obsługuje przechwytywanie obrazów i filmów za pomocą android.hardware.camera2 API lub kamera Intent. Oto istotne zajęcia:

android.hardware.camera2
Ten pakiet jest podstawowym interfejsem API do sterowania kamerami urządzenia. Może służyć do podejmowania zdjęć lub filmów wideo podczas tworzenia aplikacji aparatu.
Camera
Ta klasa to starszy wycofany interfejs API do sterowania kamerami urządzenia.
SurfaceView
Te zajęcia służą do prezentowania użytkownikowi podglądu z kamery na żywo.
MediaRecorder
Te zajęcia służą do nagrywania obrazu z kamery.
Intent
Działanie typu MediaStore.ACTION_IMAGE_CAPTURE lub MediaStore.ACTION_VIDEO_CAPTURE może być używane do robienia zdjęć i filmów bez bezpośredniego przy użyciu obiektu Camera.

Deklaracje w pliku manifestu

Zanim zaczniesz programować przy użyciu interfejsu Camera API, upewnij się, plik manifestu zawiera odpowiednie deklaracje pozwalające na korzystanie ze sprzętu kamery i innych powiązane funkcje.

  • Uprawnienia dotyczące aparatu – aplikacja musi prosić o pozwolenie na korzystanie z urządzenia aparat fotograficzny.
    <uses-permission android:name="android.permission.CAMERA" />
    

    Uwaga: jeśli używasz kamery przez wywołanie istniejącej aplikacji aparatu, Twoja aplikacja nie musi żądać tego uprawnienia.

  • Funkcje aparatu – w aplikacji musisz też zadeklarować korzystanie z funkcji aparatu, np.:
    <uses-feature android:name="android.hardware.camera" />
    

    Listę funkcji aparatu znajdziesz w pliku manifestu Funkcje Plik referencyjny.

    Dodanie funkcji aparatu do pliku manifestu powoduje, że Google Play uniemożliwia aplikacji na urządzeniach, które nie mają kamery lub nie obsługują jej funkcji określić. Więcej informacji o używaniu filtrowania na podstawie cech w Google Play znajdziesz w sekcji Google Play Play i filtrowanie oparte na funkcjach.

    jeśli aplikacja może używać jej funkcji do prawidłowego działania, ale nie nie są wymagane, określ to w pliku manifestu, dodając atrybut android:required i ustawiając dla niego wartość false:

    <uses-feature android:name="android.hardware.camera" android:required="false" />
    
  • Uprawnienie do pamięci – aplikacja może zapisywać obrazy i filmy w pamięci zewnętrznej urządzenia (karty SD), jeśli jest ona kierowana na Androida 10 (poziom interfejsu API 29) lub i określa w pliku manifestu te elementy.
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    
  • Uprawnienia do nagrywania dźwięku – w przypadku nagrywania dźwięku z obrazem aplikacja musi prosić o uprawnienia do przechwytywania dźwięku.
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    
  • Pozwolenie na lokalizację – jeśli aplikacja taguje obrazy z informacjami o lokalizacji GPS, musisz wysłać prośbę o ACCESS_FINE_LOCATION uprawnienia. Pamiętaj, że jeśli aplikacja jest kierowana na Androida 5.0 (poziom interfejsu API 21) lub wyżej, musisz też zadeklarować, że aplikacja używa GPS-a urządzenia:

    <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" />
    

    Więcej informacji o uzyskiwaniu lokalizacji użytkownika znajdziesz w sekcji Strategie lokalizacji.

Korzystanie z istniejących aplikacji aparatu

Szybki sposób na robienie zdjęć i nagrywanie filmów w aplikacji bez konieczności pisania dużych ilości kodu to użycie Intent do wywołania istniejącej aplikacji aparatu na Androida. Szczegóły są opisane w wykładach szkoleniowych Proste robienie zdjęć Proste nagrywanie filmów.

Tworzę aplikację aparatu

Niektórzy deweloperzy mogą wymagać interfejsu użytkownika kamery dostosowanego do wyglądu aplikacji lub oferuje specjalne funkcje. Pisanie własnego kodu do robienia zdjęć może być atrakcyjniejsza dla użytkowników.

Uwaga: ten przewodnik dotyczy starszych, wycofanych wersji Camera API. W przypadku nowych i zaawansowanych aplikacji aparatu nowszy interfejs API android.hardware.camera2 to .

Ogólne kroki tworzenia interfejsu aparatu niestandardowego na potrzeby aplikacji są następujące:

  • Wykryj kamerę i uzyskaj dostęp do niej – utwórz kod, aby sprawdzić, czy i poprosić o dostęp.
  • Utwórz klasę podglądu – utwórz klasę podglądu kamery, która rozszerza język SurfaceView i implementuje interfejs SurfaceHolder. Ten podczas lekcji wyświetli podgląd obrazów z kamery.
  • Utwórz układ podglądu – gdy masz już klasę podglądu aparatu, utwórz który obejmuje podgląd i wybrane elementy interfejsu.
  • Skonfiguruj detektory przechwytywania – połącz detektory dla swojego interfejsu. elementów sterujących do rozpoczynania nagrywania obrazów i filmów w odpowiedzi na działania użytkownika, takie jak naciśnięcie Przycisk
  • Przechwyć i zapisz pliki – skonfiguruj kod do robienia zdjęć lub filmy i zapisanie wyników.
  • Zwalnianie aparatu – po użyciu aparatu aplikacja musi: i umożliwić jej używanie w innych aplikacjach.

Kamera to zasób współdzielony, którym trzeba odpowiednio zarządzać, aby aplikacja działała. w taki sposób, aby nie kolidowały z innymi aplikacjami, które również mogą zechcieć z niego korzystać. W poniższych sekcjach omówiono jak wykryć sprzęt z aparatu, jak poprosić o dostęp do aparatu, jak robić zdjęcia lub nagrywać filmy i jak ją zwolnić.

Uwaga: pamiętaj, by zwolnić Camera przez wywołanie Camera.release(), gdy można za jej pomocą zakończyć korzystanie z aplikacji. Jeśli aplikacja nie uruchomi poprawnie aparatu, kolejne próby dostępu do kamery, również te realizowane przez Twoją aplikację, zakończą się niepowodzeniem i mogą może spowodować wyłączenie aplikacji lub innych aplikacji.

Wykrywam aparat

Jeśli Twoja aplikacja nie wymaga użycia aparatu przy użyciu deklaracji w pliku manifestu, powinien sprawdzić, czy kamera jest dostępna w czasie działania. Aby to zrobić, użyj metody PackageManager.hasSystemFeature() zgodnie z przykładowym kodem poniżej:

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;
    }
}

Urządzenia z Androidem mogą mieć kilka aparatów, na przykład tylny aparat fotograficzny przednim aparatem do rozmów wideo. Android 2.3 (poziom interfejsu API 9) i nowsze umożliwiają sprawdzenie liczba kamer dostępnych na urządzeniu za pomocą metody Camera.getNumberOfCameras().

Dostęp do kamer

Jeśli okaże się, że urządzenie, na którym działa aplikacja, ma kamerę, musi zażądać dostępu do niego przez pobranie instancji Camera (chyba że używają zamiaru dostępu do kamery).

Aby uzyskać dostęp do aparatu głównego, użyj metody Camera.open() i pamiętaj o wykrywaniu wszelkich wyjątków, tak jak w poniższym kodzie:

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
}

Uwaga: jeśli używasz Camera.open(), zawsze sprawdzaj wyjątki. Nie udało się sprawdzić wyjątków, jeśli kamera jest włączona lub jeśli nie istnieje, spowoduje to wyłączenie aplikacji przez system.

Na urządzeniach z Androidem 2.3 (poziom interfejsu API 9) lub nowszym dostęp do określonych aparatów możesz uzyskać za pomocą Camera.open(int) Powyższy przykładowy kod umożliwia dostęp pierwszy tylny aparat w urządzeniu z więcej niż 1 aparatem.

Sprawdzam funkcje aparatu

Gdy już uzyskasz dostęp do kamery, możesz dowiedzieć się więcej o jej możliwościach w metody Camera.getParameters() i sprawdź zwrócił obiekt Camera.Parameters, aby uzyskać obsługiwane funkcje. W przypadku użycia funkcji Interfejs API na poziomie 9 lub wyższym: użyj interfejsu Camera.getCameraInfo(), aby określić, czy kamera jest z przodu lub tylnej części urządzenia oraz orientację zdjęcia.

Tworzenie zajęć w wersji testowej

Aby użytkownicy mogli wykonywać zdjęcia i nagrywać filmy, muszą mieć możliwość zobaczenia obrazu z aparatu urządzenia. który widzi. Klasa podglądu aparatu to obiekt SurfaceView, który może wyświetlać obraz na żywo z aparatu, dzięki czemu użytkownicy mogą wykadrować i nagrać zdjęcie lub nagrać film.

Ten przykładowy kod pokazuje, jak utworzyć podstawową klasę podglądu aparatu, którą można zawarte w układzie View. Ta klasa implementuje funkcję SurfaceHolder.Callback, aby przechwytywać zdarzenia wywołania zwrotnego do tworzenia i niszczenia widoku, które są potrzebne do przypisywania danych wejściowych podglądu z kamery.

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());
        }
    }
}

Jeśli chcesz ustawić konkretny rozmiar podglądu z aparatu, ustaw go w metodzie surfaceChanged() zgodnie z opisem w komentarzach powyżej. Ustawiając rozmiar podglądu, musi używać wartości z getSupportedPreviewSizes(). Nie ustawiaj dowolnych wartości w metodzie setPreviewSize().

Uwaga: Dzięki wprowadzeniu funkcji wielu okien w Androidzie 7.0 (poziom interfejsu API 24) i nowszych, Zakładamy, że format obrazu podglądu jest taki sam jak w przypadku aktywności nawet po połączeniu telefonu z numerem setDisplayOrientation(). W zależności od rozmiaru okna i formatu obrazu konieczne może być dopasowanie do podglądu z aparatu w układzie pionowym lub odwrotnie, letterbox.

Umieszczanie podglądu w układzie

Klasa podglądu z aparatu, jak w przykładzie z poprzedniej sekcji, musi być umieszczona w polu układ aktywności wraz z innymi opcjami interfejsu do robienia zdjęcia lub nagrywania filmów. Ten pokazuje, jak utworzyć podstawowy układ i aktywność na potrzeby podglądu.

Poniższy kod układu zapewnia podstawowy widok, który można wykorzystać do wyświetlenia kamery podgląd. W tym przykładzie element FrameLayout ma być dla klasy podglądu z użyciem aparatu. Ten typ układu jest używany, aby dodatkowe zdjęcie informacje lub elementy sterujące można nałożyć na obrazy podglądu z kamery na żywo.

<?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>

Na większości urządzeń domyślna orientacja podglądu aparatu to pozioma. Ten przykładowy układ określa układ poziomy (poziomy), a poniższy kod ustawia orientację aplikacji w orientacji poziomej. Aby ułatwić renderowanie podglądu z aparatu, należy zmienić ustaw orientację działania podglądu aplikacji na poziomą. W tym celu dodaj ten fragment pliku manifestu.

<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>

Uwaga: podgląd z aparatu nie musi być w trybie poziomym. Począwszy od Androida w wersji 2.2 (poziom interfejsu API 8) możesz używać metody setDisplayOrientation() do konfigurowania przez obrót obrazu podglądu. Aby zmienić orientację podglądu, gdy użytkownik zmieni orientację w ramach metody surfaceChanged() klasy podglądu najpierw zatrzymaj podgląd przy użyciu polecenia Camera.stopPreview(), a następnie zmień orientację, a następnie ponownie włącz podgląd, wybierając Camera.startPreview().

W aktywności związanej z widokiem z kamery dodaj klasę podglądu do elementu FrameLayout widocznego w powyższym przykładzie. Aktywność kamery musi też obejmować aby ją zwolnił, gdy jest wstrzymany lub wyłączony. Ten przykład pokazuje, aby zmodyfikować aktywność kamery i dołączyć klasę podglądu widoczną w sekcji Tworzenie podglądu.

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);
    }
}

Uwaga: metoda getCameraInstance() w przykładzie powyżej odnosi się do przykładowej metody przedstawionej w sekcji Uzyskiwanie dostępu do aparatów.

Robię zdjęcia

Po utworzeniu klasy podglądu i układu widoku, w którym chcesz ją wyświetlać, możesz rozpocząć robienie obrazów za pomocą aplikacji. W kodzie aplikacji musisz skonfigurować detektory aby elementy sterujące interfejsu mogły reagować na działanie użytkownika poprzez zrobienie zdjęcia.

Aby pobrać zdjęcie, użyj metody Camera.takePicture(). Ta metoda wykorzystuje 3 parametry, które odbierają dane z kamery. Aby otrzymywać dane w formacie JPEG, musisz wdrożyć interfejs Camera.PictureCallback do odbierania danych obrazu i zapisać go w pliku. Poniższy kod przedstawia podstawową implementację interfejsu Camera.PictureCallback w celu zapisywania obrazu otrzymanego z aparatu.

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());
        }
    }
};

Aby aktywować przechwytywanie obrazu, wywołaj metodę Camera.takePicture(). Poniższy przykładowy kod pokazuje, jak wywołać tę metodę z poziomu przycisk 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);
        }
    }
);

Uwaga: do nazwy odnosi się użytkownik mPicture z poniższego przykładu. do powyższego przykładowego kodu.

Uwaga: pamiętaj, by zwolnić Camera przez wywołanie Camera.release(), gdy można za jej pomocą zakończyć korzystanie z aplikacji. Informacje na temat zwalniania aparatu znajdziesz w sekcji Zwalnianie aparatu.

Nagrywanie filmów

Nagrywanie filmów przy użyciu platformy Androida wymaga starannego zarządzania obiektem Camera i koordynacji z platformą MediaRecorder zajęcia. Podczas nagrywania filmów za pomocą urządzenia Camera musisz zarządzać połączeniami Camera.lock() i Camera.unlock(), aby zezwolić aplikacji MediaRecorder na dostęp do kamery. oprócz połączeń Camera.open() i Camera.release().

Uwaga: od Androida 4.0 (poziom interfejsu API 14) wywołania Camera.lock() i Camera.unlock() są zarządzane automatycznie.

W przeciwieństwie do robienia zdjęć aparatem urządzenia, nagrywanie filmów wymaga konkretnego połączenia. zamówienie. Aby prawidłowo przygotować film i nagrać go, musisz postępować zgodnie z określoną kolejnością ich wykonania. zgodnie z poniższym opisem.

  1. Otwórz aparat – użyj Camera.open() aby pobrać instancję obiektu Camera.
  2. Podłącz podgląd – przygotuj podgląd obrazu z kamery na żywo, podłączając SurfaceView do aparatu za pomocą Camera.setPreviewDisplay().
  3. Rozpocznij podgląd – wywołaj Camera.startPreview(), by rozpocząć wyświetlanie obrazów na żywo z kamery.
  4. Rozpocznij nagrywanie filmu – poniższe czynności należy wykonać w zamówienie, aby nagrać film:
    1. Odblokuj aparat – odblokuj aparat i korzystaj z niego do MediaRecorder, dzwoniąc pod numer Camera.unlock().
    2. Skonfiguruj MediaRecorder – wywołaj poniższe metody MediaRecorder w tej kolejności. Więcej informacji znajdziesz w dokumentacji referencyjnej MediaRecorder.
      1. setCamera() – ustaw kamerę, która będzie używana do nagrywania wideo. Użyj bieżącej instancji aplikacji. z Camera.
      2. setAudioSource() – ustaw wartość źródła dźwięku, użyj formatu MediaRecorder.AudioSource.CAMCORDER.
      3. setVideoSource() – ustaw źródła wideo, użyj MediaRecorder.VideoSource.CAMERA.
      4. Ustaw format i kodowanie wyjściowe wideo. Na Androida 2.2 (poziom interfejsu API 8) użyj metody MediaRecorder.setProfile i pobierz wystąpienie profilu za pomocą CamcorderProfile.get(). Wersje Androida starsze 2.2, należy ustawić format wyjściowy wideo i parametry kodowania:
        1. setOutputFormat() – ustaw format wyjściowy, określ ustawienie domyślne lub MediaRecorder.OutputFormat.MPEG_4.
        2. setAudioEncoder() – ustaw typ kodowania dźwięku, określ ustawienie domyślne lub MediaRecorder.AudioEncoder.AMR_NB.
        3. setVideoEncoder() – ustaw typ kodowania wideo, określ ustawienie domyślne lub MediaRecorder.VideoEncoder.MPEG_4_SP.
      5. setOutputFile() – Ustaw plik wyjściowy, użyj pola getOutputMediaFile(MEDIA_TYPE_VIDEO).toString() z przykładu w sekcji Zapisywanie plików multimedialnych.
      6. setPreviewDisplay() – określ element układu podglądu SurfaceView dla Twojej aplikacji. Użyj tego samego obiektu, który został podany w podglądzie połączenia.

      Uwaga: te metody konfiguracji MediaRecorder musisz wywoływać w tej kolejności. W przeciwnym razie aplikacja napotka błędy, a nagrywanie się nie uda.

    3. Prepare MediaRecorder – przygotowywanie MediaRecorder z podanymi ustawieniami konfiguracji przez wywołanie metody MediaRecorder.prepare().
    4. Uruchom MediaRecorder – rozpocznij nagrywanie filmu, dzwoniąc pod numer MediaRecorder.start().
  5. Zatrzymaj nagrywanie filmu – wywołaj poniższe metody w odpowiedniej kolejności, aby Zakończył nagrywanie filmu:
    1. Zatrzymaj MediaRecorder – zatrzymaj nagrywanie filmu, wywołując MediaRecorder.stop().
    2. Resetuj MediaRecorder – opcjonalnie usuń ustawienia konfiguracji z dyktafon, dzwoniąc pod numer MediaRecorder.reset().
    3. Release MediaRecorder – zwolnij MediaRecorder dzwoniąc pod numer MediaRecorder.release().
    4. Zablokuj kamerę – zablokuj kamerę, aby kolejne sesje MediaRecorder mogły z niej korzystać, wywołując funkcję Camera.lock(). Od Androida 4.0 (poziom interfejsu API 14) to wywołanie nie jest wymagane, chyba że funkcja MediaRecorder.prepare() nieudane połączenie.
  6. Zatrzymaj podgląd – gdy zakończysz aktywność z użyciem kamery, zatrzymaj wyświetlić podgląd w elemencie Camera.stopPreview().
  7. Zwolnij aparat – puść aparat, by umożliwić korzystanie z innych aplikacji go, dzwoniąc pod numer Camera.release().

Uwaga: możesz użyć MediaRecorder bez tworzenia podglądu z kamery i pomiń kilka pierwszych kroków tego procesu. Pamiętaj jednak: użytkownicy zwykle wolą zobaczyć podgląd przed rozpoczęciem nagrywania, więc które tu omawiamy.

Wskazówka: jeśli Twoja aplikacja zwykle służy do nagrywania filmów, ustaw setRecordingHint(boolean) do true przed rozpoczęciem podgląd. To ustawienie może skrócić czas potrzebny na rozpoczęcie nagrywania.

Konfigurowanie funkcji MediaRecorder

Jeśli używasz klasy MediaRecorder do nagrywania filmu, musisz wykonać w określonej kolejności, a potem wywołaj metodę MediaRecorder.prepare(), aby sprawdzić i zaimplementować konfiguracji. Poniższy przykładowy kod pokazuje, jak prawidłowo skonfigurować i przygotować MediaRecorder zajęcia do nagrywania wideo.

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;
}

Przed Androidem 2.2 (poziom interfejsu API 8) trzeba ustawiać format wyjściowy i formaty kodowania bezpośrednio, zamiast używać parametru CamcorderProfile. To podejście w tym kodzie:

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);

Podane są te parametry nagrywania wideo dla: MediaRecorder domyślnych, ale możesz też dostosować do swojej aplikacji te ustawienia:

Uruchamianie i zatrzymywanie MediaRecorder

Gdy rozpoczynasz i zatrzymujesz nagrywanie filmu za pomocą klasy MediaRecorder: należy wykonać określoną kolejność, jak podano poniżej.

  1. Odblokuj aparat za pomocą aplikacji Camera.unlock()
  2. Skonfiguruj MediaRecorder w sposób pokazany w powyższym przykładzie kodu
  3. Zacznij nagrywać za pomocą urządzenia MediaRecorder.start()
  4. Nagraj film
  5. Zatrzymaj nagrywanie za pomocą MediaRecorder.stop()
  6. Zwolnij nagrywarkę multimediów za pomocą funkcji MediaRecorder.release()
  7. Zablokuj aparat za pomocą funkcji Camera.lock()

Ten przykładowy kod pokazuje, jak podłączyć przycisk, aby prawidłowo uruchamiał i zatrzymał się nagrywanie filmów za pomocą kamery i klasy MediaRecorder.

Uwaga: podczas nagrywania filmu nie puść kamery. W przeciwnym razie podgląd zostanie zatrzymany.

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
                }
            }
        }
    }
);

Uwaga: w tym przykładzie prepareVideoRecorder() odnosi się do przykładowego kodu widocznego w sekcji Konfigurowanie MediaRecorder. Ta metoda umożliwia blokowanie kamery oraz konfigurowania i przygotowywania instancji MediaRecorder.

Zwalniam aparat

Kamery to zasób, z którego korzystają aplikacje zainstalowane na urządzeniu. Twoja aplikacja może użycia kamery po uzyskaniu wystąpienia Camera i musisz szczególnie uważaj na zwolnienie obiektu aparatu, gdy aplikacja przestanie go używać. po wstrzymaniu aplikacji (Activity.onPause()). Jeśli aplikacja nie zwalnia poprawnie kamery przy wszystkich kolejnych próbach jej uzyskania, również tych, które zostały utworzone przez Ciebie, nie będą działać i mogą spowodować wyłączyć.

Aby uruchomić wystąpienie obiektu Camera, użyj metody Camera.release(), jak pokazano w przykładowym kodzie poniżej.

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;
        }
    }
}

Uwaga: jeśli aplikacja nie uruchomi poprawnie kodu kamery, wszystkie kolejne próby uzyskania dostępu do kamery, również te wykonywane przez Twoją aplikację, może dojść do wyłączenia aplikacji lub innych aplikacji.

Zapisuję pliki multimedialne

Pliki multimedialne utworzone przez użytkowników (np. zdjęcia i filmy) powinny być zapisywane na zewnętrznym urządzeniu katalog pamięci masowej (karta SD), aby oszczędzać miejsce w systemie i umożliwić użytkownikom dostęp do tych plików. bez urządzeń mobilnych. Jest wiele możliwych lokalizacji katalogów, w których można zapisać pliki multimedialne na urządzeniu, Pamiętaj jednak, że jako programista musisz wziąć pod uwagę tylko 2 standardowe lokalizacje:

  • Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) – ta metoda zwraca standardową, udostępnioną i zalecaną metodę. miejsca zapisywania zdjęć i filmów. Ten katalog jest udostępniony (publiczny), więc inne aplikacje mogą łatwo wykrywać, czytać, zmieniać i usuwać pliki zapisane w tej lokalizacji. Jeśli Twoja aplikacja to ale to użytkownik odinstaluje aplikację, pliki multimedialne zapisane w tej lokalizacji nie zostaną usunięte. Aby unikać ingerencji w istniejące zdjęcia i filmy użytkowników, należy utworzyć podkatalog dla pliki multimedialne aplikacji w tym katalogu, jak widać w poniższym przykładzie kodu. Ta metoda jest dostępne w Androidzie 2.2 (poziom interfejsu API 8). Informacje o równoważnych wywołaniach we wcześniejszych wersjach interfejsu API znajdziesz w sekcji Zapisywanie udostępnionych plików.
  • Context.getExternalFilesDir(Environment.DIRECTORY_PICTURES) – ta metoda zwraca standardową lokalizację zapisu. zdjęcia i filmy powiązane z Twoją aplikacją. Jeśli aplikacja zostanie odinstalowana, wszystkie pliki zapisane w tej lokalizacji zostaną usunięte. Zabezpieczenia nie są wymuszane dla plików w tej lokalizacji i innych aplikacji mogą je odczytywać, zmieniać oraz usuwać.

Ten przykładowy kod pokazuje, jak utworzyć lokalizację File lub Uri dla pliku multimedialnego, której można użyć przy wywoływaniu aparatu urządzenia za pomocą Intent lub w ramach budowania kamery Aplikacja.

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;
}

Uwaga: usługa Environment.getExternalStoragePublicDirectory() jest dostępna w Androidzie 2.2 (poziom API 8) oraz wyżej. Jeśli kierujesz reklamy na urządzenia z wcześniejszymi wersjami Androida, użyj zasady Environment.getExternalStorageDirectory() . Więcej informacji znajdziesz w artykule Zapisywanie udostępnionych plików.

Aby identyfikator URI obsługiwał profile służbowe, najpierw skonwertują identyfikator URI pliku na identyfikator URI treści. Następnie dodaj identyfikator URI treści do EXTRA_OUTPUT Intent.

Więcej informacji o zapisywaniu plików na urządzeniu z Androidem znajdziesz w artykule Przechowywanie danych.

Funkcje aparatu

Android obsługuje szeroką gamę funkcji aparatu, którymi możesz sterować za pomocą aplikacji. takich jak format obrazu, tryb lampy błyskowej, ustawienia ostrości i wiele innych. W tej sekcji znajdziesz typowe z aparatem i krótkim omówieniem tego, jak z nich korzystać. Można korzystać z większości funkcji aparatu i ustawić je za pomocą obiektu do obsługi zdarzeń Camera.Parameters. Dostępnych jest jednak kilka ważnych funkcji, które wymagają czegoś więcej niż prostych ustawień w usłudze Camera.Parameters. Funkcje te są opisane w tych sekcjach:

Ogólne informacje o korzystaniu z funkcji kontrolowanych za pomocą Camera.Parameters znajdziesz w artykule Korzystanie z aparatu funkcje. Więcej informacji o korzystaniu z funkcji kontrolowanych za pomocą kamery parametrów kamery, skorzystaj z linków na liście funkcji poniżej, aby przejść do dokumentacji API dokumentacji.

Tabela 1. Wspólne funkcje aparatu posortowane według poziomu interfejsu API Androida, na którym zostały wprowadzone.

Funkcja Poziom API Opis
Wykrywanie twarzy 14 Rozpoznawaj ludzkie twarze na zdjęciu i używaj ich do ustawiania ostrości, pomiaru oraz bieli saldo
Obszary pomiaru 14 Określ co najmniej jeden obszar zdjęcia do obliczania balansu bieli
Obszary specjalizacji 14 Ustaw co najmniej jeden obszar obrazu, który będzie używany do ostrości
White Balance Lock 14 Zatrzymywanie i uruchamianie automatycznej korekty balansu bieli
Exposure Lock 14 Zatrzymywanie i uruchamianie automatycznych korekt ekspozycji
Video Snapshot 14 Robienie zdjęcia podczas nagrywania filmu (zrzut klatki)
Film w trybie poklatkowym 11 Nagrywaj klatki z ustawionym opóźnieniem, aby nagrywać filmy w trybie poklatkowym
Multiple Cameras 9 obsługa więcej niż 1 aparatu w urządzeniu, w tym przedniego i tylnego aparatu; kamery
Focus Distance 9 Informuje o odległości między aparatem a obiektami, które są na pierwszym planie
Zoom 8 Ustaw powiększenie obrazu
Exposure Compensation 8 Zwiększ lub zmniejsz poziom ekspozycji na światło
GPS Data 5 Dołączaj lub pomijaj dane o lokalizacji geograficznej na zdjęciu
White Balance 5 Ustaw tryb balansu bieli, który ma wpływ na wartości kolorów na robionym zdjęciu.
Focus Mode 5 Ustawianie ostrości aparatu na obiekcie – na przykład automatyczne, stałe, makro lub nieskończoność
Scene Mode 5 Zastosowanie trybu gotowych ustawień w określonych sytuacjach, na przykład w nocy, na plaży czy w śniegu. lub scenami przy świecach
JPEG Quality 5 Ustaw poziom kompresji obrazu JPEG, który zwiększa lub zmniejsza wyjściowy plik graficzny jakość i rozmiar
Flash Mode 5 Włączanie i wyłączanie lampy błyskowej oraz używanie ustawień automatycznych
Color Effects 5 Zastosuj efekt kolorystyczny do zdjęcia, taki jak czarno-biały, w odcieniu sepii lub negatyw.
Anti-Banding 5 Ogranicza efekt pasów w gradientach kolorów spowodowanych kompresją JPEG.
Picture Format 1 Określ format pliku zdjęcia
Picture Size 1 Określ wymiary zapisanego obrazu w pikselach.

Uwaga: te funkcje nie są obsługiwane na wszystkich urządzeniach z powodu różnice dotyczące sprzętu i implementacji oprogramowania. Informacje o sprawdzaniu dostępności funkcji urządzenia, na którym działa aplikacja, patrz sekcja Sprawdzanie, czy dostępności funkcji.

Sprawdzam dostępność funkcji

Zanim zaczniesz korzystać z funkcji aparatu na urządzeniach z Androidem, warto wiedzieć, Nie wszystkie funkcje aparatu są obsługiwane na wszystkich urządzeniach. Ponadto urządzenia obsługujące określony mogą obsługiwać różne poziomy lub opcje. Dlatego też część procesu decyzyjnego przy opracowywaniu aplikacji do obsługi kamery jest wybór funkcji kamery, które chcesz i na jakim poziomie. Po podjęciu decyzji warto umieścić kod w swojej witrynie aplikacja aparatu, która sprawdza, czy sprzęt urządzenia obsługuje te funkcje, ale kończy się niepowodzeniem. jeśli jakaś funkcja nie jest dostępna.

Aby sprawdzić dostępność funkcji kamery, pobierz wystąpienie jej parametrów i sprawdzanie odpowiednich metod. Poniższy przykładowy kod pokazuje, jak uzyskać Camera.Parameters obiekt i sprawdź, czy aparat obsługuje autofokus cecha:

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
}

W przypadku większości funkcji aparatu możesz skorzystać z opisanej powyżej metody. Obiekt Camera.Parameters udostępnia metodę getSupported...(), is...Supported() lub getMax...() do określenia, czy (i w jakim stopniu) cecha jest obsługiwane.

Jeśli Twoja aplikacja do prawidłowego działania wymaga pewnych funkcji aparatu, ich wymagane jest dodanie ich do pliku manifestu aplikacji. Gdy zadeklarujesz użycie funkcji aparatu takich jak lampa błyskowa czy autofokus, Google Play ogranicza w aplikacji możliwość jest instalowana na urządzeniach, które nie obsługują tych funkcji. Listę funkcji aparatu, które można zadeklarować w manifeście aplikacji, zobacz plik manifestu Funkcje Plik referencyjny.

Korzystanie z funkcji aparatu

Większość funkcji kamery jest aktywowana i sterowana za pomocą obiektu Camera.Parameters. Uzyskujesz ten obiekt przez pobranie instancji obiekt Camera, wywołując metodę getParameters() i zmieniając zwracany parametr. obiektu, a następnie ponownie umieścić go w obiekcie kamery, jak widać w przykładzie poniżej. kod:

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);

Ta metoda działa w przypadku prawie wszystkich funkcji kamery, a większość parametrów można zmienić w dowolnym momencie czasu po uzyskaniu instancji obiektu Camera. Zmiany w są zwykle widoczne dla użytkownika bezpośrednio na podglądzie w aplikacji. Od strony oprogramowania zmiany parametrów mogą być widoczne dopiero po kilku klatkach, ponieważ aparat przetwarza nowe instrukcje, a następnie wysyła zaktualizowane dane obrazu.

Ważne: niektórych funkcji aparatu nie można zmieniać. W zmiana rozmiaru lub orientacji podglądu aparatu wymaga wcześniejszego wyłączenia wyświetlić podgląd, zmienić jego rozmiar i ponownie uruchomić podgląd. Od Androida 4.0 (interfejs API) Poziom 14) można zmienić orientację podglądu bez jego ponownego uruchamiania.

Wdrożenie innych funkcji aparatu wymaga dodatkowego kodu, takich jak:

  • Pomiar i obszary ostrości
  • Wykrywanie twarzy
  • Film poklatkowy

Poniżej znajdziesz krótki opis implementacji tych funkcji.

Pomiar i obszary ostrości

W niektórych sytuacjach związanych z fotografią automatyczne ustawianie ostrości i pomiar światła mogą nie powodować pożądanym efektom. Począwszy od Androida 4.0 (poziom interfejsu API 14) aplikacja aparatu może udostępniać dodatkowe opcje, które pozwalają aplikacji lub użytkownikom określić obszary na obrazie, które mają być używane ustawień ostrości i poziomu oświetlenia oraz przekazuj te wartości do sprzętu aparatu, aby wykorzystać je obrazów lub filmów.

Obszary do pomiaru i ustawiania ostrości działają bardzo podobnie do innych funkcji aparatu, ponieważ możesz kontrolować je za pomocą metod w obiekcie Camera.Parameters. Następujący kod: pokazuje ustawienie dwóch obszarów pomiaru światła na potrzeby 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);

Obiekt Camera.Area zawiera 2 parametry danych: obiekt Rect do określenia obszaru w polu widzenia kamery oraz wagę. która informuje kamerę, jak ważny jest ten obszar w pomiarze światła. lub obliczeń skupienia.

Pole Rect w obiekcie Camera.Area opisuje prostokątny kształt zmapowany na siatce 2000 x 2000 jednostek. Współrzędne -1000, -1000 oznacza lewy górny róg zdjęcia z aparatu, a współrzędne 1000 i 1000 oznaczają w prawym dolnym rogu zdjęcia z aparatu, tak jak na ilustracji poniżej.

Rysunek 1. Czerwone linie przedstawiają układ współrzędnych służący do określania Camera.Area w podglądzie z aparatu. Niebieskie pole pokazuje lokalizację kształtu obszaru kamery o wartościach Rect 333 333 667 667.

Granice tego układu współrzędnych zawsze odpowiadają zewnętrznej krawędzi obrazu widocznego w podglądu z aparatu i nie zmniejszaj ani nie powiększaj wraz z poziomem powiększenia. Podobnie jest z obracaniem obrazu. zobacz podgląd w usłudze Camera.setDisplayOrientation() nie powoduje zmiany mapowania układu współrzędnych.

Wykrywanie twarzy

W przypadku zdjęć przedstawiających osoby twarze są zwykle najważniejszym elementem. służy do określania ostrości i balansu bieli podczas robienia zdjęcia. Android 4.0 (poziom API 14) udostępnia interfejsy API do rozpoznawania twarzy i obliczania ustawień zdjęcia za pomocą technologii rozpoznawania twarzy.

Uwaga: gdy funkcja wykrywania twarzy jest włączona, setWhiteBalance(String), setFocusAreas(List<Camera.Area>) i setMeteringAreas(List<Camera.Area>) nie ma żadnego efektu.

Aby zacząć korzystać z funkcji wykrywania twarzy w aplikacji aparatu, musisz wykonać kilka ogólnych czynności:

  • Sprawdź, czy urządzenie obsługuje wykrywanie twarzy
  • Utwórz detektor wykrywania twarzy
  • Dodaj detektor wykrywania twarzy do obiektu kamery
  • Uruchamiaj wykrywanie twarzy po wyświetleniu podglądu (i po każdym ponownym uruchomieniu podglądu)

Funkcja wykrywania twarzy nie jest obsługiwana na wszystkich urządzeniach. Możesz sprawdzić, czy ta funkcja obsługiwane przez wywołanie getMaxNumDetectedFaces(). An tego przykładu można sprawdzić w metodzie startFaceDetection() poniżej.

Aby otrzymywać powiadomienia i reagować na wykrycie twarzy, aplikacja aparatu musi być ustawiona detektor zdarzeń związanych z wykrywaniem twarzy. Aby to zrobić, musisz utworzyć klasę detektora, która implementuje interfejs Camera.FaceDetectionListener zgodnie z tabelą przykładowy kod poniżej.

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() );
        }
    }
}

Po utworzeniu tych zajęć możesz je ustawić w Camera – tak jak w przykładowym kodzie poniżej:

Kotlin

camera?.setFaceDetectionListener(MyFaceDetectionListener())

Java

camera.setFaceDetectionListener(new MyFaceDetectionListener());

Aplikacja musi uruchamiać funkcję wykrywania twarzy przy każdym uruchomieniu (lub ponownym uruchomieniu) funkcji podgląd z aparatu. Utwórz metodę uruchamiania wykrywania twarzy, aby móc do niej dzwonić w razie potrzeby, tak jak pokazano na ilustracji w przykładowym kodzie poniżej.

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();
    }
}

Wykrywanie twarzy musisz włączać za każdym razem, gdy uruchomisz (lub ponownie uruchomisz) podgląd aparatu. Jeśli używasz klasy podglądu widocznej w artykule Tworzenie podglądu, dodaj startFaceDetection() do funkcji surfaceCreated() i surfaceChanged() w zajęciach w wersji testowej, jak widać w przykładowym kodzie poniżej.

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());
    }
}

Uwaga: pamiętaj, by wywołać tę metodę po wywołaniu startPreview(). Nie próbuj włączać wykrywania twarzy w metodzie onCreate() podczas głównej aktywności aparatu w aplikacji, ponieważ podgląd nie jest dostępny do tego momentu wykonywania aplikacji.

Film poklatkowy

Funkcja filmów w trybie poklatkowym umożliwia tworzenie klipów wideo łączących zdjęcia wykonane kilka sekund lub minut odstępu. Ta funkcja wykorzystuje MediaRecorder do rejestrowania obrazów przez jakiś czas sekwencja poklatkowa.

Aby nagrywać filmy w trybie poklatkowym za pomocą MediaRecorder, musisz skonfigurować obiektu nagrywarki tak jak przy normalnym filmie, ustaw liczbę przechwyconych klatek na sekundę na przy użyciu jednego z ustawień jakości w trybie poklatkowym, jak widać w poniższym przykładzie kodu.

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

Te ustawienia należy wprowadzić w ramach większej procedury konfiguracji usługi MediaRecorder. Pełny kod konfiguracji znajdziesz w artykule Konfigurowanie funkcji MediaRecorder. Po zakończeniu konfiguracji zaczniesz nagrywać film tak, jakby był to zwykły klip wideo. Więcej informacji na temat konfiguracji Informacje o konfigurowaniu i uruchamianiu usługi MediaRecorder zawiera artykuł Nagrywanie filmów.

Camera2Video, oraz HdrViewfinder W przykładach szczegółowo opisano wykorzystanie interfejsów API opisanych na tej stronie.

Pola dotyczące aparatu, które wymagają uprawnień

Aplikacje na Androidzie 10 (poziom interfejsu API 29) lub nowszym muszą mieć CAMERA, aby: uzyskać dostęp do wartości następujących pól, getCameraCharacteristics() metoda zwraca:

  • LENS_POSE_ROTATION
  • LENS_POSE_TRANSLATION
  • LENS_INTRINSIC_CALIBRATION
  • LENS_RADIAL_DISTORTION
  • LENS_POSE_REFERENCE
  • LENS_DISTORTION
  • LENS_INFO_HYPERFOCAL_DISTANCE
  • LENS_INFO_MINIMUM_FOCUS_DISTANCE
  • SENSOR_REFERENCE_ILLUMINANT1
  • SENSOR_REFERENCE_ILLUMINANT2
  • SENSOR_CALIBRATION_TRANSFORM1
  • SENSOR_CALIBRATION_TRANSFORM2
  • SENSOR_COLOR_TRANSFORM1
  • SENSOR_COLOR_TRANSFORM2
  • SENSOR_FORWARD_MATRIX1
  • SENSOR_FORWARD_MATRIX2

Dodatkowy przykładowy kod

Aby pobrać przykładowe aplikacje, zobacz Przykład z Aparatu2Podstawowy oraz Oficjalna przykładowa aplikacja CameraX.