เฟรมเวิร์ก Android รองรับกล้องและฟีเจอร์กล้องต่างๆ ที่มีในอุปกรณ์ ซึ่งช่วยให้คุณจับภาพและวิดีโอในแอปพลิเคชันได้ เอกสารนี้อธิบายแนวทางที่รวดเร็วและง่ายดายในการจับภาพและวิดีโอ รวมถึงอธิบายแนวทางขั้นสูงในการสร้างประสบการณ์การใช้งานกล้องที่ปรับแต่งเองให้กับผู้ใช้
หมายเหตุ:
หน้านี้อธิบายคลาส Camera
ซึ่งเลิกใช้งานแล้ว เราขอแนะนำให้ใช้ไลบรารี CameraX ของ Jetpack หรือคลาส camera2
สำหรับ Use Case บางรายการ ทั้ง 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
(เว้นแต่คุณจะใช้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()
แล้วก็ตาม
คุณอาจต้องปรับให้ตัวอย่างภาพจากกล้องแบบมุมกว้างพอดีกับเลย์เอาต์แนวตั้ง หรือในทางกลับกันโดยใช้เลย์เอาต์แถบดำด้านบนและด้านล่าง ทั้งนี้ขึ้นอยู่กับขนาดหน้าต่างและสัดส่วนภาพ
การวางตัวอย่างในเลย์เอาต์
คลาสแสดงตัวอย่างจากกล้องถ่ายรูปอย่างเช่นตัวอย่างที่แสดงในส่วนก่อนหน้านี้ จะต้องอยู่ในการจัดวางกิจกรรมพร้อมกับส่วนควบคุมอินเทอร์เฟซผู้ใช้อื่นๆ สำหรับการถ่ายภาพหรือวิดีโอ ส่วนนี้จะแสดงวิธีสร้างเลย์เอาต์และกิจกรรมพื้นฐานสำหรับตัวอย่างเพลง
โค้ดเลย์เอาต์ต่อไปนี้แสดงมุมมองพื้นฐานมากซึ่งสามารถใช้เพื่อแสดงตัวอย่างจากกล้อง ในตัวอย่างนี้ องค์ประกอบ 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()
ในตัวอย่างด้านบนหมายถึงวิธีการตัวอย่างที่แสดงในการเข้าถึงกล้อง
การถ่ายภาพ
เมื่อคุณสร้างคลาสตัวอย่างและเลย์เอาต์มุมมองที่จะแสดงแล้ว คุณก็พร้อมที่จะ จับภาพด้วยแอปพลิเคชันของคุณ ในโค้ดแอปพลิเคชัน คุณต้องตั้งค่า Listeners สำหรับการควบคุมอินเทอร์เฟซผู้ใช้เพื่อตอบสนองการดําเนินการของผู้ใช้ด้วยการถ่ายภาพ
หากต้องการดึงภาพ ให้ใช้เมธอด 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()
เพื่อเริ่มแสดงภาพสดจากกล้อง - เริ่มบันทึกวิดีโอ - คุณต้องทําตามขั้นตอนต่อไปนี้เพื่อบันทึกวิดีโอให้สําเร็จ
- ปลดล็อกกล้อง - ปลดล็อกกล้องเพื่อให้
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()
method หมายถึงโค้ดตัวอย่างที่แสดงในการกำหนดค่า 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()
instead. โปรดดูข้อมูลเพิ่มเติมที่การบันทึกไฟล์ที่แชร์
หากต้องการให้ URI รองรับโปรไฟล์งาน ให้
แปลง URI ของไฟล์เป็น URI ของเนื้อหาก่อน จากนั้นเพิ่ม URI เนื้อหาไปยัง EXTRA_OUTPUT
ของ Intent
โปรดดูข้อมูลเพิ่มเติมเกี่ยวกับการบันทึกไฟล์ในอุปกรณ์ Android ที่พื้นที่เก็บข้อมูล
ฟีเจอร์ของกล้อง
Android รองรับฟีเจอร์กล้องที่หลากหลายซึ่งคุณควบคุมได้ด้วยแอปพลิเคชันกล้อง เช่น รูปแบบรูปภาพ โหมดแฟลช การตั้งค่าโฟกัส และอื่นๆ อีกมากมาย ส่วนนี้จะแสดงรายการฟีเจอร์กล้องทั่วไปและอธิบายวิธีใช้คร่าวๆ ฟีเจอร์กล้องส่วนใหญ่จะเข้าถึงและตั้งค่าได้โดยใช้ออบเจ็กต์ Camera.Parameters
อย่างไรก็ตาม ฟีเจอร์สำคัญหลายอย่างต้องใช้การตั้งค่ามากกว่าการตั้งค่าง่ายๆ ใน Camera.Parameters
ฟีเจอร์เหล่านี้จะกล่าวถึงในส่วนต่อไปนี้
ดูข้อมูลทั่วไปเกี่ยวกับวิธีใช้ฟีเจอร์ที่ควบคุมผ่าน Camera.Parameters
ได้ที่ส่วนการใช้ฟีเจอร์ของกล้อง ดูข้อมูลโดยละเอียดเพิ่มเติมเกี่ยวกับวิธีใช้ฟีเจอร์ที่ควบคุมผ่านออบเจ็กต์พารามิเตอร์กล้องได้โดยไปที่เอกสารอ้างอิง API ในรายการฟีเจอร์ด้านล่าง
ฟีเจอร์ | ระดับ 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 จะแสดงถึงมุมขวาด้านล่างของภาพกล้องดังที่แสดงในภาพประกอบด้านล่าง
ขอบเขตของระบบพิกัดนี้จะสอดคล้องกับขอบด้านนอกของรูปภาพที่มองเห็นในตัวอย่างกล้องเสมอ และไม่หดหรือขยายตามระดับการซูม ในทํานองเดียวกัน การหมุนตัวอย่างรูปภาพโดยใช้ 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 วินาทีหรือนาที ฟีเจอร์นี้ใช้ 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_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 อย่างเป็นทางการ