เฟรมเวิร์กของ Android ประกอบด้วยการสนับสนุนสำหรับฟีเจอร์กล้องและกล้องต่างๆ ที่มีให้ใช้งานใน เพื่อถ่ายภาพและวิดีโอในแอปพลิเคชันของคุณได้ เอกสารฉบับนี้กล่าวถึง วิธีการจับภาพและวิดีโอที่เรียบง่ายและรวดเร็ว รวมทั้งแสดงให้เห็นถึงวิธีการขั้นสูงในการสร้าง ประสบการณ์การใช้งานกล้องแบบกำหนดเองสำหรับผู้ใช้
หมายเหตุ
หน้านี้จะอธิบายถึง
Camera
คลาสที่เลิกใช้งานแล้ว เราขอแนะนำให้ใช้
ไลบรารี cameraX Jetpack หรือสำหรับกรณีการใช้งานเฉพาะ
camera2
,
ทั้ง CameraX และ Camera2 สามารถใช้กับ Android 5.0 (API ระดับ 21) และ
สูงขึ้น
โปรดดูแหล่งข้อมูลที่เกี่ยวข้องต่อไปนี้
ข้อควรพิจารณา
ก่อนที่จะเปิดให้แอปพลิเคชันของคุณใช้กล้องถ่ายรูปบนอุปกรณ์ Android คุณควรพิจารณา คำถามเกี่ยวกับวิธีที่แอปของคุณตั้งใจจะใช้ฟีเจอร์ของฮาร์ดแวร์นี้
- ความต้องการของกล้อง - การใช้กล้องมีความสำคัญต่อ ที่คุณไม่ต้องการให้ติดตั้งแอปพลิเคชันของคุณบนอุปกรณ์ที่ไม่มี กล้องถ่ายรูป ถ้าใช่ คุณควรประกาศข้อกำหนดสำหรับกล้องใน ไฟล์ Manifest
- ภาพด่วนหรือกล้องที่ปรับแต่งเอง - แอปพลิเคชันของคุณจะใช้ กล้องถ่ายรูป คุณแค่สนใจที่จะถ่ายภาพหรือวิดีโอคลิปสั้นๆ หรือว่าแอปพลิเคชันของคุณ มีวิธีการใช้กล้องแบบใหม่ไหม หากต้องการถ่ายรูปหรือถ่ายคลิปอย่างรวดเร็ว ให้พิจารณา ใช้แอปกล้องถ่ายรูปที่มีอยู่ สำหรับการพัฒนาฟีเจอร์กล้องถ่ายรูปแบบกำหนดเอง โปรดดู ในส่วนการสร้างแอปกล้องถ่ายรูป
- ข้อกําหนดของบริการที่ทำงานอยู่เบื้องหน้า - แอปของคุณจะโต้ตอบกับ กล้องล่ะ ใน Android 9 (API ระดับ 28) ขึ้นไป แอปที่ทำงานในเวอร์ชัน พื้นหลังไม่สามารถเข้าถึงกล้องถ่ายรูป ดังนั้น คุณควรใช้กล้อง เมื่อแอปทำงานอยู่เบื้องหน้าหรือเป็นส่วนหนึ่งของ บริการที่ทำงานอยู่เบื้องหน้า
- พื้นที่เก็บข้อมูล - รูปภาพหรือวิดีโอที่แอปพลิเคชันสร้างไว้หรือไม่ มองเห็นได้เฉพาะแอปพลิเคชันของคุณหรือใช้ร่วมกัน เพื่อให้แอปพลิเคชันอื่น เช่น แกลเลอรี หรือ แอปสื่อและแอปโซเชียลใช้ได้ไหม คุณต้องการให้รูปภาพและวิดีโอพร้อมใช้งานแม้ว่า ถอนการติดตั้งแอปพลิเคชันแล้วใช่ไหม โปรดดูที่ส่วนการบันทึกไฟล์สื่อเพื่อ ดูวิธีนำตัวเลือกเหล่านี้ไปใช้
ข้อมูลเบื้องต้น
เฟรมเวิร์กของ Android รองรับการจับภาพและวิดีโอผ่าน
android.hardware.camera2
API หรือกล้อง Intent
นี่คือข่าวที่เกี่ยวข้อง
ชั้นเรียน:
android.hardware.camera2
- แพ็กเกจนี้เป็น API หลักสำหรับควบคุมกล้องของอุปกรณ์ ซึ่งใช้เพื่อ รูปภาพหรือวิดีโอเมื่อคุณสร้างแอปพลิเคชันกล้องถ่ายรูป
Camera
- คลาสนี้เป็น API เวอร์ชันเก่าที่เลิกใช้งานสำหรับการควบคุมกล้องของอุปกรณ์
SurfaceView
- ชั้นเรียนนี้ใช้เพื่อแสดงตัวอย่างจากกล้องแบบสดต่อผู้ใช้
MediaRecorder
- ชั้นเรียนนี้ใช้เพื่อบันทึกวิดีโอจากกล้อง
Intent
- คุณใช้ประเภทการดำเนินการผ่าน Intent ของ
MediaStore.ACTION_IMAGE_CAPTURE
หรือMediaStore.ACTION_VIDEO_CAPTURE
เพื่อจับภาพหรือวิดีโอได้โดยไม่ต้องใช้โดยตรง โดยใช้ออบเจ็กต์Camera
การประกาศไฟล์ Manifest
ก่อนที่จะเริ่มการพัฒนาในแอปพลิเคชันด้วย Camera API คุณควรตรวจสอบ ไฟล์ Manifest ของคุณมีประกาศที่เหมาะสมเพื่ออนุญาตให้ใช้ฮาร์ดแวร์กล้องและ ฟีเจอร์ที่เกี่ยวข้อง
- สิทธิ์เข้าถึงกล้อง - แอปพลิเคชันต้องขอสิทธิ์ในการใช้อุปกรณ์
กล้อง
<uses-permission android:name="android.permission.CAMERA" />
หมายเหตุ: หากคุณใช้กล้องโดย การเรียกใช้แอปกล้องที่มีอยู่ แอปพลิเคชันของคุณไม่จำเป็นต้องขอสิทธิ์นี้
- ฟีเจอร์กล้องถ่ายรูป - แอปพลิเคชันต้องประกาศการใช้ฟีเจอร์ของกล้องด้วย
เช่น
<uses-feature android:name="android.hardware.camera" />
สำหรับรายการฟีเจอร์กล้อง โปรดดูไฟล์ Manifest ฟีเจอร์ ข้อมูลอ้างอิง
การเพิ่มฟีเจอร์กล้องลงในไฟล์ Manifest จะทำให้ Google Play ป้องกันไม่ให้แอปพลิเคชันของคุณ ได้รับการติดตั้งบนอุปกรณ์ที่ไม่มีกล้อง หรือไม่รองรับฟีเจอร์กล้องที่คุณ ระบุ ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้การกรองตามฟีเจอร์กับ Google Play ได้ที่ Google การกรอง Play และฟีเจอร์ตามฟีเจอร์
หากแอปพลิเคชันของคุณสามารถใช้ฟีเจอร์กล้องหรือกล้องเพื่อการทำงานที่เหมาะสม แต่ ไม่ต้องการ คุณควรระบุข้อมูลนี้ในไฟล์ Manifest โดยใส่แอตทริบิวต์
android:required
และตั้งค่าเป็นfalse
:<uses-feature android:name="android.hardware.camera" android:required="false" />
- สิทธิ์เข้าถึงพื้นที่เก็บข้อมูล - แอปพลิเคชันของคุณสามารถบันทึกรูปภาพหรือวิดีโอลงใน
ที่จัดเก็บข้อมูลภายนอก (การ์ด SD) ของอุปกรณ์ หากกำหนดเป้าหมายเป็น Android 10 (API ระดับ 29) หรือ
ต่ำกว่าและระบุข้อมูลต่อไปนี้ในไฟล์ Manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- สิทธิ์การบันทึกเสียง - สำหรับการบันทึกเสียงพร้อมกับการบันทึกวิดีโอ
แอปพลิเคชันต้องขอสิทธิ์บันทึกเสียง
<uses-permission android:name="android.permission.RECORD_AUDIO" />
-
สิทธิ์เข้าถึงตำแหน่ง - หากแอปพลิเคชันติดแท็กรูปภาพ ด้วยข้อมูลตำแหน่ง GPS คุณต้องขอ
ACCESS_FINE_LOCATION
สิทธิ์ โปรดทราบว่าหากแอปกำหนดเป้าหมายเป็น Android 5.0 (API ระดับ 21) หรือ คุณต้องประกาศว่าแอปของคุณใช้ GPS ของอุปกรณ์ด้วย<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> ... <!-- Needed only if your app targets Android 5.0 (API level 21) or higher. --> <uses-feature android:name="android.hardware.location.gps" />
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการหาตำแหน่งของผู้ใช้ โปรดดูที่ กลยุทธ์ด้านสถานที่ตั้ง
ใช้แอปกล้องที่มีอยู่
วิธีที่รวดเร็วในการเปิดใช้การถ่ายภาพหรือวิดีโอในแอปพลิเคชันของคุณโดยไม่ต้องใช้โค้ดเพิ่มเติมมากนัก
คือการใช้ Intent
เพื่อเรียกแอปพลิเคชันกล้อง Android ที่มีอยู่
รายละเอียดอธิบายไว้ในบทเรียนการฝึกอบรม
ถ่ายภาพได้ง่ายๆ และ
การบันทึกวิดีโอง่ายๆ
การสร้างแอปกล้องถ่ายรูป
นักพัฒนาซอฟต์แวร์บางรายอาจต้องการอินเทอร์เฟซผู้ใช้ของกล้องถ่ายรูปที่ปรับแต่งให้เข้ากับรูปลักษณ์ของ หรือให้คุณลักษณะพิเศษ การเขียนโค้ดสำหรับถ่ายภาพของคุณเอง สามารถให้ประสบการณ์ที่น่าสนใจยิ่งขึ้นสำหรับผู้ใช้
หมายเหตุ: คำแนะนำต่อไปนี้เป็นคำแนะนำสำหรับ Camera
รุ่นเก่าที่เลิกใช้งานแล้ว
API สำหรับแอปพลิเคชันกล้องใหม่หรือแอปพลิเคชันกล้องขั้นสูง android.hardware.camera2
API เวอร์ชันใหม่กว่าคือ
แนะนำ
ขั้นตอนทั่วไปในการสร้างอินเทอร์เฟซกล้องถ่ายรูปที่กำหนดเองสำหรับแอปพลิเคชันมีดังนี้
- ตรวจหาและเข้าถึงกล้อง - สร้างโค้ดเพื่อตรวจหาการมีอยู่ของ และขอสิทธิ์เข้าถึง
- สร้างคลาสการแสดงตัวอย่าง - สร้างคลาสการแสดงตัวอย่างจากกล้องที่ขยาย
SurfaceView
และใช้อินเทอร์เฟซSurfaceHolder
ช่วงเวลานี้ เพื่อดูตัวอย่างภาพสดจากกล้อง - สร้างเลย์เอาต์ตัวอย่าง - เมื่อคุณมีคลาสแสดงตัวอย่างจากกล้องแล้ว ให้สร้าง ดูเลย์เอาต์ที่รวมการแสดงตัวอย่างและการควบคุมอินเทอร์เฟซผู้ใช้ที่คุณต้องการ
- ตั้งค่า Listener สำหรับการบันทึก - เชื่อมต่อ Listener สำหรับอินเทอร์เฟซของคุณ ตัวควบคุมเพื่อเริ่มจับภาพหรือวิดีโอตามการดำเนินการของผู้ใช้ เช่น การกด
- จับภาพและบันทึกไฟล์ - ตั้งค่าโค้ดสำหรับการจับภาพหรือ วิดีโอและบันทึกเอาต์พุต
- ปล่อยกล้อง - หลังจากใช้กล้อง แอปพลิเคชันต้อง เผยแพร่อย่างเหมาะสมเพื่อให้แอปพลิเคชันอื่นใช้งาน
ฮาร์ดแวร์กล้องเป็นทรัพยากรที่แชร์ร่วมกัน ซึ่งจะต้องมีการจัดการอย่างระมัดระวังเพื่อให้แอปพลิเคชันของคุณ ไม่ขัดแย้งกับแอปพลิเคชันอื่นๆ ที่อาจต้องการใช้ ส่วนต่อไปนี้จะกล่าวถึง วิธีตรวจหาฮาร์ดแวร์กล้อง วิธีขอสิทธิ์เข้าถึงกล้อง วิธีถ่ายภาพหรือวิดีโอ และวิธีปล่อยกล้องเมื่อแอปพลิเคชันใช้งานเสร็จแล้ว
ข้อควรระวัง: อย่าลืมเผยแพร่ Camera
โดยเรียก Camera.release()
เมื่อ
เสร็จสิ้นการใช้งานด้วยซ้ำ! หากแอปพลิเคชันปล่อยกล้องไม่ถูกต้อง
การเข้าถึงกล้องในภายหลัง รวมถึงการเข้าถึงโดยแอปพลิเคชันของคุณเองจะล้มเหลวและอาจ
ทำให้แอปพลิเคชันของคุณหรือแอปพลิเคชันอื่นๆ ปิดลง
กำลังตรวจหาฮาร์ดแวร์กล้อง
หากแอปพลิเคชันของคุณไม่ได้กำหนดให้ใช้กล้องโดยเฉพาะ โดยใช้การประกาศไฟล์ Manifest คุณจะต้อง
ควรตรวจสอบว่ากล้องพร้อมใช้งานขณะรันไทม์ไหม หากต้องการดำเนินการตรวจสอบนี้ ให้ใช้เมธอด PackageManager.hasSystemFeature()
ดังที่แสดงในโค้ดตัวอย่างด้านล่าง:
Kotlin
/** Check if this device has a camera */ private fun checkCameraHardware(context: Context): Boolean { if (context.packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)) { // this device has a camera return true } else { // no camera on this device return false } }
Java
/** Check if this device has a camera */ private boolean checkCameraHardware(Context context) { if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){ // this device has a camera return true; } else { // no camera on this device return false; } }
อุปกรณ์ Android สามารถมีกล้องได้หลายตัว เช่น กล้องหลังสำหรับถ่ายภาพ
กล้องหน้าสำหรับวิดีโอคอล Android 2.3 (API ระดับ 9) ขึ้นไปทำให้คุณสามารถตรวจสอบ
จำนวนกล้องที่มีในอุปกรณ์โดยใช้เมธอด Camera.getNumberOfCameras()
การเข้าถึงกล้อง
ถ้าคุณพิจารณาแล้วว่าอุปกรณ์ที่แอปพลิเคชันของคุณเรียกใช้มีกล้อง
ต้องขอสิทธิ์เข้าถึงโดยขอรับอินสแตนซ์ Camera
(ยกเว้นในกรณีที่คุณ
กำลังใช้ความตั้งใจในการเข้าถึงกล้อง)
หากต้องการเข้าถึงกล้องหลัก ให้ใช้เมธอด Camera.open()
และอย่าลืมจับข้อยกเว้นตามที่แสดงในโค้ดด้านล่าง
Kotlin
/** A safe way to get an instance of the Camera object. */ fun getCameraInstance(): Camera? { return try { Camera.open() // attempt to get a Camera instance } catch (e: Exception) { // Camera is not available (in use or does not exist) null // returns null if camera is unavailable } }
Java
/** A safe way to get an instance of the Camera object. */ public static Camera getCameraInstance(){ Camera c = null; try { c = Camera.open(); // attempt to get a Camera instance } catch (Exception e){ // Camera is not available (in use or does not exist) } return c; // returns null if camera is unavailable }
ข้อควรระวัง: ตรวจหาข้อยกเว้นเสมอเมื่อใช้ Camera.open()
ไม่สามารถตรวจหาข้อยกเว้นหากกล้องอยู่ใน
การใช้หรือไม่มีอยู่จะทำให้ระบบปิดแอปพลิเคชันของคุณ
สำหรับอุปกรณ์ที่ใช้ Android 2.3 (API ระดับ 9) ขึ้นไป คุณสามารถเข้าถึงกล้องบางตัวได้โดยใช้
Camera.open(int)
โค้ดตัวอย่างด้านบนจะเข้าถึง
เป็นกล้องหลังตัวแรกบนอุปกรณ์ที่มีกล้องมากกว่า 1 ตัว
กำลังตรวจสอบฟีเจอร์ของกล้อง
เมื่อคุณได้สิทธิ์เข้าถึงกล้อง คุณสามารถทราบข้อมูลเพิ่มเติมเกี่ยวกับความสามารถต่างๆ ของกล้องได้โดยใช้
เมธอด Camera.getParameters()
และตรวจสอบ
แสดงผลออบเจ็กต์ Camera.Parameters
สำหรับความสามารถที่รองรับ เมื่อใช้
API ระดับ 9 ขึ้นไป ให้ใช้ Camera.getCameraInfo()
เพื่อระบุว่ากล้องอยู่ด้านหน้าหรือไม่
หรือด้านหลังของอุปกรณ์ และการวางแนวของภาพ
กำลังสร้างคลาสตัวอย่าง
เพื่อให้ผู้ใช้ถ่ายภาพหรือวิดีโอได้อย่างมีประสิทธิภาพ ผู้ใช้ต้องเห็นสิ่งที่กล้องของอุปกรณ์ได้
เห็น คลาสแสดงตัวอย่างจากกล้องคือ SurfaceView
ที่แสดงรูปภาพสดได้
ข้อมูลที่มาจากกล้องถ่ายรูป เพื่อให้ผู้ใช้สามารถจัดเฟรมและจับภาพหรือวิดีโอได้
โค้ดตัวอย่างต่อไปนี้แสดงวิธีการสร้างคลาสการแสดงตัวอย่างกล้องพื้นฐานที่สามารถ
รวมอยู่ในเลย์เอาต์ View
คลาสนี้ใช้ SurfaceHolder.Callback
เพื่อบันทึกเหตุการณ์ Callback
สำหรับการสร้างและทำลายมุมมอง ซึ่งจำเป็นสำหรับการกำหนดอินพุตตัวอย่างของกล้อง
Kotlin
/** A basic Camera preview class */ class CameraPreview( context: Context, private val mCamera: Camera ) : SurfaceView(context), SurfaceHolder.Callback { private val mHolder: SurfaceHolder = holder.apply { // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. addCallback(this@CameraPreview) // deprecated setting, but required on Android versions prior to 3.0 setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS) } override fun surfaceCreated(holder: SurfaceHolder) { // The Surface has been created, now tell the camera where to draw the preview. mCamera.apply { try { setPreviewDisplay(holder) startPreview() } catch (e: IOException) { Log.d(TAG, "Error setting camera preview: ${e.message}") } } } override fun surfaceDestroyed(holder: SurfaceHolder) { // empty. Take care of releasing the Camera preview in your activity. } override fun surfaceChanged(holder: SurfaceHolder, format: Int, w: Int, h: Int) { // If your preview can change or rotate, take care of those events here. // Make sure to stop the preview before resizing or reformatting it. if (mHolder.surface == null) { // preview surface does not exist return } // stop preview before making changes try { mCamera.stopPreview() } catch (e: Exception) { // ignore: tried to stop a non-existent preview } // set preview size and make any resize, rotate or // reformatting changes here // start preview with new settings mCamera.apply { try { setPreviewDisplay(mHolder) startPreview() } catch (e: Exception) { Log.d(TAG, "Error starting camera preview: ${e.message}") } } } }
Java
/** A basic Camera preview class */ public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder mHolder; private Camera mCamera; public CameraPreview(Context context, Camera camera) { super(context); mCamera = camera; // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. mHolder = getHolder(); mHolder.addCallback(this); // deprecated setting, but required on Android versions prior to 3.0 mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } public void surfaceCreated(SurfaceHolder holder) { // The Surface has been created, now tell the camera where to draw the preview. try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); } catch (IOException e) { Log.d(TAG, "Error setting camera preview: " + e.getMessage()); } } public void surfaceDestroyed(SurfaceHolder holder) { // empty. Take care of releasing the Camera preview in your activity. } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // If your preview can change or rotate, take care of those events here. // Make sure to stop the preview before resizing or reformatting it. if (mHolder.getSurface() == null){ // preview surface does not exist return; } // stop preview before making changes try { mCamera.stopPreview(); } catch (Exception e){ // ignore: tried to stop a non-existent preview } // set preview size and make any resize, rotate or // reformatting changes here // start preview with new settings try { mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); } catch (Exception e){ Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } } }
หากต้องการกำหนดขนาดที่เฉพาะเจาะจงสำหรับการแสดงตัวอย่างจากกล้อง ให้ตั้งค่าในเมธอด surfaceChanged()
ตามที่ระบุไว้ในความคิดเห็นด้านบน เมื่อตั้งค่าขนาดตัวอย่าง คุณจะ
ต้องใช้ค่าจาก getSupportedPreviewSizes()
อย่ากำหนดค่าที่กำหนดเองในเมธอด setPreviewSize()
หมายเหตุ
ด้วยการเปิดตัว
ฟีเจอร์หลายหน้าต่างใน Android 7.0 (API ระดับ 24) ขึ้นไป คุณไม่สามารถ
ลองเดาให้นานขึ้นว่าสัดส่วนภาพของตัวอย่างเท่ากับกิจกรรมของคุณ
แม้ว่าจะโทรหา setDisplayOrientation()
แล้ว
คุณอาจต้องปรับให้พอดีกับขนาดหน้าต่างและสัดส่วนภาพ
แสดงตัวอย่างจากกล้องเป็นเค้าโครงแนวตั้ง หรือกลับกันโดยใช้
แบบแถบดำด้านบน-ล่างของภาพ
การวางตัวอย่างในเลย์เอาต์
คลาสการแสดงตัวอย่างจากกล้องถ่ายรูป เช่น ตัวอย่างที่แสดงในส่วนก่อนหน้านี้ จะต้องอยู่ใน เลย์เอาต์ของกิจกรรมร่วมกับส่วนควบคุมอินเทอร์เฟซผู้ใช้อื่นๆ สำหรับการถ่ายภาพหรือวิดีโอ ช่วงเวลานี้ แสดงวิธีสร้างเลย์เอาต์และกิจกรรมพื้นฐานสำหรับการแสดงตัวอย่าง
รหัสเลย์เอาต์ต่อไปนี้ให้มุมมองพื้นฐานที่สามารถใช้เพื่อแสดงกล้อง
เวอร์ชันตัวอย่าง ในตัวอย่างนี้ องค์ประกอบ FrameLayout
ควรเป็น
สำหรับคลาสการแสดงตัวอย่างของกล้อง เลย์เอาต์ประเภทนี้จะใช้เพื่อให้ดูภาพเพิ่มเติม
ข้อมูลหรือการควบคุมต่างๆ สามารถวางซ้อนบนภาพตัวอย่างจากกล้องแบบสดได้
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" > <FrameLayout android:id="@+id/camera_preview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" /> <Button android:id="@+id/button_capture" android:text="Capture" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" /> </LinearLayout>
ในอุปกรณ์ส่วนใหญ่ การวางแนวเริ่มต้นของการแสดงตัวอย่างจากกล้องจะเป็นแนวนอน เลย์เอาต์ตัวอย่างนี้ ระบุการจัดวางในแนวนอน (แนวนอน) และโค้ดด้านล่างจะช่วยแก้ไขการวางแนวของ กับแนวนอน เพื่อให้แสดงภาพตัวอย่างจากกล้องได้ง่าย คุณควรเปลี่ยน วางแนวกิจกรรมหน้าตัวอย่างของแอปพลิเคชันให้อยู่ในแนวนอนโดยเพิ่มรายละเอียดต่อไปนี้ลงใน ไฟล์ Manifest
<activity android:name=".CameraActivity" android:label="@string/app_name" android:screenOrientation="landscape"> <!-- configure this activity to use landscape orientation --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
หมายเหตุ: การแสดงตัวอย่างจากกล้องไม่จำเป็นต้องอยู่ในโหมดแนวนอน
เริ่มตั้งแต่ Android 2.2 (API ระดับ 8) เป็นต้นไป คุณสามารถใช้เมธอด setDisplayOrientation()
เพื่อตั้งค่า
การหมุนภาพตัวอย่าง ในการเปลี่ยนการวางแนวของหน้าตัวอย่างเมื่อผู้ใช้ปรับทิศทาง
โทรศัพท์ ในเมธอด surfaceChanged()
ของคลาสตัวอย่างของคุณ ให้หยุดการแสดงตัวอย่างโดยให้ Camera.stopPreview()
เปลี่ยนการวางแนวก่อน จากนั้น
เริ่มแสดงตัวอย่างอีกครั้งด้วย Camera.startPreview()
ในกิจกรรมสำหรับมุมมองกล้อง ให้เพิ่มคลาสตัวอย่างลงในองค์ประกอบ FrameLayout
ที่แสดงในตัวอย่างด้านบน กิจกรรมของกล้องต้อง
ตรวจสอบให้แน่ใจว่าปล่อยกล้องเมื่อหยุดชั่วคราวหรือปิด ตัวอย่างต่อไปนี้จะแสดงวิธีการ
เพื่อแก้ไขกิจกรรมของกล้อง เพื่อแนบคลาสการแสดงตัวอย่างที่แสดงในการสร้าง
คลาสตัวอย่าง
Kotlin
class CameraActivity : Activity() { private var mCamera: Camera? = null private var mPreview: CameraPreview? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Create an instance of Camera mCamera = getCameraInstance() mPreview = mCamera?.let { // Create our Preview view CameraPreview(this, it) } // Set the Preview view as the content of our activity. mPreview?.also { val preview: FrameLayout = findViewById(R.id.camera_preview) preview.addView(it) } } }
Java
public class CameraActivity extends Activity { private Camera mCamera; private CameraPreview mPreview; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Create an instance of Camera mCamera = getCameraInstance(); // Create our Preview view and set it as the content of our activity. mPreview = new CameraPreview(this, mCamera); FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); preview.addView(mPreview); } }
หมายเหตุ: เมธอด getCameraInstance()
ในตัวอย่างด้านบน
อ้างถึงวิธีการตัวอย่างที่แสดงในการเข้าถึงกล้อง
กำลังจับภาพ
เมื่อคุณสร้างคลาสตัวอย่างและเลย์เอาต์มุมมองที่จะแสดงแล้ว คุณก็พร้อมที่จะ เริ่มจับภาพด้วยแอปพลิเคชันของคุณ ในโค้ดของแอปพลิเคชัน คุณต้องตั้งค่า Listener เพื่อตอบสนองต่อการดำเนินการของผู้ใช้ด้วยการถ่ายภาพ
หากต้องการดึงภาพ ให้ใช้เมธอด Camera.takePicture()
วิธีนี้ใช้พารามิเตอร์ 3 รายการซึ่งรับข้อมูลจากกล้อง
เพื่อรับข้อมูลในรูปแบบ JPEG คุณต้องใช้อินเทอร์เฟซ Camera.PictureCallback
เพื่อรับข้อมูลภาพและ
เขียนลงในไฟล์ โค้ดต่อไปนี้แสดงการใช้งานอินเทอร์เฟซ Camera.PictureCallback
ขั้นพื้นฐานเพื่อบันทึกรูปภาพที่ได้รับจากกล้อง
Kotlin
private val mPicture = Camera.PictureCallback { data, _ -> val pictureFile: File = getOutputMediaFile(MEDIA_TYPE_IMAGE) ?: run { Log.d(TAG, ("Error creating media file, check storage permissions")) return@PictureCallback } try { val fos = FileOutputStream(pictureFile) fos.write(data) fos.close() } catch (e: FileNotFoundException) { Log.d(TAG, "File not found: ${e.message}") } catch (e: IOException) { Log.d(TAG, "Error accessing file: ${e.message}") } }
Java
private PictureCallback mPicture = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE); if (pictureFile == null){ Log.d(TAG, "Error creating media file, check storage permissions"); return; } try { FileOutputStream fos = new FileOutputStream(pictureFile); fos.write(data); fos.close(); } catch (FileNotFoundException e) { Log.d(TAG, "File not found: " + e.getMessage()); } catch (IOException e) { Log.d(TAG, "Error accessing file: " + e.getMessage()); } } };
ทริกเกอร์การจับภาพโดยเรียกใช้เมธอด Camera.takePicture()
โค้ดตัวอย่างต่อไปนี้แสดงวิธีเรียกใช้เมธอดนี้จาก
ปุ่ม View.OnClickListener
Kotlin
val captureButton: Button = findViewById(R.id.button_capture) captureButton.setOnClickListener { // get an image from the camera mCamera?.takePicture(null, null, picture) }
Java
// Add a listener to the Capture button Button captureButton = (Button) findViewById(R.id.button_capture); captureButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { // get an image from the camera mCamera.takePicture(null, null, picture); } } );
หมายเหตุ: สมาชิก mPicture
ในตัวอย่างต่อไปนี้อ้างถึง
กับโค้ดตัวอย่างด้านบน
ข้อควรระวัง: อย่าลืมเผยแพร่ Camera
โดยเรียก Camera.release()
เมื่อ
เสร็จสิ้นการใช้งานด้วยซ้ำ! โปรดดูข้อมูลเกี่ยวกับวิธีปล่อยกล้องที่หัวข้อการปล่อยกล้อง
การจับภาพวิดีโอ
การจับภาพวิดีโอโดยใช้เฟรมเวิร์ก Android ต้องมีการจัดการออบเจ็กต์ Camera
อย่างรอบคอบและประสานงานกับ MediaRecorder
เมื่อบันทึกวิดีโอด้วย Camera
คุณต้องจัดการการเรียก Camera.lock()
และ Camera.unlock()
เพื่ออนุญาตให้ MediaRecorder
เข้าถึงฮาร์ดแวร์กล้อง
นอกเหนือจากการโทร Camera.open()
และ Camera.release()
หมายเหตุ: ตั้งแต่ Android 4.0 (API ระดับ 14) เป็นต้นไป ระบบจะจัดการการเรียก Camera.lock()
และ Camera.unlock()
ให้คุณโดยอัตโนมัติ
การถ่ายวิดีโอต้องใช้การโทรที่พิเศษมากๆ ต่างจากการถ่ายภาพด้วยกล้องของอุปกรณ์ คำสั่งซื้อ คุณต้องทำตามลำดับการดำเนินการที่เฉพาะเจาะจงเพื่อเตรียมพร้อมและบันทึกวิดีโอ กับใบสมัครของคุณ ตามรายละเอียดด้านล่าง
- เปิดกล้อง - ใช้
Camera.open()
เพื่อรับอินสแตนซ์ของออบเจ็กต์กล้อง - ตัวอย่างการเชื่อมต่อ - เตรียมตัวอย่างรูปภาพแบบสดจากกล้องโดยเชื่อมต่อ
SurfaceView
กับกล้องโดยใช้Camera.setPreviewDisplay()
- เริ่มการแสดงตัวอย่าง - โทรหา
Camera.startPreview()
เพื่อเริ่มแสดงภาพสดจากกล้อง - เริ่มบันทึกวิดีโอ - โปรดทำตามขั้นตอนต่อไปนี้ใน
order เพื่อให้บันทึกวิดีโอได้สำเร็จ:
- ปลดล็อกกล้อง - ปลดล็อกกล้องเพื่อใช้กับ
MediaRecorder
โดยโทรไปที่Camera.unlock()
- กำหนดค่า MediaRecorder - เรียกใช้เมธอด
MediaRecorder
ต่อไปนี้ในลำดับนี้ สำหรับข้อมูลเพิ่มเติม โปรดดูเอกสารอ้างอิงMediaRecorder
setCamera()
- ตั้งค่ากล้องที่จะใช้ในการบันทึกวิดีโอ ใช้อินสแตนซ์ปัจจุบันของแอปพลิเคชัน ของCamera
setAudioSource()
- ตั้งค่า แหล่งที่มาของเสียง ให้ใช้MediaRecorder.AudioSource.CAMCORDER
setVideoSource()
- ตั้งค่าแล้ว แหล่งที่มาของวิดีโอ ให้ใช้MediaRecorder.VideoSource.CAMERA
- ตั้งค่ารูปแบบและการเข้ารหัสเอาต์พุตวิดีโอ สำหรับ Android 2.2 (API ระดับ 8) และ
ให้สูงกว่า วิธี
MediaRecorder.setProfile
และรับอินสแตนซ์โปรไฟล์โดยใช้CamcorderProfile.get()
สำหรับ Android เวอร์ชันก่อน 2.2 คุณต้องตั้งค่ารูปแบบเอาต์พุตวิดีโอและพารามิเตอร์การเข้ารหัส ดังนี้setOutputFormat()
- ตั้งค่าแล้ว รูปแบบเอาต์พุต ให้ระบุการตั้งค่าเริ่มต้นหรือMediaRecorder.OutputFormat.MPEG_4
setAudioEncoder()
- ตั้งค่าแล้ว ประเภทการเข้ารหัสเสียง ให้ระบุการตั้งค่าเริ่มต้นหรือMediaRecorder.AudioEncoder.AMR_NB
setVideoEncoder()
- ตั้งค่าแล้ว ประเภทการเข้ารหัสวิดีโอ ให้กำหนดการตั้งค่าเริ่มต้นหรือMediaRecorder.VideoEncoder.MPEG_4_SP
setOutputFile()
- ตั้งค่าไฟล์เอาต์พุต ใช้getOutputMediaFile(MEDIA_TYPE_VIDEO).toString()
จากตัวอย่าง ในส่วนการบันทึกไฟล์สื่อsetPreviewDisplay()
- ระบุองค์ประกอบเค้าโครงตัวอย่างSurfaceView
สำหรับ แอปพลิเคชันของคุณ ใช้ออบเจ็กต์เดียวกันกับที่คุณระบุสำหรับ Connect Preview
ข้อควรระวัง: คุณต้องเรียกใช้วิธีการกำหนดค่า
MediaRecorder
เหล่านี้ตามลำดับนี้ มิฉะนั้น แอปพลิเคชันจะเกิดข้อผิดพลาดและการบันทึกจะล้มเหลว - เตรียม MediaRecorder - เตรียม
MediaRecorder
พร้อมการตั้งค่าที่กำหนดไว้โดยโทรหาMediaRecorder.prepare()
- เริ่ม MediaRecorder - เริ่มบันทึกวิดีโอโดยโทรหา
MediaRecorder.start()
- ปลดล็อกกล้อง - ปลดล็อกกล้องเพื่อใช้กับ
- หยุดบันทึกวิดีโอ - เรียกเมธอดต่อไปนี้ตามลำดับ เพื่อ
บันทึกวิดีโอเสร็จสมบูรณ์:
- หยุด MediaRecorder - หยุดบันทึกวิดีโอโดยโทรหา
MediaRecorder.stop()
- รีเซ็ต MediaRecorder - (ไม่บังคับ) นำการตั้งค่าการกำหนดค่าออกจาก
โดยโทรหา
MediaRecorder.reset()
- Release MediaRecorder - เผยแพร่
MediaRecorder
โดยโทรไปที่MediaRecorder.release()
- ล็อกกล้อง - ล็อกกล้องเพื่อให้เซสชันของ
MediaRecorder
ในอนาคตใช้งานได้โดยโทรหาCamera.lock()
สำหรับ Android 4.0 (API ระดับ 14) เป็นต้นไป ไม่จำเป็นต้องใช้การเรียกนี้เว้นแต่ โทรMediaRecorder.prepare()
ไม่สำเร็จ
- หยุด MediaRecorder - หยุดบันทึกวิดีโอโดยโทรหา
- หยุดการแสดงตัวอย่าง - เมื่อใช้กล้องเสร็จแล้ว ให้หยุด
ดูตัวอย่างโดยใช้
Camera.stopPreview()
- ปล่อยกล้อง - ปล่อยกล้องเพื่อให้แอปพลิเคชันอื่นใช้งานได้
โดยโทรไปที่
Camera.release()
หมายเหตุ: คุณสามารถใช้ MediaRecorder
โดยไม่ต้องสร้างการแสดงตัวอย่างจากกล้องก่อน และข้ามขั้นตอนแรกๆ ของกระบวนการนี้ อย่างไรก็ตาม
เนื่องจากผู้ใช้มักจะต้องการดูตัวอย่างก่อนจะเริ่มบันทึก
ที่กล่าวถึงในที่นี้
เคล็ดลับ: หากโดยปกติแล้วแอปพลิเคชันของคุณใช้สำหรับบันทึกวิดีโอ ให้ตั้งค่า
setRecordingHint(boolean)
ถึง true
ก่อนเริ่มต้น
เวอร์ชันตัวอย่าง การตั้งค่าดังกล่าวจะช่วยลดเวลาที่ใช้ในการเริ่มบันทึกได้
การกำหนดค่า MediaRecorder
เมื่อใช้ชั้นเรียน MediaRecorder
เพื่อบันทึกวิดีโอ คุณต้องดำเนินการต่อไปนี้
ขั้นตอนการกำหนดค่าในลำดับเฉพาะ จากนั้นเรียกเมธอด MediaRecorder.prepare()
เพื่อตรวจสอบและใช้งาน
การกำหนดค่า โค้ดตัวอย่างต่อไปนี้แสดงวิธีกำหนดค่าและเตรียมฟังก์ชัน
MediaRecorder
ชั้นเรียนสำหรับการบันทึกวิดีโอ
Kotlin
private fun prepareVideoRecorder(): Boolean { mediaRecorder = MediaRecorder() mCamera?.let { camera -> // Step 1: Unlock and set camera to MediaRecorder camera?.unlock() mediaRecorder?.run { setCamera(camera) // Step 2: Set sources setAudioSource(MediaRecorder.AudioSource.CAMCORDER) setVideoSource(MediaRecorder.VideoSource.CAMERA) // Step 3: Set a CamcorderProfile (requires API Level 8 or higher) setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)) // Step 4: Set output file setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString()) // Step 5: Set the preview output setPreviewDisplay(mPreview?.holder?.surface) setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT) setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT) // Step 6: Prepare configured MediaRecorder return try { prepare() true } catch (e: IllegalStateException) { Log.d(TAG, "IllegalStateException preparing MediaRecorder: ${e.message}") releaseMediaRecorder() false } catch (e: IOException) { Log.d(TAG, "IOException preparing MediaRecorder: ${e.message}") releaseMediaRecorder() false } } } return false }
Java
private boolean prepareVideoRecorder(){ mCamera = getCameraInstance(); mediaRecorder = new MediaRecorder(); // Step 1: Unlock and set camera to MediaRecorder mCamera.unlock(); mediaRecorder.setCamera(mCamera); // Step 2: Set sources mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // Step 3: Set a CamcorderProfile (requires API Level 8 or higher) mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)); // Step 4: Set output file mediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString()); // Step 5: Set the preview output mediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface()); // Step 6: Prepare configured MediaRecorder try { mediaRecorder.prepare(); } catch (IllegalStateException e) { Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage()); releaseMediaRecorder(); return false; } catch (IOException e) { Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage()); releaseMediaRecorder(); return false; } return true; }
ก่อนที่จะมี Android 2.2 (API ระดับ 8) คุณต้องตั้งค่ารูปแบบเอาต์พุตและรูปแบบการเข้ารหัส
พารามิเตอร์ได้โดยตรง แทนที่จะใช้ CamcorderProfile
วิธีนี้
แสดงในโค้ดต่อไปนี้
Kotlin
// Step 3: Set output format and encoding (for versions prior to API Level 8) mediaRecorder?.apply { setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT) setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT) }
Java
// Step 3: Set output format and encoding (for versions prior to API Level 8) mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
ระบุพารามิเตอร์การบันทึกวิดีโอต่อไปนี้สำหรับ MediaRecorder
การตั้งค่าเริ่มต้น อย่างไรก็ตาม คุณอาจต้องการปรับการตั้งค่าเหล่านี้สำหรับแอปพลิเคชันของคุณ ดังนี้:
setVideoEncodingBitRate()
setVideoSize()
setVideoFrameRate()
setAudioEncodingBitRate()
setAudioChannels()
setAudioSamplingRate()
การเริ่มและการหยุด MediaRecorder
เมื่อเริ่มและหยุดการบันทึกวิดีโอโดยใช้ชั้นเรียน MediaRecorder
คุณต้องทำตามคำสั่งซื้อที่เฉพาะเจาะจง ตามที่ระบุไว้ด้านล่าง
- ปลดล็อกกล้องด้วย
Camera.unlock()
- กำหนดค่า
MediaRecorder
ดังที่แสดงในตัวอย่างโค้ดด้านบน - เริ่มบันทึกโดยใช้
MediaRecorder.start()
- บันทึกวิดีโอ
- หยุดบันทึกโดยใช้
MediaRecorder.stop()
- เปิดตัวเครื่องบันทึกสื่อด้วย
MediaRecorder.release()
- ล็อกกล้องโดยใช้
Camera.lock()
โค้ดตัวอย่างต่อไปนี้แสดงวิธีเดินสายปุ่มเพื่อเริ่มและหยุดอย่างถูกต้อง
การบันทึกวิดีโอโดยใช้กล้องและชั้นเรียน MediaRecorder
หมายเหตุ: เมื่อบันทึกวิดีโอเสร็จแล้ว อย่าปล่อยกล้อง ไม่เช่นนั้นการแสดงตัวอย่างจะหยุด
Kotlin
var isRecording = false val captureButton: Button = findViewById(R.id.button_capture) captureButton.setOnClickListener { if (isRecording) { // stop recording and release camera mediaRecorder?.stop() // stop the recording releaseMediaRecorder() // release the MediaRecorder object mCamera?.lock() // take camera access back from MediaRecorder // inform the user that recording has stopped setCaptureButtonText("Capture") isRecording = false } else { // initialize video camera if (prepareVideoRecorder()) { // Camera is available and unlocked, MediaRecorder is prepared, // now you can start recording mediaRecorder?.start() // inform the user that recording has started setCaptureButtonText("Stop") isRecording = true } else { // prepare didn't work, release the camera releaseMediaRecorder() // inform user } } }
Java
private boolean isRecording = false; // Add a listener to the Capture button Button captureButton = (Button) findViewById(id.button_capture); captureButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { if (isRecording) { // stop recording and release camera mediaRecorder.stop(); // stop the recording releaseMediaRecorder(); // release the MediaRecorder object mCamera.lock(); // take camera access back from MediaRecorder // inform the user that recording has stopped setCaptureButtonText("Capture"); isRecording = false; } else { // initialize video camera if (prepareVideoRecorder()) { // Camera is available and unlocked, MediaRecorder is prepared, // now you can start recording mediaRecorder.start(); // inform the user that recording has started setCaptureButtonText("Stop"); isRecording = true; } else { // prepare didn't work, release the camera releaseMediaRecorder(); // inform user } } } } );
หมายเหตุ: ในตัวอย่างด้านบน prepareVideoRecorder()
เมธอดจะอ้างอิงโค้ดตัวอย่างที่แสดงในการกำหนดค่า MediaRecorder วิธีนี้จะช่วยดูแลการล็อก
กล้อง กำลังกำหนดค่าและเตรียมอินสแตนซ์ MediaRecorder
กำลังปล่อยกล้อง
กล้องเป็นทรัพยากรที่แอปพลิเคชันต่างๆ ในอุปกรณ์ใช้ร่วมกัน แอปพลิเคชันของคุณสามารถ
ที่ใช้กล้องหลังจากได้รับอินสแตนซ์ Camera
และคุณต้อง
ระมัดระวังเป็นพิเศษในการปล่อยวัตถุกล้องถ่ายรูปเมื่อแอปพลิเคชันของคุณหยุดใช้งาน และ
ทันทีที่แอปพลิเคชันหยุดชั่วคราว (Activity.onPause()
) ถ้า
แอปพลิเคชันของคุณปล่อยกล้องไม่ถูกต้อง ความพยายามเข้าถึงกล้องในครั้งต่อๆ ไปทั้งหมด
ซึ่งรวมถึงซอฟต์แวร์จากแอปพลิเคชันของคุณเอง จะล้มเหลวและอาจทำให้แอปพลิเคชันของคุณหรือแอปพลิเคชันอื่น
ปิด
หากต้องการปล่อยอินสแตนซ์ของออบเจ็กต์ Camera
ให้ใช้เมธอด Camera.release()
ดังที่แสดงในโค้ดตัวอย่างด้านล่าง
Kotlin
class CameraActivity : Activity() { private var mCamera: Camera? private var preview: SurfaceView? private var mediaRecorder: MediaRecorder? override fun onPause() { super.onPause() releaseMediaRecorder() // if you are using MediaRecorder, release it first releaseCamera() // release the camera immediately on pause event } private fun releaseMediaRecorder() { mediaRecorder?.reset() // clear recorder configuration mediaRecorder?.release() // release the recorder object mediaRecorder = null mCamera?.lock() // lock camera for later use } private fun releaseCamera() { mCamera?.release() // release the camera for other applications mCamera = null } }
Java
public class CameraActivity extends Activity { private Camera mCamera; private SurfaceView preview; private MediaRecorder mediaRecorder; ... @Override protected void onPause() { super.onPause(); releaseMediaRecorder(); // if you are using MediaRecorder, release it first releaseCamera(); // release the camera immediately on pause event } private void releaseMediaRecorder(){ if (mediaRecorder != null) { mediaRecorder.reset(); // clear recorder configuration mediaRecorder.release(); // release the recorder object mediaRecorder = null; mCamera.lock(); // lock camera for later use } } private void releaseCamera(){ if (mCamera != null){ mCamera.release(); // release the camera for other applications mCamera = null; } } }
ข้อควรระวัง: หากแอปพลิเคชันไม่ได้เผยแพร่ การเข้าถึงกล้องในภายหลังทั้งหมด รวมถึงการพยายามเข้าถึงกล้องด้วยแอปพลิเคชันของคุณเองจะ ล้มเหลวและอาจทำให้แอปพลิเคชันของคุณหรือแอปพลิเคชันอื่นๆ ปิดลง
กำลังบันทึกไฟล์สื่อ
ไฟล์สื่อที่ผู้ใช้สร้าง เช่น รูปภาพและวิดีโอ ควรบันทึกไปยังโค้ดภายนอกของอุปกรณ์ ไดเรกทอรีพื้นที่เก็บข้อมูล (SD Card) เพื่อประหยัดพื้นที่ของระบบและเพื่อให้ผู้ใช้เข้าถึงไฟล์เหล่านี้ได้ โดยไม่มีอุปกรณ์ การบันทึกไฟล์สื่อในอุปกรณ์สามารถทำได้หลายวิธี อย่างไรก็ตาม มีเพียง 2 ตำแหน่งมาตรฐานที่คุณควรถือว่าเป็นนักพัฒนาซอฟต์แวร์ ได้แก่
Environment.getExternalStoragePublicDirectory
(Environment.DIRECTORY_PICTURES
) - วิธีนี้แสดงแบบมาตรฐาน แชร์ และที่แนะนำ ตำแหน่งสำหรับบันทึกภาพและวิดีโอ ไดเรกทอรีนี้เป็นการใช้ร่วมกัน (สาธารณะ) ดังนั้นแอปพลิเคชันอื่นๆ สามารถค้นพบ อ่าน เปลี่ยนแปลง และลบไฟล์ที่บันทึกไว้ในตำแหน่งนี้ได้อย่างง่ายดาย หากแอปพลิเคชันของคุณคือ ผู้ใช้ถอนการติดตั้งแล้ว ไฟล์สื่อที่บันทึกไว้ในตำแหน่งนี้จะไม่ถูกลบ วิธีหลีกเลี่ยง เมื่อรบกวนรูปภาพและวิดีโอที่มีอยู่ของผู้ใช้ คุณควรสร้างไดเรกทอรีย่อยสำหรับ ไฟล์สื่อของแอปพลิเคชันภายในไดเรกทอรีนี้ ดังที่แสดงในตัวอย่างโค้ดด้านล่าง วิธีนี้เป็น พร้อมใช้งานใน Android 2.2 (API ระดับ 8) สำหรับการเรียก API เวอร์ชันก่อนหน้า โปรดดูที่การบันทึกไฟล์ที่แชร์Context.getExternalFilesDir
(Environment.DIRECTORY_PICTURES
) - เมธอดนี้จะแสดงตำแหน่งมาตรฐานสำหรับการบันทึก รูปภาพและวิดีโอที่เกี่ยวข้องกับแอปพลิเคชันของคุณ หากถอนการติดตั้งแอปพลิเคชันแล้ว ไฟล์ที่บันทึกไว้ในตำแหน่งนี้จะถูกลบออก ไม่ได้บังคับใช้การรักษาความปลอดภัยสำหรับไฟล์ใน ตำแหน่งและแอปพลิเคชันอื่นๆ อาจอ่าน เปลี่ยนแปลง และลบรายการเหล่านั้น
โค้ดตัวอย่างต่อไปนี้แสดงวิธีการสร้างตำแหน่ง File
หรือ Uri
สำหรับไฟล์สื่อที่สามารถใช้เมื่อเรียกใช้กล้องของอุปกรณ์ด้วย
Intent
หรือส่วนหนึ่งของการสร้างกล้อง
แอป
Kotlin
val MEDIA_TYPE_IMAGE = 1 val MEDIA_TYPE_VIDEO = 2 /** Create a file Uri for saving an image or video */ private fun getOutputMediaFileUri(type: Int): Uri { return Uri.fromFile(getOutputMediaFile(type)) } /** Create a File for saving an image or video */ private fun getOutputMediaFile(type: Int): File? { // To be safe, you should check that the SDCard is mounted // using Environment.getExternalStorageState() before doing this. val mediaStorageDir = File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyCameraApp" ) // This location works best if you want the created images to be shared // between applications and persist after your app has been uninstalled. // Create the storage directory if it does not exist mediaStorageDir.apply { if (!exists()) { if (!mkdirs()) { Log.d("MyCameraApp", "failed to create directory") return null } } } // Create a media file name val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date()) return when (type) { MEDIA_TYPE_IMAGE -> { File("${mediaStorageDir.path}${File.separator}IMG_$timeStamp.jpg") } MEDIA_TYPE_VIDEO -> { File("${mediaStorageDir.path}${File.separator}VID_$timeStamp.mp4") } else -> null } }
Java
public static final int MEDIA_TYPE_IMAGE = 1; public static final int MEDIA_TYPE_VIDEO = 2; /** Create a file Uri for saving an image or video */ private static Uri getOutputMediaFileUri(int type){ return Uri.fromFile(getOutputMediaFile(type)); } /** Create a File for saving an image or video */ private static File getOutputMediaFile(int type){ // To be safe, you should check that the SDCard is mounted // using Environment.getExternalStorageState() before doing this. File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES), "MyCameraApp"); // This location works best if you want the created images to be shared // between applications and persist after your app has been uninstalled. // Create the storage directory if it does not exist if (! mediaStorageDir.exists()){ if (! mediaStorageDir.mkdirs()){ Log.d("MyCameraApp", "failed to create directory"); return null; } } // Create a media file name String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); File mediaFile; if (type == MEDIA_TYPE_IMAGE){ mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_"+ timeStamp + ".jpg"); } else if(type == MEDIA_TYPE_VIDEO) { mediaFile = new File(mediaStorageDir.getPath() + File.separator + "VID_"+ timeStamp + ".mp4"); } else { return null; } return mediaFile; }
หมายเหตุ: Environment.getExternalStoragePublicDirectory()
พร้อมใช้งานใน Android 2.2 (API ระดับ 8) หรือ
สูงขึ้น หากกำลังกำหนดเป้าหมายอุปกรณ์ที่มี Android เวอร์ชันก่อนหน้า ให้ใช้ Environment.getExternalStorageDirectory()
แทน โปรดดูข้อมูลเพิ่มเติมที่การบันทึกไฟล์ที่แชร์
หากต้องการให้ URI รองรับโปรไฟล์งาน ก่อนอื่นให้
แปลง URI ของไฟล์เป็น URI ของเนื้อหา จากนั้นเพิ่ม URI เนื้อหาไปยัง
EXTRA_OUTPUT
ของ Intent
โปรดดูข้อมูลเพิ่มเติมเกี่ยวกับการบันทึกไฟล์ในอุปกรณ์ Android ที่พื้นที่เก็บข้อมูล
ฟีเจอร์ของกล้อง
Android สนับสนุนคุณลักษณะของกล้องที่หลากหลายที่คุณสามารถควบคุมได้ด้วยแอปพลิเคชันกล้อง
เช่น รูปแบบภาพ โหมดแฟลช การตั้งค่าโฟกัส และอื่นๆ อีกมากมาย ส่วนนี้แสดงรายการ
ของคุณลักษณะกล้อง และพูดคุยสั้นๆ ถึงวิธีการใช้ ฟีเจอร์กล้องส่วนใหญ่เข้าถึงและตั้งค่าได้
โดยใช้ออบเจ็กต์ผ่าน Camera.Parameters
อย่างไรก็ตาม ก็มี
ฟีเจอร์สำคัญที่ต้องการมากกว่าการตั้งค่าง่ายๆ ใน Camera.Parameters
ฟีเจอร์เหล่านี้จะกล่าวถึงในส่วนต่อไปนี้
สำหรับข้อมูลทั่วไปเกี่ยวกับวิธีใช้ฟีเจอร์ที่ควบคุมผ่าน Camera.Parameters
โปรดอ่านการใช้กล้อง
ฟีเจอร์ สําหรับข้อมูลโดยละเอียดเพิ่มเติมเกี่ยวกับวิธีใช้ฟีเจอร์ที่ควบคุมผ่าน
ออบเจ็กต์พารามิเตอร์กล้อง โปรดไปตามลิงก์ในรายการฟีเจอร์ด้านล่างไปยังข้อมูลอ้างอิง API
เอกสารประกอบ
ตาราง 1 ฟีเจอร์ทั่วไปของกล้องที่จัดเรียงตามระดับ API ของ Android ที่ ได้แนะนำ
ฟีเจอร์ | ระดับ API | คำอธิบาย |
---|---|---|
การตรวจจับใบหน้า | 14 | ระบุใบหน้าของมนุษย์ในภาพแล้วใช้ประกอบเพื่อโฟกัส วัดแสง และสีขาว ยอดคงเหลือ |
พื้นที่การวัด | 14 | ระบุพื้นที่อย่างน้อย 1 พื้นที่ภายในรูปภาพเพื่อคำนวณไวท์บาลานซ์ |
ด้านที่มุ่งเน้น | 14 | ตั้งค่าพื้นที่อย่างน้อย 1 ส่วนภายในรูปภาพเพื่อใช้สำหรับโฟกัส |
White Balance Lock |
14 | หยุดหรือเริ่มการปรับไวท์บาลานซ์อัตโนมัติ |
Exposure Lock |
14 | หยุดหรือเริ่มการปรับการรับแสงอัตโนมัติ |
Video Snapshot |
14 | ถ่ายรูปขณะถ่ายวิดีโอ (จับเฟรม) |
วิดีโอไทม์แลปส์ | 11 | บันทึกเฟรมที่มีการหน่วงเวลาที่ตั้งไว้เพื่อบันทึกวิดีโอไทม์แลปส์ |
Multiple Cameras |
9 | รองรับกล้องมากกว่า 1 ตัวในอุปกรณ์ 1 ตัว ซึ่งรวมถึงกล้องหน้าและกล้องหลัง กล้อง |
Focus Distance |
9 | รายงานระยะห่างระหว่างกล้องกับวัตถุที่ดูเหมือนจะอยู่ในโฟกัส |
Zoom |
8 | ตั้งค่าการขยายรูปภาพ |
Exposure
Compensation |
8 | เพิ่มหรือลดระดับการรับแสง |
GPS Data |
5 | ใส่หรือไม่รวมข้อมูลสถานที่ตั้งทางภูมิศาสตร์ไว้ในรูปภาพ |
White Balance |
5 | ตั้งค่าโหมดไวท์บาลานซ์ซึ่งจะส่งผลต่อค่าสีในรูปภาพที่จับภาพไว้ |
Focus Mode |
5 | กำหนดวิธีที่กล้องโฟกัสวัตถุ เช่น อัตโนมัติ คงที่ มาโคร หรืออนันต์ |
Scene Mode |
5 | ใช้โหมดที่กำหนดล่วงหน้าสำหรับสถานการณ์การถ่ายภาพบางประเภท เช่น กลางคืน ชายหาด หิมะ หรือฉากใต้แสงเทียน |
JPEG Quality |
5 | ตั้งค่าระดับการบีบอัดสําหรับรูปภาพ JPEG ซึ่งจะเพิ่มหรือลดไฟล์เอาต์พุตรูปภาพ คุณภาพและขนาด |
Flash Mode |
5 | เปิด ปิด หรือใช้การตั้งค่าอัตโนมัติ |
Color Effects |
5 | ใช้เอฟเฟกต์สีกับภาพที่จับภาพไว้ เช่น ขาวดำ โทนสีซีเปีย หรือภาพเนกาทีฟ |
Anti-Banding |
5 | ลดผลกระทบของแถบสีในการไล่ระดับสีเนื่องจากการบีบอัด JPEG |
Picture Format |
1 | ระบุรูปแบบไฟล์ของรูปภาพ |
Picture Size |
1 | ระบุขนาดพิกเซลของภาพที่บันทึกไว้ |
หมายเหตุ: อุปกรณ์บางเครื่องไม่รองรับฟีเจอร์เหล่านี้เนื่องจาก ความแตกต่างของฮาร์ดแวร์และซอฟต์แวร์ สำหรับข้อมูลเกี่ยวกับการตรวจสอบความพร้อมจำหน่ายสินค้า ของฟีเจอร์ในอุปกรณ์ที่แอปพลิเคชันทำงานอยู่ โปรดดูหัวข้อการตรวจสอบ ความพร้อมใช้งานของฟีเจอร์
กำลังตรวจสอบความพร้อมใช้งานของฟีเจอร์
สิ่งแรกที่ต้องเข้าใจเมื่อตั้งค่าเพื่อใช้ฟีเจอร์กล้องบนอุปกรณ์ Android คือ อุปกรณ์บางรุ่นอาจไม่รองรับฟีเจอร์ของกล้องบางอย่าง นอกจากนี้ อุปกรณ์ที่รองรับ อาจรองรับวิดีโอในระดับอื่นหรือด้วยตัวเลือกอื่น ดังนั้น ส่วนหนึ่งของ ระหว่างการพัฒนาแอปพลิเคชันกล้อง คือการตัดสินใจว่าต้องการใช้ฟีเจอร์ใดของกล้อง และการสนับสนุนในระดับใด หลังจากตัดสินใจแล้ว คุณควรวางแผนที่จะรวมโค้ดไว้ใน แอปพลิเคชันกล้องที่ตรวจสอบว่าฮาร์ดแวร์ของอุปกรณ์รองรับฟีเจอร์เหล่านั้นแต่ทำงานล้มเหลวหรือไม่ ด้วยความยินดีหากฟีเจอร์นั้นไม่พร้อมใช้งาน
คุณสามารถตรวจสอบความพร้อมใช้งานของฟีเจอร์กล้องได้โดยรับอินสแตนซ์ของพารามิเตอร์ของกล้อง
และตรวจสอบเมธอดที่เกี่ยวข้อง ตัวอย่างโค้ดต่อไปนี้แสดงวิธีขอรับ
Camera.Parameters
วัตถุและตรวจสอบว่ากล้องรองรับการโฟกัสอัตโนมัติหรือไม่
ฟีเจอร์:
Kotlin
val params: Camera.Parameters? = camera?.parameters val focusModes: List<String>? = params?.supportedFocusModes if (focusModes?.contains(Camera.Parameters.FOCUS_MODE_AUTO) == true) { // Autofocus mode is supported }
Java
// get Camera parameters Camera.Parameters params = camera.getParameters(); List<String> focusModes = params.getSupportedFocusModes(); if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) { // Autofocus mode is supported }
คุณสามารถใช้เทคนิคที่แสดงด้านบนกับฟีเจอร์ส่วนใหญ่ของกล้องได้
ออบเจ็กต์ Camera.Parameters
มีเมธอด getSupported...()
, is...Supported()
หรือ getMax...()
เพื่อระบุว่าฟีเจอร์นั้น (และขอบเขต) หรือไม่
ที่รองรับ
หากแอปพลิเคชันของคุณต้องใช้คุณลักษณะบางอย่างของกล้องถ่ายรูปเพื่อให้ทำงานได้อย่างถูกต้อง คุณสามารถ ต้องการรายการเหล่านี้ผ่านการเพิ่มไฟล์ Manifest ของแอปพลิเคชัน เมื่อคุณประกาศการใช้ คุณลักษณะของกล้องถ่ายรูป เช่น แฟลชและโฟกัสอัตโนมัติ Google Play จะจำกัดไม่ให้แอปพลิเคชันของคุณทำงาน กำลังติดตั้งบนอุปกรณ์ที่ไม่รองรับฟีเจอร์เหล่านี้ สำหรับรายการฟีเจอร์กล้องที่ สามารถประกาศในไฟล์ Manifest ของแอปได้ โปรดดูไฟล์ Manifest ฟีเจอร์ ข้อมูลอ้างอิง
การใช้ฟีเจอร์ของกล้อง
ฟีเจอร์กล้องส่วนใหญ่จะเปิดใช้งานและควบคุมโดยใช้ออบเจ็กต์ Camera.Parameters
คุณได้รับออบเจ็กต์นี้โดยรับอินสแตนซ์ของ
ออบเจ็กต์ Camera
การเรียกเมธอด getParameters()
การเปลี่ยนพารามิเตอร์ที่แสดงผล
แล้วตั้งค่ากลับเข้าไปในออบเจ็กต์กล้อง ดังที่แสดงในตัวอย่างต่อไปนี้
รหัส:
Kotlin
val params: Camera.Parameters? = camera?.parameters params?.focusMode = Camera.Parameters.FOCUS_MODE_AUTO camera?.parameters = params
Java
// get Camera parameters Camera.Parameters params = camera.getParameters(); // set the focus mode params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); // set Camera parameters camera.setParameters(params);
เทคนิคนี้ใช้ได้กับฟีเจอร์กล้องเกือบทั้งหมด และพารามิเตอร์ส่วนใหญ่สามารถเปลี่ยนแปลงได้
ระยะเวลาหลังจากที่คุณได้รับอินสแตนซ์ของออบเจ็กต์ Camera
การเปลี่ยนแปลงเป็น
โดยทั่วไป ผู้ใช้จะมองเห็นพารามิเตอร์นี้ทันทีในการแสดงตัวอย่างจากกล้องของแอปพลิเคชัน
ในด้านซอฟต์แวร์ การเปลี่ยนแปลงพารามิเตอร์อาจใช้เวลาหลายเฟรมจึงจะมีผลเนื่องจาก
ฮาร์ดแวร์กล้องจะประมวลผลคำสั่งใหม่ แล้วส่งข้อมูลรูปภาพที่อัปเดตแล้ว
สำคัญ: คุณเปลี่ยนแปลงฟีเจอร์บางอย่างของกล้องไม่ได้ในตอนนี้ ใน โดยเฉพาะอย่างยิ่ง การเปลี่ยนขนาดหรือการวางแนวของหน้าตัวอย่างกล้องถ่ายรูปคุณจะต้องหยุด แสดงตัวอย่าง เปลี่ยนขนาดการแสดงตัวอย่าง แล้วเริ่มการแสดงตัวอย่างใหม่ เริ่มต้นด้วย Android 4.0 (API ระดับ 14) การวางแนวของตัวอย่างสามารถเปลี่ยนแปลงได้โดยไม่ต้องเริ่มการแสดงตัวอย่างใหม่
ฟีเจอร์อื่นๆ ของกล้องต้องใช้โค้ดเพิ่มเติมในการใช้งาน ดังนี้
- การวัดและด้านที่มุ่งเน้น
- การตรวจจับใบหน้า
- วิดีโอไทม์แลปส์
ดูสรุปวิธีใช้งานฟีเจอร์เหล่านี้ได้ในส่วนต่อไปนี้
การวัดและด้านที่มุ่งเน้น
ในบางสถานการณ์การถ่ายภาพ การโฟกัสอัตโนมัติและการวัดแสงอาจไม่ก่อให้เกิด ผลลัพธ์ที่ต้องการ ตั้งแต่ Android 4.0 (API ระดับ 14) แอปพลิเคชันกล้องถ่ายรูปสามารถให้ การควบคุมเพิ่มเติมเพื่อให้แอปหรือผู้ใช้ระบุพื้นที่ในรูปภาพเพื่อใช้ระบุได้ การตั้งค่าโฟกัสหรือระดับแสง แล้วส่งค่าเหล่านี้ไปยังฮาร์ดแวร์กล้องเพื่อใช้ในการจับภาพ รูปภาพหรือวิดีโอ
พื้นที่สำหรับการวัดและการโฟกัสทำงานคล้ายกับฟีเจอร์กล้องอื่นๆ อย่างมากตรงที่คุณสามารถควบคุม
ผ่านเมธอดในออบเจ็กต์ Camera.Parameters
รหัสต่อไปนี้
จะแสดงการตั้งค่าพื้นที่การวัดแสง 2 จุดในกรณี
Camera
:
Kotlin
// Create an instance of Camera camera = getCameraInstance() // set Camera parameters val params: Camera.Parameters? = camera?.parameters params?.apply { if (maxNumMeteringAreas > 0) { // check that metering areas are supported meteringAreas = ArrayList<Camera.Area>().apply { val areaRect1 = Rect(-100, -100, 100, 100) // specify an area in center of image add(Camera.Area(areaRect1, 600)) // set weight to 60% val areaRect2 = Rect(800, -1000, 1000, -800) // specify an area in upper right of image add(Camera.Area(areaRect2, 400)) // set weight to 40% } } camera?.parameters = this }
Java
// Create an instance of Camera camera = getCameraInstance(); // set Camera parameters Camera.Parameters params = camera.getParameters(); if (params.getMaxNumMeteringAreas() > 0){ // check that metering areas are supported List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>(); Rect areaRect1 = new Rect(-100, -100, 100, 100); // specify an area in center of image meteringAreas.add(new Camera.Area(areaRect1, 600)); // set weight to 60% Rect areaRect2 = new Rect(800, -1000, 1000, -800); // specify an area in upper right of image meteringAreas.add(new Camera.Area(areaRect2, 400)); // set weight to 40% params.setMeteringAreas(meteringAreas); } camera.setParameters(params);
ออบเจ็กต์ Camera.Area
มีพารามิเตอร์ข้อมูล 2 รายการ ได้แก่ ออบเจ็กต์ Rect
สำหรับระบุพื้นที่ภายในขอบเขตการมองเห็นของกล้องและน้ำหนัก
ซึ่งจะบอกกล้องว่าพื้นที่นี้ควรให้ความสำคัญในระดับใดในการตรวจสอบแสง
หรือโฟกัสที่การคำนวณได้
ช่อง Rect
ในออบเจ็กต์ Camera.Area
อธิบายรูปร่างสี่เหลี่ยมผืนผ้าที่จับคู่กับตารางกริดขนาด 2000 x 2000 หน่วย พิกัด -1000, -1000
แสดงมุมซ้ายบนของภาพกล้อง และพิกัด 1000, 1000 จะแสดงค่า
มุมล่างขวาของภาพกล้องดังที่แสดงในภาพด้านล่าง
รูปที่ 1 เส้นสีแดงแสดงถึงระบบพิกัดที่ใช้ระบุ
Camera.Area
ในการแสดงตัวอย่างจากกล้อง กล่องสีฟ้าจะแสดงตำแหน่งและ
รูปร่างของพื้นที่กล้องที่มีค่า Rect
เป็น 333,333,667,667
ขอบเขตของระบบพิกัดนี้จะสอดคล้องกับขอบด้านนอกของภาพที่มองเห็นใน
แสดงตัวอย่างจากกล้อง และไม่ย่อหรือขยายโดยใช้ระดับการซูม ในทำนองเดียวกัน การหมุนรูปภาพ
แสดงตัวอย่างโดยใช้ Camera.setDisplayOrientation()
จะไม่แมประบบพิกัดใหม่
การตรวจจับใบหน้า
สำหรับรูปภาพที่มีผู้คน ใบหน้ามักจะเป็นส่วนที่สำคัญที่สุดของภาพ และ ควรใช้สำหรับกำหนดทั้งโฟกัสและไวท์บาลานซ์เมื่อจับภาพ Android 4.0 เฟรมเวิร์ก (API ระดับ 14) มี API สำหรับการระบุใบหน้าและคำนวณการตั้งค่าภาพโดยใช้ เทคโนโลยีการจดจำใบหน้า
หมายเหตุ: ขณะที่ฟีเจอร์การตรวจจับใบหน้าทำงานอยู่
setWhiteBalance(String)
,
setFocusAreas(List<Camera.Area>)
และ
setMeteringAreas(List<Camera.Area>)
จะไม่มีผล
การใช้ฟีเจอร์การตรวจจับใบหน้าในแอปพลิเคชันกล้องมีขั้นตอนทั่วไป 2-3 ขั้นตอนต่อไปนี้
- ตรวจสอบว่าอุปกรณ์รองรับการตรวจจับใบหน้า
- สร้าง Listener การตรวจจับใบหน้า
- เพิ่ม Listener การตรวจจับใบหน้าลงในวัตถุของกล้อง
- เริ่มการตรวจจับใบหน้าหลังจากการแสดงตัวอย่าง (และหลังจากการรีสตาร์ทการแสดงตัวอย่างทุกครั้ง)
อุปกรณ์บางรุ่นไม่รองรับฟีเจอร์การตรวจจับใบหน้า คุณสามารถตรวจสอบว่าฟีเจอร์นี้
รองรับโดยการโทรหา getMaxNumDetectedFaces()
CANNOT TRANSLATE
ตัวอย่างของการตรวจสอบนี้จะแสดงในวิธีการตัวอย่างด้านล่าง startFaceDetection()
ในการแจ้งเตือนและตอบสนองต่อการตรวจจับใบหน้า แอปพลิเคชันกล้องของคุณต้องตั้งค่า
Listener เหตุการณ์การตรวจจับใบหน้า ในการทำเช่นนั้น คุณต้องสร้างคลาส Listener ที่
ใช้อินเทอร์เฟซ Camera.FaceDetectionListener
ตามที่แสดงใน
โค้ดตัวอย่างด้านล่าง
Kotlin
internal class MyFaceDetectionListener : Camera.FaceDetectionListener { override fun onFaceDetection(faces: Array<Camera.Face>, camera: Camera) { if (faces.isNotEmpty()) { Log.d("FaceDetection", ("face detected: ${faces.size}" + " Face 1 Location X: ${faces[0].rect.centerX()}" + "Y: ${faces[0].rect.centerY()}")) } } }
Java
class MyFaceDetectionListener implements Camera.FaceDetectionListener { @Override public void onFaceDetection(Face[] faces, Camera camera) { if (faces.length > 0){ Log.d("FaceDetection", "face detected: "+ faces.length + " Face 1 Location X: " + faces[0].rect.centerX() + "Y: " + faces[0].rect.centerY() ); } } }
หลังจากสร้างชั้นเรียนนี้แล้ว ก็ตั้งค่าชั้นเรียนลงใน
Camera
ดังที่แสดงในโค้ดตัวอย่างด้านล่าง
Kotlin
camera?.setFaceDetectionListener(MyFaceDetectionListener())
Java
camera.setFaceDetectionListener(new MyFaceDetectionListener());
แอปพลิเคชันต้องเริ่มฟังก์ชันการตรวจจับใบหน้าทุกครั้งที่คุณเริ่ม (หรือรีสตาร์ท) แสดงตัวอย่างจากกล้อง สร้างวิธีการเริ่มต้นการตรวจจับใบหน้าเพื่อให้คุณโทรออกได้ตามที่ต้องการ ดังที่แสดงไว้ ในโค้ดตัวอย่างด้านล่าง
Kotlin
fun startFaceDetection() { // Try starting Face Detection val params = mCamera?.parameters // start face detection only *after* preview has started params?.apply { if (maxNumDetectedFaces > 0) { // camera supports face detection, so can start it: mCamera?.startFaceDetection() } } }
Java
public void startFaceDetection(){ // Try starting Face Detection Camera.Parameters params = mCamera.getParameters(); // start face detection only *after* preview has started if (params.getMaxNumDetectedFaces() > 0){ // camera supports face detection, so can start it: mCamera.startFaceDetection(); } }
คุณต้องเริ่มการตรวจจับใบหน้าทุกครั้งที่เริ่ม (หรือรีสตาร์ท) การแสดงตัวอย่างจากกล้อง ถ้า
เมื่อคุณใช้คลาสการแสดงตัวอย่างที่แสดงในการสร้างคลาสตัวอย่าง ให้เพิ่ม
startFaceDetection()
ไปยังทั้งเมธอด
surfaceCreated()
และ surfaceChanged()
เมธอดในคลาสดูตัวอย่างของคุณ
ดังที่แสดงในโค้ดตัวอย่างด้านล่าง
Kotlin
override fun surfaceCreated(holder: SurfaceHolder) { try { mCamera.setPreviewDisplay(holder) mCamera.startPreview() startFaceDetection() // start face detection feature } catch (e: IOException) { Log.d(TAG, "Error setting camera preview: ${e.message}") } } override fun surfaceChanged(holder: SurfaceHolder, format: Int, w: Int, h: Int) { if (holder.surface == null) { // preview surface does not exist Log.d(TAG, "holder.getSurface() == null") return } try { mCamera.stopPreview() } catch (e: Exception) { // ignore: tried to stop a non-existent preview Log.d(TAG, "Error stopping camera preview: ${e.message}") } try { mCamera.setPreviewDisplay(holder) mCamera.startPreview() startFaceDetection() // re-start face detection feature } catch (e: Exception) { // ignore: tried to stop a non-existent preview Log.d(TAG, "Error starting camera preview: ${e.message}") } }
Java
public void surfaceCreated(SurfaceHolder holder) { try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); startFaceDetection(); // start face detection feature } catch (IOException e) { Log.d(TAG, "Error setting camera preview: " + e.getMessage()); } } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { if (holder.getSurface() == null){ // preview surface does not exist Log.d(TAG, "holder.getSurface() == null"); return; } try { mCamera.stopPreview(); } catch (Exception e){ // ignore: tried to stop a non-existent preview Log.d(TAG, "Error stopping camera preview: " + e.getMessage()); } try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); startFaceDetection(); // re-start face detection feature } catch (Exception e){ // ignore: tried to stop a non-existent preview Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } }
หมายเหตุ: อย่าลืมเรียกใช้วิธีการนี้หลังจากการโทร
startPreview()
อย่าพยายามเริ่มการตรวจจับใบหน้า
ในเมธอด onCreate()
ของกิจกรรมหลักของแอปกล้อง
เนื่องจากการแสดงตัวอย่างยังไม่พร้อมใช้งาน ณ จุดนี้ในการดำเนินการของแอปพลิเคชันของคุณ
วิดีโอไทม์แลปส์
วิดีโอไทม์แลปส์ช่วยให้ผู้ใช้สร้างวิดีโอคลิปซึ่งรวมภาพที่ถ่ายในเวลา 2-3 วินาที หรือ
ห่างกัน 1 นาที ฟีเจอร์นี้ใช้ MediaRecorder
เพื่อบันทึกรูปภาพเป็นเวลาหนึ่ง
ตามลำดับขั้น
หากต้องการบันทึกวิดีโอไทม์แลปส์ด้วย MediaRecorder
คุณต้องกำหนดค่า
เหมือนว่าคุณกำลังบันทึกวิดีโอปกติอยู่ โดยตั้งค่าเฟรมต่อวินาทีที่บันทึก
ตัวเลขต่ำและใช้การตั้งค่าคุณภาพของไทม์แลปส์แบบใดแบบหนึ่ง ดังที่แสดงในตัวอย่างโค้ดด้านล่าง
Kotlin
mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH)) mediaRecorder.setCaptureRate(0.1) // capture a frame every 10 seconds
Java
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher) mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH)); ... // Step 5.5: Set the video capture rate to a low number mediaRecorder.setCaptureRate(0.1); // capture a frame every 10 seconds
การตั้งค่าเหล่านี้ต้องทำในฐานะขั้นตอนการกำหนดค่าที่ใหญ่กว่าสำหรับ MediaRecorder
สำหรับตัวอย่างรหัสการกำหนดค่าแบบเต็ม โปรดดูการกำหนดค่า MediaRecorder เมื่อกำหนดค่าเสร็จสมบูรณ์แล้ว
คุณจะเริ่มการบันทึกวิดีโอเหมือนกับว่าคุณกำลังบันทึกวิดีโอคลิปทั่วไป หากต้องการดูข้อมูลเพิ่มเติม
เกี่ยวกับการกำหนดค่าและการเรียกใช้ MediaRecorder
โปรดดูการจับภาพวิดีโอ
กล้องถ่ายรูป2วิดีโอ และ HdrViewfinder ตัวอย่างเพิ่มเติมสาธิตการใช้ API ที่กล่าวถึงในหน้านี้
ช่องกล้องที่ต้องใช้สิทธิ์
แอปที่ใช้ Android 10 (API ระดับ 29) ขึ้นไปต้องมี
CAMERA
เพื่อ
เข้าถึงค่าของช่องต่อไปนี้ที่พร็อพเพอร์ตี้
getCameraCharacteristics()
ผลลัพธ์:
LENS_POSE_ROTATION
LENS_POSE_TRANSLATION
LENS_INTRINSIC_CALIBRATION
LENS_RADIAL_DISTORTION
LENS_POSE_REFERENCE
LENS_DISTORTION
LENS_INFO_HYPERFOCAL_DISTANCE
LENS_INFO_MINIMUM_FOCUS_DISTANCE
SENSOR_REFERENCE_ILLUMINANT1
SENSOR_REFERENCE_ILLUMINANT2
SENSOR_CALIBRATION_TRANSFORM1
SENSOR_CALIBRATION_TRANSFORM2
SENSOR_COLOR_TRANSFORM1
SENSOR_COLOR_TRANSFORM2
SENSOR_FORWARD_MATRIX1
SENSOR_FORWARD_MATRIX2
โค้ดตัวอย่างเพิ่มเติม
หากต้องการดาวน์โหลดแอปตัวอย่าง โปรดดูที่ ตัวอย่าง Camera2Basic และ ตัวอย่างแอป CameraX อย่างเป็นทางการ