API กล้องถ่ายรูป

เฟรมเวิร์กของ Android ประกอบด้วยการสนับสนุนสำหรับฟีเจอร์กล้องและกล้องต่างๆ ที่มีให้ใช้งานใน เพื่อถ่ายภาพและวิดีโอในแอปพลิเคชันของคุณได้ เอกสารฉบับนี้กล่าวถึง วิธีการจับภาพและวิดีโอที่เรียบง่ายและรวดเร็ว รวมทั้งแสดงให้เห็นถึงวิธีการขั้นสูงในการสร้าง ประสบการณ์การใช้งานกล้องแบบกำหนดเองสำหรับผู้ใช้

หมายเหตุ หน้านี้จะอธิบายถึง Camera คลาสที่เลิกใช้งานแล้ว เราขอแนะนำให้ใช้ ไลบรารี cameraX Jetpack หรือสำหรับกรณีการใช้งานเฉพาะ camera2, ทั้ง CameraX และ Camera2 สามารถใช้กับ Android 5.0 (API ระดับ 21) และ สูงขึ้น

โปรดดูแหล่งข้อมูลที่เกี่ยวข้องต่อไปนี้

ข้อควรพิจารณา

ก่อนที่จะเปิดให้แอปพลิเคชันของคุณใช้กล้องถ่ายรูปบนอุปกรณ์ Android คุณควรพิจารณา คำถามเกี่ยวกับวิธีที่แอปของคุณตั้งใจจะใช้ฟีเจอร์ของฮาร์ดแวร์นี้

  • ความต้องการของกล้อง - การใช้กล้องมีความสำคัญต่อ ที่คุณไม่ต้องการให้ติดตั้งแอปพลิเคชันของคุณบนอุปกรณ์ที่ไม่มี กล้องถ่ายรูป ถ้าใช่ คุณควรประกาศข้อกำหนดสำหรับกล้องใน ไฟล์ Manifest
  • ภาพด่วนหรือกล้องที่ปรับแต่งเอง - แอปพลิเคชันของคุณจะใช้ กล้องถ่ายรูป คุณแค่สนใจที่จะถ่ายภาพหรือวิดีโอคลิปสั้นๆ หรือว่าแอปพลิเคชันของคุณ มีวิธีการใช้กล้องแบบใหม่ไหม หากต้องการถ่ายรูปหรือถ่ายคลิปอย่างรวดเร็ว ให้พิจารณา ใช้แอปกล้องถ่ายรูปที่มีอยู่ สำหรับการพัฒนาฟีเจอร์กล้องถ่ายรูปแบบกำหนดเอง โปรดดู ในส่วนการสร้างแอปกล้องถ่ายรูป
  • ข้อกําหนดของบริการที่ทำงานอยู่เบื้องหน้า - แอปของคุณจะโต้ตอบกับ กล้องล่ะ ใน 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

การประกาศไฟล์ Manifest

ก่อนที่จะเริ่มการพัฒนาในแอปพลิเคชันด้วย Camera API คุณควรตรวจสอบ ไฟล์ Manifest ของคุณมีประกาศที่เหมาะสมเพื่ออนุญาตให้ใช้ฮาร์ดแวร์กล้องและ ฟีเจอร์ที่เกี่ยวข้อง

  • สิทธิ์เข้าถึงกล้อง - แอปพลิเคชันต้องขอสิทธิ์ในการใช้อุปกรณ์ กล้อง
    <uses-permission android:name="android.permission.CAMERA" />
    

    หมายเหตุ: หากคุณใช้กล้องโดย การเรียกใช้แอปกล้องที่มีอยู่ แอปพลิเคชันของคุณไม่จำเป็นต้องขอสิทธิ์นี้

  • ฟีเจอร์กล้องถ่ายรูป - แอปพลิเคชันต้องประกาศการใช้ฟีเจอร์ของกล้องด้วย เช่น
    <uses-feature android:name="android.hardware.camera" />
    

    สำหรับรายการฟีเจอร์กล้อง โปรดดูไฟล์ Manifest ฟีเจอร์ ข้อมูลอ้างอิง

    การเพิ่มฟีเจอร์กล้องลงในไฟล์ Manifest จะทำให้ Google Play ป้องกันไม่ให้แอปพลิเคชันของคุณ ได้รับการติดตั้งบนอุปกรณ์ที่ไม่มีกล้อง หรือไม่รองรับฟีเจอร์กล้องที่คุณ ระบุ ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้การกรองตามฟีเจอร์กับ Google Play ได้ที่ Google การกรอง Play และฟีเจอร์ตามฟีเจอร์

    หากแอปพลิเคชันของคุณสามารถใช้ฟีเจอร์กล้องหรือกล้องเพื่อการทำงานที่เหมาะสม แต่ ไม่ต้องการ คุณควรระบุข้อมูลนี้ในไฟล์ Manifest โดยใส่แอตทริบิวต์ android:required และตั้งค่าเป็น false:

    <uses-feature android:name="android.hardware.camera" android:required="false" />
    
  • สิทธิ์เข้าถึงพื้นที่เก็บข้อมูล - แอปพลิเคชันของคุณสามารถบันทึกรูปภาพหรือวิดีโอลงใน ที่จัดเก็บข้อมูลภายนอก (การ์ด SD) ของอุปกรณ์ หากกำหนดเป้าหมายเป็น Android 10 (API ระดับ 29) หรือ ต่ำกว่าและระบุข้อมูลต่อไปนี้ในไฟล์ Manifest
    <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 ที่มีอยู่ รายละเอียดอธิบายไว้ในบทเรียนการฝึกอบรม ถ่ายภาพได้ง่ายๆ และ การบันทึกวิดีโอง่ายๆ

การสร้างแอปกล้องถ่ายรูป

นักพัฒนาซอฟต์แวร์บางรายอาจต้องการอินเทอร์เฟซผู้ใช้ของกล้องถ่ายรูปที่ปรับแต่งให้เข้ากับรูปลักษณ์ของ หรือให้คุณลักษณะพิเศษ การเขียนโค้ดสำหรับถ่ายภาพของคุณเอง สามารถให้ประสบการณ์ที่น่าสนใจยิ่งขึ้นสำหรับผู้ใช้

หมายเหตุ: คำแนะนำต่อไปนี้เป็นคำแนะนำสำหรับ Camera รุ่นเก่าที่เลิกใช้งานแล้ว API สำหรับแอปพลิเคชันกล้องใหม่หรือแอปพลิเคชันกล้องขั้นสูง android.hardware.camera2 API เวอร์ชันใหม่กว่าคือ แนะนำ

ขั้นตอนทั่วไปในการสร้างอินเทอร์เฟซกล้องถ่ายรูปที่กำหนดเองสำหรับแอปพลิเคชันมีดังนี้

  • ตรวจหาและเข้าถึงกล้อง - สร้างโค้ดเพื่อตรวจหาการมีอยู่ของ และขอสิทธิ์เข้าถึง
  • สร้างคลาสการแสดงตัวอย่าง - สร้างคลาสการแสดงตัวอย่างจากกล้องที่ขยาย SurfaceView และใช้อินเทอร์เฟซ SurfaceHolder ช่วงเวลานี้ เพื่อดูตัวอย่างภาพสดจากกล้อง
  • สร้างเลย์เอาต์ตัวอย่าง - เมื่อคุณมีคลาสแสดงตัวอย่างจากกล้องแล้ว ให้สร้าง ดูเลย์เอาต์ที่รวมการแสดงตัวอย่างและการควบคุมอินเทอร์เฟซผู้ใช้ที่คุณต้องการ
  • ตั้งค่า Listener สำหรับการบันทึก - เชื่อมต่อ Listener สำหรับอินเทอร์เฟซของคุณ ตัวควบคุมเพื่อเริ่มจับภาพหรือวิดีโอตามการดำเนินการของผู้ใช้ เช่น การกด
  • จับภาพและบันทึกไฟล์ - ตั้งค่าโค้ดสำหรับการจับภาพหรือ วิดีโอและบันทึกเอาต์พุต
  • ปล่อยกล้อง - หลังจากใช้กล้อง แอปพลิเคชันต้อง เผยแพร่อย่างเหมาะสมเพื่อให้แอปพลิเคชันอื่นใช้งาน

ฮาร์ดแวร์กล้องเป็นทรัพยากรที่แชร์ร่วมกัน ซึ่งจะต้องมีการจัดการอย่างระมัดระวังเพื่อให้แอปพลิเคชันของคุณ ไม่ขัดแย้งกับแอปพลิเคชันอื่นๆ ที่อาจต้องการใช้ ส่วนต่อไปนี้จะกล่าวถึง วิธีตรวจหาฮาร์ดแวร์กล้อง วิธีขอสิทธิ์เข้าถึงกล้อง วิธีถ่ายภาพหรือวิดีโอ และวิธีปล่อยกล้องเมื่อแอปพลิเคชันใช้งานเสร็จแล้ว

ข้อควรระวัง: อย่าลืมเผยแพร่ Camera โดยเรียก Camera.release() เมื่อ เสร็จสิ้นการใช้งานด้วยซ้ำ! หากแอปพลิเคชันปล่อยกล้องไม่ถูกต้อง การเข้าถึงกล้องในภายหลัง รวมถึงจำนวนครั้งที่ดำเนินการโดยแอปพลิเคชันของคุณเอง จะล้มเหลวและอาจ ทำให้แอปพลิเคชันของคุณหรือแอปพลิเคชันอื่นๆ ปิดลง

กำลังตรวจหาฮาร์ดแวร์กล้อง

หากแอปพลิเคชันของคุณไม่ได้กำหนดให้ใช้กล้องเป็นการเฉพาะโดยใช้การประกาศไฟล์ Manifest คุณจะต้อง ควรตรวจสอบว่ากล้องพร้อมใช้งานขณะรันไทม์ไหม หากต้องการดำเนินการตรวจสอบนี้ ให้ใช้เมธอด 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) โค้ดตัวอย่างด้านบนจะเข้าถึง เป็นกล้องหลังตัวแรกบนอุปกรณ์ที่มีกล้องมากกว่า 1 ตัว

กำลังตรวจสอบฟีเจอร์ของกล้อง

เมื่อคุณได้สิทธิ์เข้าถึงกล้อง คุณสามารถทราบข้อมูลเพิ่มเติมเกี่ยวกับความสามารถต่างๆ ของกล้องได้โดยใช้ เมธอด Camera.getParameters() และตรวจสอบ แสดงผลออบเจ็กต์ Camera.Parameters สำหรับความสามารถที่รองรับ เมื่อใช้ API ระดับ 9 ขึ้นไป ให้ใช้ Camera.getCameraInfo() เพื่อระบุว่ากล้องอยู่ด้านหน้าหรือไม่ หรือด้านหลังของอุปกรณ์ และการวางแนวของภาพ

กำลังสร้างคลาสตัวอย่าง

เพื่อให้ผู้ใช้ถ่ายภาพหรือวิดีโอได้อย่างมีประสิทธิภาพ ผู้ใช้ต้องเห็นสิ่งที่กล้องของอุปกรณ์ได้ เห็น คลาสแสดงตัวอย่างจากกล้องคือ SurfaceView ที่แสดงรูปภาพสดได้ ข้อมูลที่มาจากกล้องถ่ายรูป เพื่อให้ผู้ใช้สามารถจัดเฟรมและจับภาพหรือวิดีโอได้

โค้ดตัวอย่างต่อไปนี้แสดงวิธีการสร้างคลาสการแสดงตัวอย่างกล้องพื้นฐานที่สามารถ รวมอยู่ในเลย์เอาต์ View คลาสนี้ใช้ SurfaceHolder.Callback เพื่อบันทึกเหตุการณ์ 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() แล้ว คุณอาจต้องปรับให้พอดีกับขนาดหน้าต่างและสัดส่วนภาพ แสดงตัวอย่างจากกล้องเป็นเค้าโครงแนวตั้ง หรือกลับกันโดยใช้ แบบแถบดำด้านบน-ล่างของภาพ

การวางตัวอย่างในเลย์เอาต์

คลาสการแสดงตัวอย่างจากกล้องถ่ายรูป เช่น ตัวอย่างที่แสดงในส่วนก่อนหน้านี้ จะต้องอยู่ใน เลย์เอาต์ของกิจกรรมร่วมกับส่วนควบคุมอินเทอร์เฟซผู้ใช้อื่นๆ สำหรับการถ่ายภาพหรือวิดีโอ ช่วงเวลานี้ แสดงวิธีสร้างเลย์เอาต์และกิจกรรมพื้นฐานสำหรับการแสดงตัวอย่าง

รหัสเลย์เอาต์ต่อไปนี้ให้มุมมองพื้นฐานที่สามารถใช้เพื่อแสดงกล้อง เวอร์ชันตัวอย่าง ในตัวอย่างนี้ องค์ประกอบ 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>

ในอุปกรณ์ส่วนใหญ่ การวางแนวเริ่มต้นของการแสดงตัวอย่างจากกล้องจะเป็นแนวนอน เลย์เอาต์ตัวอย่างนี้ ระบุการจัดวางในแนวนอน (แนวนอน) และโค้ดด้านล่างจะช่วยแก้ไขการวางแนวของ กับแนวนอน เพื่อให้แสดงภาพตัวอย่างจากกล้องได้ง่าย คุณควรเปลี่ยน วางแนวกิจกรรมหน้าตัวอย่างของแอปพลิเคชันให้อยู่ในแนวนอนโดยเพิ่มรายละเอียดต่อไปนี้ลงใน ไฟล์ Manifest

<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() ในตัวอย่างด้านบน อ้างถึงวิธีการตัวอย่างที่แสดงในการเข้าถึงกล้อง

กำลังจับภาพ

เมื่อคุณสร้างคลาสตัวอย่างและเลย์เอาต์มุมมองที่จะแสดงแล้ว คุณก็พร้อมที่จะ เริ่มจับภาพด้วยแอปพลิเคชันของคุณ ในโค้ดของแอปพลิเคชัน คุณต้องตั้งค่า Listener เพื่อตอบสนองต่อการดำเนินการของผู้ใช้ด้วยการถ่ายภาพ

หากต้องการดึงภาพ ให้ใช้เมธอด Camera.takePicture() วิธีนี้ใช้พารามิเตอร์ 3 รายการซึ่งรับข้อมูลจากกล้อง เพื่อรับข้อมูลในรูปแบบ 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() ให้คุณโดยอัตโนมัติ

การถ่ายวิดีโอต้องใช้การโทรที่พิเศษมากๆ ต่างจากการถ่ายภาพด้วยกล้องของอุปกรณ์ คำสั่งซื้อ คุณต้องทำตามลำดับการดำเนินการที่เฉพาะเจาะจงเพื่อเตรียมพร้อมและบันทึกวิดีโอ กับใบสมัครของคุณ ตามรายละเอียดด้านล่าง

  1. เปิดกล้อง - ใช้Camera.open() เพื่อรับอินสแตนซ์ของออบเจ็กต์กล้อง
  2. ตัวอย่างการเชื่อมต่อ - เตรียมตัวอย่างรูปภาพแบบสดจากกล้องโดยเชื่อมต่อ SurfaceView กับกล้องโดยใช้ Camera.setPreviewDisplay()
  3. เริ่มการแสดงตัวอย่าง - โทรหา Camera.startPreview() เพื่อเริ่มแสดงภาพสดจากกล้อง
  4. เริ่มบันทึกวิดีโอ - โปรดทำตามขั้นตอนต่อไปนี้ใน order เพื่อให้บันทึกวิดีโอได้สำเร็จ:
    1. ปลดล็อกกล้อง - ปลดล็อกกล้องเพื่อใช้กับ MediaRecorder โดยโทรไปที่ Camera.unlock()
    2. กำหนดค่า MediaRecorder - เรียกใช้เมธอด MediaRecorder ต่อไปนี้ในลำดับนี้ สำหรับข้อมูลเพิ่มเติม โปรดดูเอกสารอ้างอิง MediaRecorder
      1. setCamera() - ตั้งค่ากล้องที่จะใช้ในการบันทึกวิดีโอ ใช้อินสแตนซ์ปัจจุบันของแอปพลิเคชัน ของ Camera
      2. setAudioSource() - ตั้งค่า แหล่งที่มาของเสียง ให้ใช้ MediaRecorder.AudioSource.CAMCORDER
      3. setVideoSource() - ตั้งค่าแล้ว แหล่งที่มาของวิดีโอ ให้ใช้ MediaRecorder.VideoSource.CAMERA
      4. ตั้งค่ารูปแบบและการเข้ารหัสเอาต์พุตวิดีโอ สำหรับ Android 2.2 (API ระดับ 8) และ ให้สูงกว่า วิธี MediaRecorder.setProfile และรับอินสแตนซ์โปรไฟล์โดยใช้ CamcorderProfile.get() สำหรับ Android เวอร์ชันก่อน 2.2 คุณต้องตั้งค่ารูปแบบเอาต์พุตวิดีโอและพารามิเตอร์การเข้ารหัส ดังนี้
        1. setOutputFormat() - ตั้งค่าแล้ว รูปแบบเอาต์พุต ให้ระบุการตั้งค่าเริ่มต้นหรือ MediaRecorder.OutputFormat.MPEG_4
        2. setAudioEncoder() - ตั้งค่าแล้ว ประเภทการเข้ารหัสเสียง ให้ระบุการตั้งค่าเริ่มต้นหรือ MediaRecorder.AudioEncoder.AMR_NB
        3. setVideoEncoder() - ตั้งค่าแล้ว ประเภทการเข้ารหัสวิดีโอ ให้กำหนดการตั้งค่าเริ่มต้นหรือMediaRecorder.VideoEncoder.MPEG_4_SP
      5. setOutputFile() - ตั้งค่าไฟล์เอาต์พุต ใช้ getOutputMediaFile(MEDIA_TYPE_VIDEO).toString() จากตัวอย่าง ในส่วนการบันทึกไฟล์สื่อ
      6. setPreviewDisplay() - ระบุองค์ประกอบเค้าโครงตัวอย่าง SurfaceView สำหรับ แอปพลิเคชันของคุณ ใช้ออบเจ็กต์เดียวกันกับที่คุณระบุสำหรับ Connect Preview

      ข้อควรระวัง: คุณต้องเรียกใช้วิธีการกำหนดค่า MediaRecorder เหล่านี้ตามลำดับนี้ มิฉะนั้น แอปพลิเคชันจะเกิดข้อผิดพลาดและการบันทึกจะล้มเหลว

    3. เตรียม MediaRecorder - เตรียม MediaRecorder พร้อมการตั้งค่าที่กำหนดไว้โดยโทรหา MediaRecorder.prepare()
    4. เริ่ม MediaRecorder - เริ่มบันทึกวิดีโอโดยโทรหา MediaRecorder.start()
  5. หยุดบันทึกวิดีโอ - เรียกเมธอดต่อไปนี้ตามลำดับ เพื่อ บันทึกวิดีโอเสร็จสมบูรณ์:
    1. หยุด MediaRecorder - หยุดบันทึกวิดีโอโดยโทรหา MediaRecorder.stop()
    2. รีเซ็ต MediaRecorder - (ไม่บังคับ) นำการตั้งค่าการกำหนดค่าออกจาก โดยโทรหา MediaRecorder.reset()
    3. Release MediaRecorder - เผยแพร่ MediaRecorder โดยโทรไปที่ MediaRecorder.release()
    4. ล็อกกล้อง - ล็อกกล้องเพื่อให้เซสชันของ MediaRecorder ในอนาคตใช้งานได้โดยโทรหา Camera.lock() สำหรับ Android 4.0 (API ระดับ 14) เป็นต้นไป ไม่จำเป็นต้องใช้การเรียกนี้เว้นแต่ โทร MediaRecorder.prepare() ไม่สำเร็จ
  6. หยุดการแสดงตัวอย่าง - เมื่อใช้กล้องเสร็จแล้ว ให้หยุด ดูตัวอย่างโดยใช้ Camera.stopPreview()
  7. ปล่อยกล้อง - ปล่อยกล้องเพื่อให้แอปพลิเคชันอื่นใช้งานได้ โดยโทรไปที่ 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 การตั้งค่าเริ่มต้น อย่างไรก็ตาม คุณอาจต้องการปรับการตั้งค่าเหล่านี้สำหรับแอปพลิเคชันของคุณ ดังนี้:

การเริ่มและการหยุด MediaRecorder

เมื่อเริ่มและหยุดการบันทึกวิดีโอโดยใช้ชั้นเรียน MediaRecorder คุณต้องทำตามคำสั่งซื้อที่เฉพาะเจาะจง ตามที่ระบุไว้ด้านล่าง

  1. ปลดล็อกกล้องด้วย Camera.unlock()
  2. กำหนดค่า MediaRecorder ดังที่แสดงในตัวอย่างโค้ดด้านบน
  3. เริ่มบันทึกโดยใช้ MediaRecorder.start()
  4. บันทึกวิดีโอ
  5. หยุดบันทึกโดยใช้ MediaRecorder.stop()
  6. เปิดตัวเครื่องบันทึกสื่อด้วย MediaRecorder.release()
  7. ล็อกกล้องโดยใช้ 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 Card) เพื่อประหยัดพื้นที่ของระบบและเพื่อให้ผู้ใช้เข้าถึงไฟล์เหล่านี้ได้ โดยไม่มีอุปกรณ์ การบันทึกไฟล์สื่อในอุปกรณ์สามารถทำได้หลายวิธี อย่างไรก็ตาม มีเพียง 2 ตำแหน่งมาตรฐานที่คุณควรถือว่าเป็นนักพัฒนาซอฟต์แวร์ ได้แก่

  • 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 ฟีเจอร์ทั่วไปของกล้องที่จัดเรียงตามระดับ API ของ Android ที่ ได้แนะนำ

ฟีเจอร์ ระดับ API คำอธิบาย
การตรวจจับใบหน้า 14 ระบุใบหน้าของมนุษย์ในภาพแล้วใช้ประกอบเพื่อโฟกัส วัดแสง และสีขาว ยอดคงเหลือ
พื้นที่การวัด 14 ระบุพื้นที่อย่างน้อย 1 พื้นที่ภายในรูปภาพเพื่อคำนวณไวท์บาลานซ์
ด้านที่มุ่งเน้น 14 ตั้งค่าพื้นที่อย่างน้อย 1 ส่วนภายในรูปภาพเพื่อใช้สำหรับโฟกัส
White Balance Lock 14 หยุดหรือเริ่มการปรับไวท์บาลานซ์อัตโนมัติ
Exposure Lock 14 หยุดหรือเริ่มการปรับการรับแสงอัตโนมัติ
Video Snapshot 14 ถ่ายรูปขณะถ่ายวิดีโอ (จับเฟรม)
วิดีโอไทม์แลปส์ 11 บันทึกเฟรมที่มีการหน่วงเวลาที่ตั้งไว้เพื่อบันทึกวิดีโอไทม์แลปส์
Multiple Cameras 9 รองรับกล้องมากกว่า 1 ตัวในอุปกรณ์ 1 ตัว ซึ่งรวมถึงกล้องหน้าและกล้องหลัง กล้อง
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...() เพื่อระบุว่าฟีเจอร์นั้น (และขอบเขต) หรือไม่ ที่รองรับ

หากแอปพลิเคชันของคุณต้องใช้คุณลักษณะบางอย่างของกล้องถ่ายรูปเพื่อให้ทำงานได้อย่างถูกต้อง คุณสามารถ ต้องการรายการเหล่านี้ผ่านการเพิ่มไฟล์ Manifest ของแอปพลิเคชัน เมื่อคุณประกาศการใช้ คุณลักษณะของกล้องถ่ายรูป เช่น แฟลชและโฟกัสอัตโนมัติ Google Play จะจำกัดไม่ให้แอปพลิเคชันของคุณทำงาน กำลังติดตั้งบนอุปกรณ์ที่ไม่รองรับฟีเจอร์เหล่านี้ สำหรับรายการฟีเจอร์กล้องที่ สามารถประกาศในไฟล์ Manifest ของแอปได้ โปรดดูไฟล์ Manifest ฟีเจอร์ ข้อมูลอ้างอิง

การใช้ฟีเจอร์ของกล้อง

ฟีเจอร์กล้องส่วนใหญ่จะเปิดใช้งานและควบคุมโดยใช้ออบเจ็กต์ 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 รหัสต่อไปนี้ จะแสดงการตั้งค่าพื้นที่การวัดแสง 2 จุดในกรณี 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 มีพารามิเตอร์ข้อมูล 2 รายการ ได้แก่ ออบเจ็กต์ 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>) จะไม่มีผล

การใช้ฟีเจอร์การตรวจจับใบหน้าในแอปพลิเคชันกล้องมีขั้นตอนทั่วไป 2-3 ขั้นตอนต่อไปนี้

  • ตรวจสอบว่าอุปกรณ์รองรับการตรวจจับใบหน้า
  • สร้าง Listener การตรวจจับใบหน้า
  • เพิ่ม Listener การตรวจจับใบหน้าลงในวัตถุของกล้อง
  • เริ่มการตรวจจับใบหน้าหลังจากการแสดงตัวอย่าง (และหลังจากการรีสตาร์ทการแสดงตัวอย่างทุกครั้ง)

อุปกรณ์บางรุ่นไม่รองรับฟีเจอร์การตรวจจับใบหน้า คุณสามารถตรวจสอบว่าฟีเจอร์นี้ รองรับโดยการโทรหา getMaxNumDetectedFaces() CANNOT TRANSLATE ตัวอย่างของการตรวจสอบนี้จะแสดงในวิธีการตัวอย่างด้านล่าง startFaceDetection()

ในการแจ้งเตือนและตอบสนองต่อการตรวจจับใบหน้า แอปพลิเคชันกล้องของคุณต้องตั้งค่า Listener เหตุการณ์การตรวจจับใบหน้า ในการดำเนินการนี้ คุณต้องสร้างคลาส Listener ที่ ใช้อินเทอร์เฟซ 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() ของกิจกรรมหลักของแอปกล้อง เนื่องจากการแสดงตัวอย่างยังไม่พร้อมใช้งาน ณ จุดนี้ในการดำเนินการของแอปพลิเคชันของคุณ

วิดีโอไทม์แลปส์

วิดีโอไทม์แลปส์ช่วยให้ผู้ใช้สร้างวิดีโอคลิปซึ่งรวมภาพที่ถ่ายในเวลา 2-3 วินาที หรือ ห่างกัน 1 นาที ฟีเจอร์นี้ใช้ 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 โปรดดูการจับภาพวิดีโอ

กล้องถ่ายรูป2วิดีโอ และ HdrViewfinder ตัวอย่างเพิ่มเติมสาธิตการใช้ API ที่กล่าวถึงในหน้านี้

ช่องกล้องที่ต้องใช้สิทธิ์

แอปที่ใช้ Android 10 (API ระดับ 29) ขึ้นไปต้องมี CAMERA เพื่อ เข้าถึงค่าของช่องต่อไปนี้ที่พร็อพเพอร์ตี้ getCameraCharacteristics() ผลลัพธ์:

  • 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

โค้ดตัวอย่างเพิ่มเติม

หากต้องการดาวน์โหลดแอปตัวอย่าง โปรดดูที่ ตัวอย่าง Camera2Basic และ ตัวอย่างแอป CameraX อย่างเป็นทางการ