หน้านี้อ้างอิงถึงคลาส Camera ซึ่งเลิกใช้งานแล้ว เราขอแนะนำให้ใช้ CameraX หรือ Camera2 สำหรับกรณีการใช้งานที่เฉพาะเจาะจง ทั้ง CameraX และ Camera2 รองรับ Android 5.0 (API ระดับ 21) ขึ้นไป
หากต้องการดูวิธีย้ายข้อมูลจาก Camera1 ไปยัง CameraX โปรดดูหัวข้อย้ายข้อมูล Camera1 ไปยัง CameraX หรือจะใช้ทักษะแบบ Agentic สำหรับการย้ายข้อมูลจาก Camera1 ไปยัง CameraX ก็ได้
เฟรมเวิร์ก Android รองรับกล้องและฟีเจอร์กล้องต่างๆ ที่มีในอุปกรณ์ ซึ่งช่วยให้คุณถ่ายภาพและวิดีโอในแอปพลิเคชันได้ เอกสารนี้จะกล่าวถึงแนวทางที่รวดเร็วและง่ายดายในการจับภาพและวิดีโอ รวมถึงสรุปแนวทางขั้นสูงในการสร้างประสบการณ์การใช้งานกล้องที่กำหนดเองสำหรับผู้ใช้
โปรดดูแหล่งข้อมูลที่เกี่ยวข้องต่อไปนี้
ข้อควรพิจารณา
ก่อนเปิดใช้แอปพลิเคชันเพื่อใช้กล้องในอุปกรณ์ 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 (เว้นแต่คุณจะใช้ Intent เพื่อเข้าถึงกล้อง)
หากต้องการเข้าถึงกล้องหลัก ให้ใช้เมธอด 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() แล้วก็ตาม
คุณอาจต้องปรับตัวอย่างภาพจากกล้องแบบกว้างให้พอดีกับเลย์เอาต์แนวตั้งหรือในทางกลับกันโดยใช้เลย์เอาต์แบบ Letterbox ทั้งนี้ขึ้นอยู่กับขนาดหน้าต่างและสัดส่วนภาพ
การวางตัวอย่างในเลย์เอาต์
ต้องวางคลาสตัวอย่างภาพจากกล้อง เช่น ตัวอย่างที่แสดงในส่วนก่อนหน้าไว้ในเลย์เอาต์ของกิจกรรมพร้อมกับตัวควบคุมอินเทอร์เฟซผู้ใช้อื่นๆ สำหรับการถ่ายภาพหรือวิดีโอ ส่วนนี้จะแสดงวิธีสร้างเลย์เอาต์และกิจกรรมพื้นฐานสำหรับตัวอย่าง
โค้ดเลย์เอาต์ต่อไปนี้แสดงมุมมองพื้นฐานที่ใช้แสดงตัวอย่างกล้องได้ ในตัวอย่างนี้ องค์ประกอบ 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>
ในอุปกรณ์ส่วนใหญ่ การวางแนวเริ่มต้นของตัวอย่างภาพจากกล้องจะเป็นแนวนอน เลย์เอาต์ตัวอย่างนี้ระบุเลย์เอาต์แนวนอน (Landscape) และโค้ดด้านล่างจะกำหนดการวางแนวของแอปพลิเคชันเป็นแนวนอน เพื่อให้แสดงตัวอย่างกล้องได้ง่ายขึ้น คุณควรเปลี่ยนการวางแนวของกิจกรรมตัวอย่างของแอปพลิเคชันเป็นแนวนอนโดยเพิ่มข้อมูลต่อไปนี้ลงในไฟล์ 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()เพื่อรับอินสแตนซ์ของออบเจ็กต์กล้อง - Connect Preview - เตรียมตัวอย่างรูปภาพจากกล้องแบบสดโดยเชื่อมต่อ
SurfaceViewกับกล้องโดยใช้Camera.setPreviewDisplay() - Start Preview - เรียกใช้
Camera.startPreview()เพื่อเริ่มแสดงภาพจากกล้องแบบเรียลไทม์ - เริ่มบันทึกวิดีโอ - คุณต้องทำตามขั้นตอนต่อไปนี้ตามลำดับเพื่อบันทึกวิดีโอให้สำเร็จ
- ปลดล็อกกล้อง - ปลดล็อกกล้องเพื่อให้
MediaRecorderใช้ได้โดยเรียกใช้Camera.unlock() - กำหนดค่า MediaRecorder - เรียกใช้เมธอด
MediaRecorderต่อไปนี้ตามลำดับนี้ ดูข้อมูลเพิ่มเติมได้ในเอกสารอ้างอิงMediaRecordersetCamera()- ตั้งค่ากล้องที่จะใช้สำหรับการจับภาพวิดีโอ โดยใช้อินสแตนซ์ปัจจุบันของCameraในแอปพลิเคชันของคุณsetAudioSource()- ตั้งค่าแหล่งที่มาของเสียง ให้ใช้MediaRecorder.AudioSource.CAMCORDERsetVideoSource()- ตั้งค่าแหล่งที่มาของวิดีโอ โดยใช้MediaRecorder.VideoSource.CAMERA- ตั้งค่ารูปแบบเอาต์พุตและการเข้ารหัสวิดีโอ สำหรับ Android 2.2 (API ระดับ 8) ขึ้นไป ให้ใช้เมธอด
MediaRecorder.setProfileและรับอินสแตนซ์โปรไฟล์โดยใช้CamcorderProfile.get()สำหรับ Android เวอร์ชันก่อน 2.2 คุณต้องตั้งค่ารูปแบบเอาต์พุตวิดีโอและพารามิเตอร์การเข้ารหัส ดังนี้setOutputFormat()- ตั้งค่ารูปแบบเอาต์พุต ระบุการตั้งค่าเริ่มต้นหรือMediaRecorder.OutputFormat.MPEG_4setAudioEncoder()- ตั้งค่าประเภทการเข้ารหัสเสียง ระบุการตั้งค่าเริ่มต้นหรือMediaRecorder.AudioEncoder.AMR_NBsetVideoEncoder()- ตั้งค่าประเภทการเข้ารหัสวิดีโอ ระบุการตั้งค่าเริ่มต้นหรือMediaRecorder.VideoEncoder.MPEG_4_SP
setOutputFile()- ตั้งค่าไฟล์เอาต์พุต โดยใช้getOutputMediaFile(MEDIA_TYPE_VIDEO).toString()จากเมธอดตัวอย่างในส่วนการบันทึกไฟล์สื่อsetPreviewDisplay()- ระบุองค์ประกอบเลย์เอาต์ตัวอย่างSurfaceViewสำหรับแอปพลิเคชันของคุณ ใช้ออบเจ็กต์เดียวกับที่คุณระบุไว้สำหรับแสดงตัวอย่างการเชื่อมต่อ
ข้อควรระวัง: คุณต้องเรียกใช้เมธอดการกำหนดค่า
MediaRecorderเหล่านี้ตามลำดับนี้ ไม่เช่นนั้นแอปพลิเคชันจะพบข้อผิดพลาดและการบันทึกจะล้มเหลว - เตรียม MediaRecorder - เตรียม
MediaRecorderด้วยการตั้งค่าที่ให้มาโดยเรียกใช้MediaRecorder.prepare() - เริ่ม MediaRecorder - เริ่มบันทึกวิดีโอโดยเรียกใช้
MediaRecorder.start()
- ปลดล็อกกล้อง - ปลดล็อกกล้องเพื่อให้
- หยุดบันทึกวิดีโอ - เรียกใช้เมธอดต่อไปนี้ตามลำดับเพื่อบันทึกวิดีโอให้เสร็จสมบูรณ์
- หยุด MediaRecorder - หยุดบันทึกวิดีโอโดยเรียกใช้
MediaRecorder.stop() - รีเซ็ต MediaRecorder - นำการตั้งค่าการกำหนดค่าออกจากโปรแกรมบันทึกโดยเรียกใช้
MediaRecorder.reset()(ไม่บังคับ) - Release MediaRecorder - ปล่อย
MediaRecorderโดยเรียกใช้MediaRecorder.release() - ล็อกกล้อง - ล็อกกล้องเพื่อให้เซสชัน
MediaRecorderในอนาคตใช้กล้องได้โดยการเรียกใช้Camera.lock()ตั้งแต่ Android 4.0 (API ระดับ 14) เป็นต้นไป การเรียกนี้ไม่จำเป็น เว้นแต่การเรียกMediaRecorder.prepare()จะไม่สำเร็จ
- หยุด MediaRecorder - หยุดบันทึกวิดีโอโดยเรียกใช้
- หยุดการแสดงตัวอย่าง - เมื่อกิจกรรมใช้กล้องเสร็จแล้ว ให้หยุดการแสดงตัวอย่างโดยใช้
Camera.stopPreview() - Release Camera - ปล่อยกล้องเพื่อให้แอปพลิเคชันอื่นๆ ใช้ได้โดยเรียกใช้
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) เพื่อประหยัดพื้นที่ของระบบและอนุญาตให้ผู้ใช้เข้าถึงไฟล์เหล่านี้ได้โดยไม่ต้องใช้อุปกรณ์ มีตำแหน่งไดเรกทอรีที่เป็นไปได้หลายตำแหน่งสำหรับบันทึกไฟล์สื่อในอุปกรณ์ อย่างไรก็ตาม มีตำแหน่งมาตรฐานเพียง 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 อธิบายรูปร่างสี่เหลี่ยมผืนผ้าที่แมปบนตารางกริดขนาด 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>) จะไม่มีผล
การใช้ฟีเจอร์การตรวจจับใบหน้าในแอปพลิเคชันกล้องมีขั้นตอนทั่วไปดังนี้
- ตรวจสอบว่าอุปกรณ์รองรับการตรวจจับใบหน้า
- สร้าง Listener การตรวจจับใบหน้า
- เพิ่ม Listener การตรวจจับใบหน้าลงในออบเจ็กต์กล้อง
- เริ่มการตรวจจับใบหน้าหลังจากการแสดงตัวอย่าง (และหลังจากรีสตาร์ทการแสดงตัวอย่างทุกครั้ง)
อุปกรณ์บางรุ่นไม่รองรับฟีเจอร์การตรวจจับใบหน้า คุณตรวจสอบได้ว่าฟีเจอร์นี้รองรับหรือไม่โดยโทรไปที่ getMaxNumDetectedFaces() ตัวอย่างการตรวจสอบนี้แสดงอยู่ในเมธอดตัวอย่าง 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() ของกิจกรรมหลักของแอปกล้อง เนื่องจากตัวอย่างจะไม่พร้อมใช้งาน ณ จุดนี้ในการดำเนินการของแอปพลิเคชัน
วิดีโอไทม์แลปส์
วิดีโอไทม์แลปส์ช่วยให้ผู้ใช้สร้างวิดีโอคลิปที่รวมรูปภาพที่ถ่ายห่างกันไม่กี่วินาทีหรือนาทีได้ ฟีเจอร์นี้ใช้ MediaRecorder เพื่อบันทึกรูปภาพสำหรับลำดับไทม์แลปส์
หากต้องการบันทึกวิดีโอไทม์แลปส์ด้วย MediaRecorder คุณต้องกำหนดค่าออบเจ็กต์โปรแกรมบันทึกเหมือนกับว่าคุณกำลังบันทึกวิดีโอปกติ โดยตั้งค่าเฟรมต่อวินาทีที่บันทึกเป็นตัวเลขต่ำๆ และใช้การตั้งค่าคุณภาพไทม์แลปส์อย่างใดอย่างหนึ่ง ดังที่แสดงในตัวอย่างโค้ดด้านล่าง
Kotlin
mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH)) mediaRecorder.setCaptureRate(0.1) // capture a frame every 10 seconds
Java
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher) mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH)); ... // Step 5.5: Set the video capture rate to a low number mediaRecorder.setCaptureRate(0.1); // capture a frame every 10 seconds
การตั้งค่าเหล่านี้ต้องทำเป็นส่วนหนึ่งของขั้นตอนการกำหนดค่าที่ใหญ่ขึ้นสำหรับ MediaRecorder ดูตัวอย่างโค้ดการกำหนดค่าแบบเต็มได้ที่การกำหนดค่า MediaRecorder เมื่อกำหนดค่าเสร็จแล้ว ให้เริ่มบันทึกวิดีโอเหมือนกับที่บันทึกวิดีโอคลิปตามปกติ ดูข้อมูลเพิ่มเติมเกี่ยวกับการกำหนดค่าและการเรียกใช้ MediaRecorder ได้ที่การจับภาพวิดีโอ
ตัวอย่าง Camera2Video และ HdrViewfinder จะสาธิตการใช้ API ที่ครอบคลุมในหน้านี้เพิ่มเติม
ช่องของกล้องที่ต้องได้รับสิทธิ์
แอปที่ใช้ Android 10 (API ระดับ 29) ขึ้นไปต้องมีสิทธิ์ CAMERA เพื่อเข้าถึงค่าของช่องต่อไปนี้ที่เมธอด getCameraCharacteristics() แสดงผล
LENS_POSE_ROTATIONLENS_POSE_TRANSLATIONLENS_INTRINSIC_CALIBRATIONLENS_RADIAL_DISTORTIONLENS_POSE_REFERENCELENS_DISTORTIONLENS_INFO_HYPERFOCAL_DISTANCELENS_INFO_MINIMUM_FOCUS_DISTANCESENSOR_REFERENCE_ILLUMINANT1SENSOR_REFERENCE_ILLUMINANT2SENSOR_CALIBRATION_TRANSFORM1SENSOR_CALIBRATION_TRANSFORM2SENSOR_COLOR_TRANSFORM1SENSOR_COLOR_TRANSFORM2SENSOR_FORWARD_MATRIX1SENSOR_FORWARD_MATRIX2
โค้ดตัวอย่างเพิ่มเติม
หากต้องการดาวน์โหลดแอปตัวอย่าง โปรดดูตัวอย่าง Camera2Basic และแอปตัวอย่าง CameraX อย่างเป็นทางการ