เฟรมเวิร์กของ Android ประกอบด้วยการสนับสนุนสำหรับฟีเจอร์กล้องและกล้องต่างๆ ที่มีให้ใช้งานใน เพื่อถ่ายภาพและวิดีโอในแอปพลิเคชันของคุณได้ เอกสารฉบับนี้กล่าวถึง วิธีการจับภาพและวิดีโอที่เรียบง่ายและรวดเร็ว รวมทั้งแสดงให้เห็นถึงวิธีการขั้นสูงในการสร้าง ประสบการณ์การใช้งานกล้องแบบกำหนดเองสำหรับผู้ใช้
หมายเหตุ:
หน้านี้อธิบายคลาส Camera
ซึ่งเลิกใช้งานแล้ว เราขอแนะนำให้ใช้
ไลบรารี cameraX Jetpack หรือสำหรับกรณีการใช้งานเฉพาะ
camera2
ทั้ง CameraX และ Camera2 ใช้งานได้ใน Android 5.0 (API ระดับ 21) ขึ้นไป
โปรดดูแหล่งข้อมูลที่เกี่ยวข้องต่อไปนี้
ข้อควรพิจารณา
ก่อนเปิดใช้แอปพลิเคชันเพื่อใช้กล้องในอุปกรณ์ Android คุณควรพิจารณาคำถาม 2-3 ข้อเกี่ยวกับวิธีที่แอปของคุณตั้งใจจะใช้ฟีเจอร์ฮาร์ดแวร์นี้
- ข้อกำหนดเกี่ยวกับกล้อง - การใช้กล้องสำคัญกับแอปพลิเคชันของคุณมากจนคุณไม่ต้องการให้ติดตั้งแอปพลิเคชันบนอุปกรณ์ที่ไม่มีกล้องใช่ไหม ถ้าใช่ คุณควรประกาศข้อกำหนดเกี่ยวกับกล้องใน ไฟล์ 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
คลาสนี้จะแสดงตัวอย่างภาพสดจากกล้อง - สร้างเลย์เอาต์ตัวอย่าง - เมื่อคุณมีคลาสตัวอย่างจากกล้องแล้ว ให้สร้างเลย์เอาต์มุมมองที่รวมตัวอย่างและการควบคุมอินเทอร์เฟซผู้ใช้ที่ต้องการ
- ตั้งค่า Listeners สําหรับการจับภาพ - เชื่อมต่อ Listeners สําหรับตัวควบคุมอินเทอร์เฟซเพื่อเริ่มจับภาพรูปภาพหรือวิดีโอเมื่อผู้ใช้ดำเนินการต่างๆ เช่น การกดปุ่ม
- จับภาพและบันทึกไฟล์ - ตั้งค่าโค้ดสําหรับจับภาพหรือวิดีโอและบันทึกเอาต์พุต
- ปล่อยกล้อง - หลังจากใช้กล้อง แอปพลิเคชันต้อง เผยแพร่อย่างเหมาะสมเพื่อให้แอปพลิเคชันอื่นใช้งาน
ฮาร์ดแวร์กล้องเป็นทรัพยากรที่แชร์ร่วมกัน ซึ่งจะต้องมีการจัดการอย่างระมัดระวังเพื่อให้แอปพลิเคชันของคุณ ไม่ขัดแย้งกับแอปพลิเคชันอื่นๆ ที่อาจต้องการใช้ ส่วนต่อไปนี้จะอธิบายวิธีตรวจหาฮาร์ดแวร์ของกล้อง วิธีขอสิทธิ์เข้าถึงกล้อง วิธีจับภาพหรือวิดีโอ และวิธีปล่อยกล้องเมื่อแอปพลิเคชันของคุณใช้งานเสร็จแล้ว
ข้อควรระวัง: อย่าลืมปล่อย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()
ให้คุณโดยอัตโนมัติ
การจับภาพวิดีโอต้องใช้คําสั่งเรียกที่เฉพาะเจาะจงมาก ซึ่งแตกต่างจากการถ่ายภาพด้วยกล้องของอุปกรณ์ คุณต้องทําตามลําดับการดําเนินการอย่างเจาะจงเพื่อเตรียมพร้อมและบันทึกวิดีโอด้วยแอปพลิเคชันของคุณให้สําเร็จ ตามที่ระบุไว้ด้านล่าง
- เปิดกล้อง - ใช้
Camera.open()
เพื่อรับอินสแตนซ์ของออบเจ็กต์กล้อง - ตัวอย่างการเชื่อมต่อ - เตรียมตัวอย่างรูปภาพแบบสดจากกล้องโดยเชื่อมต่อ
SurfaceView
กับกล้องโดยใช้Camera.setPreviewDisplay()
- เริ่มการแสดงตัวอย่าง - โทรหา
Camera.startPreview()
เพื่อเริ่มแสดงภาพสดจากกล้อง - เริ่มบันทึกวิดีโอ - โปรดทำตามขั้นตอนต่อไปนี้ใน
order เพื่อให้บันทึกวิดีโอได้สำเร็จ:
- ปลดล็อกกล้อง - ปลดล็อกกล้องเพื่อให้
MediaRecorder
ใช้ได้โดยโทรหาCamera.unlock()
- กำหนดค่า MediaRecorder - เรียกใช้เมธอด
MediaRecorder
ต่อไปนี้ตามลำดับนี้ ดูข้อมูลเพิ่มเติมได้ที่MediaRecorder
เอกสารอ้างอิงsetCamera()
- ตั้งค่ากล้องที่จะใช้ในการบันทึกวิดีโอ ใช้อินสแตนซ์ปัจจุบันของแอปพลิเคชัน ของCamera
setAudioSource()
- ตั้งค่า แหล่งที่มาของเสียง ให้ใช้MediaRecorder.AudioSource.CAMCORDER
setVideoSource()
- ตั้งค่าแหล่งที่มาของวิดีโอ ใช้MediaRecorder.VideoSource.CAMERA
- ตั้งค่ารูปแบบและการเข้ารหัสเอาต์พุตวิดีโอ สำหรับ Android 2.2 (API ระดับ 8) และ
ให้สูงกว่า วิธี
MediaRecorder.setProfile
และรับอินสแตนซ์โปรไฟล์โดยใช้CamcorderProfile.get()
สำหรับ Android เวอร์ชันก่อน 2.2 คุณต้องตั้งค่ารูปแบบเอาต์พุตวิดีโอและพารามิเตอร์การเข้ารหัส ดังนี้setOutputFormat()
- ตั้งค่าแล้ว รูปแบบเอาต์พุต ให้ระบุการตั้งค่าเริ่มต้นหรือMediaRecorder.OutputFormat.MPEG_4
setAudioEncoder()
- ตั้งค่าแล้ว ประเภทการเข้ารหัสเสียง ให้ระบุการตั้งค่าเริ่มต้นหรือMediaRecorder.AudioEncoder.AMR_NB
setVideoEncoder()
- ตั้งค่าแล้ว ประเภทการเข้ารหัสวิดีโอ ให้กำหนดการตั้งค่าเริ่มต้นหรือMediaRecorder.VideoEncoder.MPEG_4_SP
setOutputFile()
- ใช้getOutputMediaFile(MEDIA_TYPE_VIDEO).toString()
จากตัวอย่างวิธีการในส่วนการบันทึกไฟล์สื่อเพื่อตั้งค่าไฟล์เอาต์พุตsetPreviewDisplay()
- ระบุองค์ประกอบเลย์เอาต์ตัวอย่างSurfaceView
สำหรับแอปพลิเคชัน ใช้ออบเจ็กต์เดียวกันกับที่คุณระบุสำหรับ Connect Preview
ข้อควรระวัง: คุณต้องเรียกใช้วิธีการกําหนดค่า
MediaRecorder
เหล่านี้ตามลําดับนี้ มิฉะนั้นแอปพลิเคชันจะพบข้อผิดพลาดและการบันทึกจะไม่สําเร็จ - เตรียม MediaRecorder - เตรียม
MediaRecorder
พร้อมการตั้งค่าที่กำหนดไว้โดยโทรหาMediaRecorder.prepare()
- เริ่ม MediaRecorder - เริ่มบันทึกวิดีโอโดยโทรหา
MediaRecorder.start()
- ปลดล็อกกล้อง - ปลดล็อกกล้องเพื่อให้
- หยุดบันทึกวิดีโอ - เรียกใช้วิธีการต่อไปนี้ตามลำดับเพื่อบันทึกวิดีโอให้เสร็จสมบูรณ์
- หยุด MediaRecorder - หยุดบันทึกวิดีโอโดยเรียกใช้
MediaRecorder.stop()
- รีเซ็ต MediaRecorder - นำการตั้งค่าการกําหนดค่าออกจากเครื่องบันทึกโดยเรียกใช้
MediaRecorder.reset()
(ไม่บังคับ) - ปล่อย MediaRecorder - ปล่อย
MediaRecorder
โดยเรียกใช้MediaRecorder.release()
- ล็อกกล้อง - ล็อกกล้องเพื่อให้เซสชัน
MediaRecorder
ในอนาคตใช้กล้องได้โดยเรียกใช้Camera.lock()
ตั้งแต่ Android 4.0 (API ระดับ 14) เป็นต้นไป คุณไม่จำเป็นต้องเรียกใช้ API นี้ เว้นแต่การเรียกใช้MediaRecorder.prepare()
จะล้มเหลว
- หยุด MediaRecorder - หยุดบันทึกวิดีโอโดยเรียกใช้
- หยุดการแสดงตัวอย่าง - เมื่อใช้กล้องเสร็จแล้ว ให้หยุด
ดูตัวอย่างโดยใช้
Camera.stopPreview()
- ปล่อยกล้อง - ปล่อยกล้องเพื่อให้แอปพลิเคชันอื่นใช้งานได้
โดยโทรไปที่
Camera.release()
หมายเหตุ: คุณสามารถใช้ MediaRecorder
โดยไม่ต้องสร้างตัวอย่างจากกล้องก่อนและข้ามขั้นตอนแรกๆ ของกระบวนการนี้ อย่างไรก็ตาม เนื่องจากผู้ใช้มักต้องการดูตัวอย่างก่อนเริ่มบันทึก เราจึงไม่ได้กล่าวถึงกระบวนการดังกล่าวในบทความนี้
เคล็ดลับ: หากแอปพลิเคชันของคุณมักใช้สำหรับการบันทึกวิดีโอ ให้ตั้งค่า setRecordingHint(boolean)
เป็น true
ก่อนเริ่มแสดงตัวอย่าง การตั้งค่าดังกล่าวจะช่วยลดเวลาที่ใช้ในการเริ่มบันทึกได้
การกำหนดค่า MediaRecorder
เมื่อใช้คลาส MediaRecorder
เพื่อบันทึกวิดีโอ คุณต้องทําตามขั้นตอนการกําหนดค่าในลําดับที่เฉพาะเจาะจง จากนั้นเรียกใช้เมธอด MediaRecorder.prepare()
เพื่อตรวจสอบและใช้งานการกําหนดค่า โค้ดตัวอย่างต่อไปนี้แสดงวิธีกําหนดค่าและเตรียมคลาส MediaRecorder
อย่างถูกต้องสําหรับการบันทึกวิดีโอ
Kotlin
private fun prepareVideoRecorder(): Boolean { mediaRecorder = MediaRecorder() mCamera?.let { camera -> // Step 1: Unlock and set camera to MediaRecorder camera?.unlock() mediaRecorder?.run { setCamera(camera) // Step 2: Set sources setAudioSource(MediaRecorder.AudioSource.CAMCORDER) setVideoSource(MediaRecorder.VideoSource.CAMERA) // Step 3: Set a CamcorderProfile (requires API Level 8 or higher) setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)) // Step 4: Set output file setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString()) // Step 5: Set the preview output setPreviewDisplay(mPreview?.holder?.surface) setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT) setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT) // Step 6: Prepare configured MediaRecorder return try { prepare() true } catch (e: IllegalStateException) { Log.d(TAG, "IllegalStateException preparing MediaRecorder: ${e.message}") releaseMediaRecorder() false } catch (e: IOException) { Log.d(TAG, "IOException preparing MediaRecorder: ${e.message}") releaseMediaRecorder() false } } } return false }
Java
private boolean prepareVideoRecorder(){ mCamera = getCameraInstance(); mediaRecorder = new MediaRecorder(); // Step 1: Unlock and set camera to MediaRecorder mCamera.unlock(); mediaRecorder.setCamera(mCamera); // Step 2: Set sources mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // Step 3: Set a CamcorderProfile (requires API Level 8 or higher) mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)); // Step 4: Set output file mediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString()); // Step 5: Set the preview output mediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface()); // Step 6: Prepare configured MediaRecorder try { mediaRecorder.prepare(); } catch (IllegalStateException e) { Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage()); releaseMediaRecorder(); return false; } catch (IOException e) { Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage()); releaseMediaRecorder(); return false; } return true; }
ก่อนที่จะมี Android 2.2 (API ระดับ 8) คุณต้องตั้งค่ารูปแบบเอาต์พุตและรูปแบบการเข้ารหัส
พารามิเตอร์ได้โดยตรง แทนที่จะใช้ CamcorderProfile
วิธีการนี้แสดงอยู่ในโค้ดต่อไปนี้
Kotlin
// Step 3: Set output format and encoding (for versions prior to API Level 8) mediaRecorder?.apply { setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT) setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT) }
Java
// Step 3: Set output format and encoding (for versions prior to API Level 8) mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
ระบุพารามิเตอร์การบันทึกวิดีโอต่อไปนี้สำหรับ MediaRecorder
การตั้งค่าเริ่มต้น อย่างไรก็ตาม คุณอาจต้องการปรับการตั้งค่าเหล่านี้สำหรับแอปพลิเคชันของคุณ ดังนี้:
setVideoEncodingBitRate()
setVideoSize()
setVideoFrameRate()
setAudioEncodingBitRate()
setAudioChannels()
setAudioSamplingRate()
การเริ่มและหยุด MediaRecorder
เมื่อเริ่มและหยุดการบันทึกวิดีโอโดยใช้ชั้นเรียน MediaRecorder
คุณต้องทำตามคำสั่งซื้อที่เฉพาะเจาะจง ตามที่ระบุไว้ด้านล่าง
- ปลดล็อกกล้องด้วย
Camera.unlock()
- กำหนดค่า
MediaRecorder
ดังที่แสดงในตัวอย่างโค้ดด้านบน - เริ่มบันทึกโดยใช้
MediaRecorder.start()
- บันทึกวิดีโอ
- หยุดบันทึกโดยใช้
MediaRecorder.stop()
- ปล่อยโปรแกรมอัดสื่อด้วย
MediaRecorder.release()
- ล็อกกล้องโดยใช้
Camera.lock()
ตัวอย่างโค้ดต่อไปนี้แสดงวิธีต่อสายปุ่มเพื่อเริ่มและหยุดการบันทึกวิดีโออย่างถูกต้องโดยใช้กล้องและคลาส MediaRecorder
หมายเหตุ: เมื่อบันทึกวิดีโอเสร็จแล้ว อย่าปล่อยกล้อง ไม่เช่นนั้นระบบจะหยุดแสดงตัวอย่าง
Kotlin
var isRecording = false val captureButton: Button = findViewById(R.id.button_capture) captureButton.setOnClickListener { if (isRecording) { // stop recording and release camera mediaRecorder?.stop() // stop the recording releaseMediaRecorder() // release the MediaRecorder object mCamera?.lock() // take camera access back from MediaRecorder // inform the user that recording has stopped setCaptureButtonText("Capture") isRecording = false } else { // initialize video camera if (prepareVideoRecorder()) { // Camera is available and unlocked, MediaRecorder is prepared, // now you can start recording mediaRecorder?.start() // inform the user that recording has started setCaptureButtonText("Stop") isRecording = true } else { // prepare didn't work, release the camera releaseMediaRecorder() // inform user } } }
Java
private boolean isRecording = false; // Add a listener to the Capture button Button captureButton = (Button) findViewById(id.button_capture); captureButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { if (isRecording) { // stop recording and release camera mediaRecorder.stop(); // stop the recording releaseMediaRecorder(); // release the MediaRecorder object mCamera.lock(); // take camera access back from MediaRecorder // inform the user that recording has stopped setCaptureButtonText("Capture"); isRecording = false; } else { // initialize video camera if (prepareVideoRecorder()) { // Camera is available and unlocked, MediaRecorder is prepared, // now you can start recording mediaRecorder.start(); // inform the user that recording has started setCaptureButtonText("Stop"); isRecording = true; } else { // prepare didn't work, release the camera releaseMediaRecorder(); // inform user } } } } );
หมายเหตุ: ในตัวอย่างด้านบน prepareVideoRecorder()
เมธอดจะอ้างอิงโค้ดตัวอย่างที่แสดงในการกำหนดค่า MediaRecorder วิธีนี้จะจัดการการล็อกกล้อง การกำหนดค่า และการเตรียมอินสแตนซ์ MediaRecorder
ปล่อยกล้อง
กล้องเป็นทรัพยากรที่แอปพลิเคชันต่างๆ ในอุปกรณ์ใช้ร่วมกัน แอปพลิเคชันของคุณสามารถ
ที่ใช้กล้องหลังจากได้รับอินสแตนซ์ Camera
และคุณต้อง
ระมัดระวังเป็นพิเศษในการปล่อยวัตถุกล้องถ่ายรูปเมื่อแอปพลิเคชันของคุณหยุดใช้งาน และ
ทันทีที่แอปพลิเคชันหยุดชั่วคราว (Activity.onPause()
) ถ้า
แอปพลิเคชันของคุณปล่อยกล้องไม่ถูกต้อง ความพยายามเข้าถึงกล้องในครั้งต่อๆ ไปทั้งหมด
ซึ่งรวมถึงซอฟต์แวร์จากแอปพลิเคชันของคุณเอง จะล้มเหลวและอาจทำให้แอปพลิเคชันของคุณหรือแอปพลิเคชันอื่น
ปิด
หากต้องการปล่อยอินสแตนซ์ของออบเจ็กต์ Camera
ให้ใช้เมธอด Camera.release()
ดังที่แสดงในโค้ดตัวอย่างด้านล่าง
Kotlin
class CameraActivity : Activity() { private var mCamera: Camera? private var preview: SurfaceView? private var mediaRecorder: MediaRecorder? override fun onPause() { super.onPause() releaseMediaRecorder() // if you are using MediaRecorder, release it first releaseCamera() // release the camera immediately on pause event } private fun releaseMediaRecorder() { mediaRecorder?.reset() // clear recorder configuration mediaRecorder?.release() // release the recorder object mediaRecorder = null mCamera?.lock() // lock camera for later use } private fun releaseCamera() { mCamera?.release() // release the camera for other applications mCamera = null } }
Java
public class CameraActivity extends Activity { private Camera mCamera; private SurfaceView preview; private MediaRecorder mediaRecorder; ... @Override protected void onPause() { super.onPause(); releaseMediaRecorder(); // if you are using MediaRecorder, release it first releaseCamera(); // release the camera immediately on pause event } private void releaseMediaRecorder(){ if (mediaRecorder != null) { mediaRecorder.reset(); // clear recorder configuration mediaRecorder.release(); // release the recorder object mediaRecorder = null; mCamera.lock(); // lock camera for later use } } private void releaseCamera(){ if (mCamera != null){ mCamera.release(); // release the camera for other applications mCamera = null; } } }
ข้อควรระวัง: หากแอปพลิเคชันไม่ได้เผยแพร่ การเข้าถึงกล้องในภายหลังทั้งหมด รวมถึงการพยายามเข้าถึงกล้องด้วยแอปพลิเคชันของคุณเองจะ ล้มเหลวและอาจทำให้แอปพลิเคชันของคุณหรือแอปพลิเคชันอื่นๆ ปิดลง
การบันทึกไฟล์สื่อ
ไฟล์สื่อที่ผู้ใช้สร้าง เช่น รูปภาพและวิดีโอ ควรบันทึกไปยังโค้ดภายนอกของอุปกรณ์ ไดเรกทอรีพื้นที่เก็บข้อมูล (SD 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 ตัวในอุปกรณ์ ซึ่งรวมถึงกล้องหน้าและกล้องหลัง |
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
อธิบายรูปสี่เหลี่ยมผืนผ้าที่แมปบนตารางกริด 2,000 x 2,000 หน่วย พิกัด -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 ขั้นตอนดังนี้
- ตรวจสอบว่าอุปกรณ์รองรับการตรวจจับใบหน้า
- สร้างโปรแกรมรับฟังการตรวจจับใบหน้า
- เพิ่มโปรแกรมรับฟังการตรวจจับใบหน้าลงในออบเจ็กต์กล้อง
- เริ่มตรวจจับใบหน้าหลังจากแสดงตัวอย่าง (และหลังจากรีสตาร์ทการแสดงตัวอย่างทุกครั้ง)
อุปกรณ์บางรุ่นไม่รองรับฟีเจอร์การตรวจจับใบหน้า คุณสามารถตรวจสอบว่าฟีเจอร์นี้รองรับหรือไม่โดยโทรไปที่ getMaxNumDetectedFaces()
ตัวอย่างการตรวจสอบนี้จะแสดงอยู่ในstartFaceDetection()
เมธอดตัวอย่างด้านล่าง
แอปพลิเคชันกล้องต้องตั้งค่าตัวรับฟังเหตุการณ์การตรวจจับใบหน้าเพื่อรับการแจ้งเตือนและตอบสนองต่อการตรวจจับใบหน้า ในการทำเช่นนั้น คุณต้องสร้างคลาส 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 วินาทีหรือ 2-3 นาที ฟีเจอร์นี้ใช้ 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 อย่างเป็นทางการ