เฟรมเวิร์ก Android รองรับกล้องและฟีเจอร์กล้องต่างๆ ที่มีใน อุปกรณ์ ซึ่งช่วยให้คุณถ่ายภาพและวิดีโอในแอปพลิเคชันได้ เอกสารนี้จะกล่าวถึงแนวทางที่รวดเร็วและง่ายดายในการจับภาพและวิดีโอ รวมถึงอธิบายแนวทางขั้นสูงในการสร้าง ประสบการณ์การใช้งานกล้องที่กำหนดเองสำหรับผู้ใช้
หมายเหตุ:
หน้านี้อธิบายเกี่ยวกับคลาส
Camera
ซึ่งเลิกใช้งานแล้ว เราขอแนะนำให้ใช้ไลบรารี Jetpack CameraX หรือคลาส
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
คลาสนี้แสดงตัวอย่างรูปภาพสดจากกล้อง - สร้างเลย์เอาต์ตัวอย่าง - เมื่อมีคลาสตัวอย่างกล้องแล้ว ให้สร้างเลย์เอาต์ มุมมองที่รวมตัวอย่างและการควบคุมอินเทอร์เฟซผู้ใช้ที่คุณต้องการ
- ตั้งค่า Listener สำหรับ Capture - เชื่อมต่อ 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
เพื่อบันทึกเหตุการณ์เรียกกลับ
สำหรับการสร้างและทำลายมุมมอง ซึ่งจำเป็นต่อการกำหนดอินพุตตัวอย่างกล้อง
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
element มีไว้เพื่อเป็น
คอนเทนเนอร์สำหรับคลาสตัวอย่างกล้อง เลย์เอาต์ประเภทนี้ใช้เพื่อให้สามารถวางซ้อนข้อมูลหรือการควบคุมรูปภาพเพิ่มเติมบนรูปภาพตัวอย่างกล้องสดได้
<?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()
เพื่อตั้งค่าการหมุนของรูปภาพตัวอย่างได้ หากต้องการเปลี่ยนการวางแนวของตัวอย่างเมื่อผู้ใช้เปลี่ยนการวางแนวของโทรศัพท์ ให้หยุดตัวอย่างด้วย Camera.stopPreview()
ภายในเมธอด surfaceChanged()
ของคลาสตัวอย่างของคุณก่อน จากนั้นเปลี่ยนการวางแนว แล้วเริ่มตัวอย่างอีกครั้งด้วย 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()
- เริ่มแสดงตัวอย่าง - เรียกใช้
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
สำหรับ แอปพลิเคชันของคุณ ใช้ออบเจ็กต์เดียวกันกับที่ระบุไว้สำหรับเชื่อมต่อตัวอย่าง
ข้อควรระวัง: คุณต้องเรียกใช้
MediaRecorder
วิธีการกำหนดค่าเหล่านี้ตามลำดับนี้ มิฉะนั้นแอปพลิเคชันจะพบข้อผิดพลาดและบันทึกไม่ได้ - เตรียม MediaRecorder - เตรียม
MediaRecorder
ด้วยการตั้งค่าที่ระบุโดยการเรียกใช้MediaRecorder.prepare()
- Start MediaRecorder - เริ่มบันทึกวิดีโอโดยเรียกใช้
MediaRecorder.start()
- ปลดล็อกกล้อง - ปลดล็อกกล้องเพื่อให้
- หยุดบันทึกวิดีโอ - เรียกใช้เมธอดต่อไปนี้ตามลำดับเพื่อบันทึกวิดีโอให้เสร็จสมบูรณ์
- Stop MediaRecorder - หยุดบันทึกวิดีโอโดยเรียกใช้
MediaRecorder.stop()
- รีเซ็ต MediaRecorder - คุณจะนำการตั้งค่าออกจากเครื่องบันทึกได้โดยเรียกใช้
MediaRecorder.reset()
(ไม่บังคับ) - Release MediaRecorder - Release the
MediaRecorder
by callingMediaRecorder.release()
. - ล็อกกล้อง - ล็อกกล้องเพื่อให้เซสชัน
MediaRecorder
ในอนาคตใช้กล้องได้โดยการเรียกใช้Camera.lock()
เริ่มตั้งแต่ Android 4.0 (API ระดับ 14) เป็นต้นไป ไม่จำเป็นต้องโทรนี้ เว้นแต่การโทรMediaRecorder.prepare()
จะล้มเหลว
- Stop MediaRecorder - หยุดบันทึกวิดีโอโดยเรียกใช้
- หยุดการแสดงตัวอย่าง - เมื่อกิจกรรมที่ใช้กล้องเสร็จสิ้นแล้ว ให้หยุด
การแสดงตัวอย่างโดยใช้
Camera.stopPreview()
- ปล่อยกล้อง - ปล่อยกล้องเพื่อให้แอปพลิเคชันอื่นๆ ใช้กล้องได้โดยการเรียก
Camera.release()
หมายเหตุ: คุณสามารถใช้ MediaRecorder
โดยไม่ต้องสร้างตัวอย่างกล้องก่อนและข้าม 2-3 ขั้นตอนแรกของกระบวนการนี้ได้ อย่างไรก็ตาม เนื่องจากโดยปกติแล้วผู้ใช้มักจะต้องการดูตัวอย่างก่อนเริ่มบันทึก เราจึงจะไม่กล่าวถึงกระบวนการดังกล่าวในที่นี้
เคล็ดลับ: หากปกติคุณใช้แอปพลิเคชันเพื่อบันทึกวิดีโอ ให้ตั้งค่า
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()
แทน ดูข้อมูลเพิ่มเติมได้ที่การบันทึกไฟล์ที่แชร์
หากต้องการให้ URI รองรับโปรไฟล์งาน ให้
แปลง URI ของไฟล์เป็น URI ของเนื้อหาก่อน จากนั้นเพิ่ม URI ของเนื้อหาไปยัง
EXTRA_OUTPUT
ของ Intent
ดูข้อมูลเพิ่มเติมเกี่ยวกับการบันทึกไฟล์ในอุปกรณ์ Android ได้ที่ที่เก็บข้อมูล
ฟีเจอร์ของกล้อง
Android รองรับฟีเจอร์กล้องมากมายที่คุณควบคุมได้ด้วยแอปพลิเคชันกล้อง
เช่น รูปแบบรูปภาพ โหมดแฟลช การตั้งค่าโฟกัส และอื่นๆ อีกมากมาย ส่วนนี้แสดงรายการฟีเจอร์กล้องทั่วไป
และอธิบายวิธีใช้ฟีเจอร์เหล่านั้นโดยย่อ คุณเข้าถึงและตั้งค่าฟีเจอร์กล้องส่วนใหญ่ได้
โดยใช้ผ่านออบเจ็กต์ Camera.Parameters
อย่างไรก็ตาม มีฟีเจอร์สำคัญหลายอย่างที่ต้องมีการตั้งค่าที่ซับซ้อนกว่าการตั้งค่าทั่วไปใน Camera.Parameters
ฟีเจอร์เหล่านี้จะอธิบายไว้ในส่วนต่อไปนี้
ดูข้อมูลทั่วไปเกี่ยวกับวิธีใช้ฟีเจอร์ที่ควบคุมผ่าน Camera.Parameters
ได้ที่ส่วนการใช้ฟีเจอร์
กล้อง ดูข้อมูลโดยละเอียดเพิ่มเติมเกี่ยวกับวิธีใช้ฟีเจอร์ที่ควบคุมผ่านออบเจ็กต์พารามิเตอร์กล้องได้โดยคลิกลิงก์ในรายการฟีเจอร์ด้านล่างเพื่อไปยังเอกสารประกอบอ้างอิง API
ตารางที่ 1 ฟีเจอร์กล้องทั่วไปเรียงตามระดับ API ของ Android ที่มีการเปิดตัวฟีเจอร์นั้นๆ
ฟีเจอร์ | ระดับ API | คำอธิบาย |
---|---|---|
การตรวจจับใบหน้า | 14 | ระบุใบหน้ามนุษย์ภายในรูปภาพและใช้ใบหน้าเหล่านั้นเพื่อโฟกัส การวัดแสง และไวต์ บาลานซ์ |
พื้นที่การวัดการใช้งาน | 14 | ระบุพื้นที่อย่างน้อย 1 พื้นที่ภายในรูปภาพเพื่อคำนวณไวต์บาลานซ์ |
Focus Areas | 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 เส้นสีแดงแสดงระบบพิกัดสำหรับการระบุ a
Camera.Area
ภายในตัวอย่างกล้อง กรอบสีน้ำเงินแสดงตำแหน่งและ
รูปร่างของพื้นที่กล้องที่มีค่า Rect
333,333,667,667
ขอบเขตของระบบพิกัดนี้จะสอดคล้องกับขอบด้านนอกของรูปภาพที่มองเห็นใน
ตัวอย่างกล้องเสมอ และจะไม่หดหรือขยายตามระดับการซูม ในทำนองเดียวกัน การหมุนภาพ
ตัวอย่างโดยใช้ Camera.setDisplayOrientation()
จะไม่เปลี่ยนระบบพิกัด
การตรวจจับใบหน้า
สำหรับรูปภาพที่มีบุคคล ใบหน้ามักเป็นส่วนที่สำคัญที่สุดของรูปภาพ และควรใช้เพื่อกำหนดทั้งโฟกัสและไวต์บาลานซ์เมื่อถ่ายภาพ เฟรมเวิร์ก Android 4.0 (API ระดับ 14) มี API สำหรับระบุใบหน้าและคำนวณการตั้งค่ารูปภาพโดยใช้ เทคโนโลยีการจดจำใบหน้า
หมายเหตุ: ขณะที่ฟีเจอร์การตรวจจับใบหน้าทำงานอยู่
setWhiteBalance(String)
setFocusAreas(List<Camera.Area>)
และ
setMeteringAreas(List<Camera.Area>)
จะไม่มีผล
การใช้ฟีเจอร์การตรวจจับใบหน้าในแอปพลิเคชันกล้องต้องทำตามขั้นตอนทั่วไป 2-3 ขั้นตอน
- ตรวจสอบว่าอุปกรณ์รองรับการตรวจจับใบหน้า
- สร้างเครื่องมือฟังการตรวจจับใบหน้า
- เพิ่มเครื่องมือฟังการตรวจจับใบหน้าไปยังออบเจ็กต์กล้อง
- เริ่มการตรวจหาใบหน้าหลังจากแสดงตัวอย่าง (และหลังจากรีสตาร์ทการแสดงตัวอย่างทุกครั้ง)
อุปกรณ์บางรุ่นไม่รองรับฟีเจอร์การตรวจหาใบหน้า คุณตรวจสอบได้ว่าฟีเจอร์นี้
รองรับโดยการโทรหา getMaxNumDetectedFaces()
startFaceDetection()
ตัวอย่างวิธีนี้แสดงไว้ในตัวอย่างด้านล่าง
หากต้องการรับการแจ้งเตือนและตอบสนองต่อการตรวจจับใบหน้า แอปพลิเคชันกล้องต้องตั้งค่า
เครื่องมือฟังสำหรับเหตุการณ์การตรวจจับใบหน้า หากต้องการดำเนินการนี้ คุณต้องสร้างคลาส Listener ที่
ใช้Camera.FaceDetectionListener
อินเทอร์เฟซตามที่แสดงใน
โค้ดตัวอย่างด้านล่าง
Kotlin
internal class MyFaceDetectionListener : Camera.FaceDetectionListener { override fun onFaceDetection(faces: Array<Camera.Face>, camera: Camera) { if (faces.isNotEmpty()) { Log.d("FaceDetection", ("face detected: ${faces.size}" + " Face 1 Location X: ${faces[0].rect.centerX()}" + "Y: ${faces[0].rect.centerY()}")) } } }
Java
class MyFaceDetectionListener implements Camera.FaceDetectionListener { @Override public void onFaceDetection(Face[] faces, Camera camera) { if (faces.length > 0){ Log.d("FaceDetection", "face detected: "+ faces.length + " Face 1 Location X: " + faces[0].rect.centerX() + "Y: " + faces[0].rect.centerY() ); } } }
หลังจากสร้างคลาสนี้แล้ว คุณจะตั้งค่าในออบเจ็กต์
Camera
ของแอปพลิเคชันได้ ดังที่แสดงในตัวอย่างโค้ดด้านล่าง
Kotlin
camera?.setFaceDetectionListener(MyFaceDetectionListener())
Java
camera.setFaceDetectionListener(new MyFaceDetectionListener());
แอปพลิเคชันของคุณต้องเริ่มฟังก์ชันการตรวจจับใบหน้าทุกครั้งที่คุณเริ่ม (หรือรีสตาร์ท) ตัวอย่างกล้อง สร้างวิธีการเริ่มต้นการตรวจจับใบหน้าเพื่อให้เรียกใช้ได้ตามต้องการ ดังที่แสดง ในโค้ดตัวอย่างด้านล่าง
Kotlin
fun startFaceDetection() { // Try starting Face Detection val params = mCamera?.parameters // start face detection only *after* preview has started params?.apply { if (maxNumDetectedFaces > 0) { // camera supports face detection, so can start it: mCamera?.startFaceDetection() } } }
Java
public void startFaceDetection(){ // Try starting Face Detection Camera.Parameters params = mCamera.getParameters(); // start face detection only *after* preview has started if (params.getMaxNumDetectedFaces() > 0){ // camera supports face detection, so can start it: mCamera.startFaceDetection(); } }
คุณต้องเริ่มการตรวจจับใบหน้าทุกครั้งที่เริ่ม (หรือเริ่มใหม่) ตัวอย่างกล้อง หากคุณใช้คลาสตัวอย่างที่แสดงในการสร้างคลาสตัวอย่าง ให้เพิ่มเมธอด
startFaceDetection()
ลงในเมธอด surfaceCreated()
และ surfaceChanged()
ในคลาสตัวอย่าง
ตามที่แสดงในโค้ดตัวอย่างด้านล่าง
Kotlin
override fun surfaceCreated(holder: SurfaceHolder) { try { mCamera.setPreviewDisplay(holder) mCamera.startPreview() startFaceDetection() // start face detection feature } catch (e: IOException) { Log.d(TAG, "Error setting camera preview: ${e.message}") } } override fun surfaceChanged(holder: SurfaceHolder, format: Int, w: Int, h: Int) { if (holder.surface == null) { // preview surface does not exist Log.d(TAG, "holder.getSurface() == null") return } try { mCamera.stopPreview() } catch (e: Exception) { // ignore: tried to stop a non-existent preview Log.d(TAG, "Error stopping camera preview: ${e.message}") } try { mCamera.setPreviewDisplay(holder) mCamera.startPreview() startFaceDetection() // re-start face detection feature } catch (e: Exception) { // ignore: tried to stop a non-existent preview Log.d(TAG, "Error starting camera preview: ${e.message}") } }
Java
public void surfaceCreated(SurfaceHolder holder) { try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); startFaceDetection(); // start face detection feature } catch (IOException e) { Log.d(TAG, "Error setting camera preview: " + e.getMessage()); } } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { if (holder.getSurface() == null){ // preview surface does not exist Log.d(TAG, "holder.getSurface() == null"); return; } try { mCamera.stopPreview(); } catch (Exception e){ // ignore: tried to stop a non-existent preview Log.d(TAG, "Error stopping camera preview: " + e.getMessage()); } try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); startFaceDetection(); // re-start face detection feature } catch (Exception e){ // ignore: tried to stop a non-existent preview Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } }
หมายเหตุ: อย่าลืมเรียกใช้เมธอดนี้หลังจากเรียกใช้
startPreview()
อย่าพยายามเริ่มการตรวจหาใบหน้า
ในเมธอด onCreate()
ของกิจกรรมหลักของแอปกล้อง
เนื่องจากตัวอย่างจะไม่พร้อมใช้งาน ณ จุดนี้ในการดำเนินการของแอปพลิเคชัน
วิดีโอไทม์แลปส์
วิดีโอไทม์แลปส์ช่วยให้ผู้ใช้สร้างวิดีโอคลิปที่รวมรูปภาพซึ่งถ่ายห่างกันไม่กี่วินาทีหรือ
นาที ฟีเจอร์นี้ใช้ 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 อย่างเป็นทางการ