چارچوب Android شامل پشتیبانی از دوربینهای مختلف و ویژگیهای دوربین موجود در دستگاهها است که به شما امکان میدهد عکسها و ویدیوها را در برنامههای خود ثبت کنید. این سند یک رویکرد ساده و سریع برای ضبط تصویر و ویدیو را مورد بحث قرار میدهد و یک رویکرد پیشرفته را برای ایجاد تجربههای دوربین سفارشی برای کاربران شما تشریح میکند.
توجه: این صفحه کلاس Camera
را توصیف می کند که منسوخ شده است. توصیه می کنیم از کتابخانه CameraX Jetpack یا برای موارد استفاده خاص، از کلاس camera2
استفاده کنید. هر دو CameraX و Camera2 روی Android 5.0 (سطح API 21) و بالاتر کار می کنند.
به منابع مرتبط زیر مراجعه کنید:
ملاحظات
قبل از فعال کردن برنامه خود برای استفاده از دوربین در دستگاه های اندرویدی، باید چند سوال در مورد اینکه برنامه شما چگونه قصد استفاده از این ویژگی سخت افزاری را دارد، در نظر بگیرید.
- الزامات دوربین - آیا استفاده از دوربین آنقدر برای برنامه شما مهم است که نمی خواهید برنامه شما روی دستگاهی که دوربین ندارد نصب شود؟ اگر چنین است، باید الزامات دوربین را در مانیفست خود اعلام کنید.
- تصویر سریع یا دوربین سفارشی - برنامه شما چگونه از دوربین استفاده می کند؟ آیا فقط به گرفتن یک عکس یا کلیپ ویدیویی سریع علاقه دارید یا برنامه شما روش جدیدی برای استفاده از دوربین ارائه می دهد؟ برای گرفتن یک عکس یا کلیپ سریع، استفاده از برنامههای دوربین موجود را در نظر بگیرید. برای توسعه یک ویژگی دوربین سفارشی شده، بخش ساخت اپلیکیشن دوربین را بررسی کنید.
- الزامات خدمات پیش زمینه - چه زمانی برنامه شما با دوربین تعامل می کند؟ در اندروید 9 (سطح API 28) و جدیدتر، برنامههایی که در پسزمینه اجرا میشوند نمیتوانند به دوربین دسترسی داشته باشند. بنابراین، باید از دوربین یا زمانی که برنامه شما در پیش زمینه است یا به عنوان بخشی از یک سرویس پیش زمینه استفاده کنید.
- ذخیره سازی - آیا تصاویر یا ویدیوهایی که برنامه شما تولید می کند در نظر گرفته شده است که فقط برای برنامه شما قابل مشاهده باشند یا به اشتراک گذاشته شوند تا سایر برنامه ها مانند گالری یا سایر رسانه ها و برنامه های اجتماعی بتوانند از آنها استفاده کنند؟ آیا می خواهید حتی اگر برنامه شما حذف شده باشد، تصاویر و ویدیوها در دسترس باشند؟ برای مشاهده نحوه پیاده سازی این گزینه ها، بخش Saving Media Files را بررسی کنید.
اصول اولیه
چارچوب Android از ضبط تصاویر و ویدیو از طریق android.hardware.camera2
API یا Camera Intent
پشتیبانی می کند. در اینجا کلاس های مربوطه آمده است:
-
android.hardware.camera2
- این بسته API اصلی برای کنترل دوربین های دستگاه است. هنگامی که در حال ساخت یک برنامه دوربین هستید، می توان از آن برای گرفتن عکس یا فیلم استفاده کرد.
-
Camera
- این کلاس API قدیمیتر منسوخ برای کنترل دوربینهای دستگاه است.
-
SurfaceView
- این کلاس برای ارائه پیش نمایش دوربین زنده به کاربر استفاده می شود.
-
MediaRecorder
- این کلاس برای ضبط فیلم از دوربین استفاده می شود.
-
Intent
- یک نوع کنش هدف
MediaStore.ACTION_IMAGE_CAPTURE
یاMediaStore.ACTION_VIDEO_CAPTURE
میتواند برای گرفتن تصاویر یا ویدیوها بدون استفاده مستقیم از شیCamera
استفاده شود.
اعلامیه های آشکار
قبل از شروع توسعه برنامه خود با Camera API، باید مطمئن شوید که مانیفست شما دارای اعلانات مناسب برای اجازه استفاده از سخت افزار دوربین و سایر ویژگی های مرتبط است.
- مجوز دوربین - برنامه شما باید برای استفاده از دوربین دستگاه مجوز درخواست کند.
<uses-permission android:name="android.permission.CAMERA" />
توجه: اگر با فراخوانی یک برنامه دوربین موجود از دوربین استفاده می کنید، برنامه شما نیازی به درخواست این مجوز ندارد.
- ویژگی های دوربین - برنامه شما باید استفاده از ویژگی های دوربین را نیز اعلام کند، به عنوان مثال:
<uses-feature android:name="android.hardware.camera" />
برای فهرستی از ویژگیهای دوربین، به مرجع ویژگیهای مانیفست مراجعه کنید.
افزودن ویژگیهای دوربین به مانیفست شما باعث میشود Google Play از نصب برنامه شما بر روی دستگاههایی که فاقد دوربین هستند یا ویژگیهای دوربینی را که مشخص کردهاید پشتیبانی نمیکنند، جلوگیری کند. برای اطلاعات بیشتر در مورد استفاده از فیلتر مبتنی بر ویژگی با Google Play، به Google Play و فیلتر مبتنی بر ویژگی مراجعه کنید.
اگر برنامه شما می تواند از یک دوربین یا ویژگی دوربین برای عملکرد مناسب استفاده کند ، اما به آن نیاز ندارد، باید آن را در مانیفست با اضافه کردن ویژگی
android:required
و تنظیم آن بر رویfalse
مشخص کنید:<uses-feature android:name="android.hardware.camera" android:required="false" />
- مجوز ذخیرهسازی - اگر برنامه شما Android 10 (سطح API 29) یا پایینتر را هدف قرار دهد و موارد زیر را در مانیفست مشخص کند، میتواند تصاویر یا ویدیوها را در حافظه خارجی دستگاه (کارت SD) ذخیره کند.
<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
برای فراخوانی یک برنامه دوربین اندروید موجود است. جزئیات در درس های آموزش عکس گرفتن به سادگی و ضبط فیلم به سادگی توضیح داده شده است.
ساخت اپلیکیشن دوربین
برخی از توسعه دهندگان ممکن است به یک رابط کاربری دوربین نیاز داشته باشند که برای ظاهر برنامه آنها سفارشی شده باشد یا ویژگی های خاصی را ارائه دهد. نوشتن کد عکسبرداری خود می تواند تجربه قانع کننده تری را برای کاربران شما فراهم کند.
توجه: راهنمای زیر برای Camera
API قدیمی و منسوخ شده است. برای برنامه های جدید یا پیشرفته دوربین، API جدیدتر android.hardware.camera2
توصیه می شود.
مراحل کلی برای ایجاد یک رابط دوربین سفارشی برای برنامه شما به شرح زیر است:
- شناسایی و دسترسی به دوربین - برای بررسی وجود دوربین ها و درخواست دسترسی، کد ایجاد کنید.
- ایجاد کلاس پیش نمایش - یک کلاس پیش نمایش دوربین ایجاد کنید که
SurfaceView
گسترش داده و رابطSurfaceHolder
را پیاده سازی کند. این کلاس پیش نمایش تصاویر زنده از دوربین است. - ایجاد یک طرحبندی پیشنمایش - هنگامی که کلاس پیشنمایش دوربین را دارید، یک طرحنمای نمای ایجاد کنید که پیشنمایش و کنترلهای رابط کاربری مورد نظر شما را در خود جای دهد.
- Setup Listeners for Capture - شنوندگان را برای کنترل های رابط خود وصل کنید تا در پاسخ به اقدامات کاربر، مانند فشار دادن یک دکمه، ضبط تصویر یا فیلم را شروع کنید.
- ضبط و ذخیره فایل ها - کد را برای گرفتن عکس یا فیلم و ذخیره خروجی تنظیم کنید.
- رها کردن دوربین - پس از استفاده از دوربین، برنامه شما باید به درستی آن را برای استفاده توسط سایر برنامه ها آزاد کند.
سخت افزار دوربین یک منبع مشترک است که باید به دقت مدیریت شود تا برنامه شما با سایر برنامه هایی که ممکن است بخواهند از آن استفاده کنند برخورد نکند. در بخشهای زیر نحوه شناسایی سختافزار دوربین، نحوه درخواست دسترسی به دوربین، نحوه گرفتن عکس یا ویدیو و نحوه رها کردن دوربین زمانی که برنامه شما با استفاده از آن تمام شد، بحث میکند.
احتیاط: به یاد داشته باشید که وقتی برنامه شما با استفاده از آن تمام شد، با فراخوانی Camera.release()
شی Camera
آزاد کنید! اگر برنامه شما به درستی دوربین را آزاد نکند، تمام تلاشهای بعدی برای دسترسی به دوربین، از جمله تلاشهایی که توسط برنامه خودتان انجام میشود، با شکست مواجه میشوند و ممکن است باعث خاموش شدن شما یا سایر برنامهها شود.
تشخیص سخت افزار دوربین
اگر برنامه شما به طور خاص به دوربینی با استفاده از اعلان مانیفست نیاز ندارد، باید بررسی کنید که آیا دوربین در زمان اجرا در دسترس است یا خیر. برای انجام این بررسی، از متد PackageManager.hasSystemFeature()
استفاده کنید، همانطور که در کد مثال زیر نشان داده شده است:
کاتلین
/** 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 } }
جاوا
/** 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 2.3 (API Level 9) و جدیدتر به شما امکان می دهد با استفاده از روش Camera.getNumberOfCameras()
تعداد دوربین های موجود در دستگاه را بررسی کنید.
دسترسی به دوربین ها
اگر تشخیص دادهاید که دستگاهی که برنامه شما روی آن اجرا میشود دارای دوربین است، باید با دریافت نمونهای از Camera
درخواست دسترسی به آن را داشته باشید (مگر اینکه از قصدی برای دسترسی به دوربین استفاده کنید).
برای دسترسی به دوربین اصلی، از روش Camera.open()
استفاده کنید و مطمئن شوید که استثنائات را همانطور که در کد زیر نشان داده شده است، بگیرید:
کاتلین
/** 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 } }
جاوا
/** 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)
به دوربینهای خاصی دسترسی داشته باشید. کد مثال بالا به اولین دوربین پشت دستگاهی با بیش از یک دوربین دسترسی خواهد داشت.
بررسی ویژگی های دوربین
هنگامی که به یک دوربین دسترسی پیدا کردید، می توانید با استفاده از روش Camera.getParameters()
و بررسی شئ Camera.Parameters
بازگشتی برای قابلیت های پشتیبانی شده، اطلاعات بیشتری در مورد قابلیت های آن دریافت کنید. هنگام استفاده از API سطح 9 یا بالاتر، از Camera.getCameraInfo()
برای تعیین اینکه آیا دوربین در جلو یا پشت دستگاه است و جهت تصویر استفاده کنید.
ایجاد کلاس پیش نمایش
برای اینکه کاربران بتوانند به طور موثر عکس یا فیلم بگیرند، باید بتوانند آنچه را که دوربین دستگاه می بیند، ببینند. کلاس پیشنمایش دوربین، SurfaceView
است که میتواند دادههای تصویری زنده را که از یک دوربین دریافت میشود، نمایش دهد، بنابراین کاربران میتوانند یک عکس یا ویدیو را قاببندی و ضبط کنند.
کد مثال زیر نحوه ایجاد یک کلاس پیش نمایش اولیه دوربین را نشان می دهد که می تواند در یک طرح بندی View
گنجانده شود. این کلاس SurfaceHolder.Callback
را به منظور ضبط رویدادهای برگشتی برای ایجاد و از بین بردن نمای، که برای تخصیص ورودی پیش نمایش دوربین مورد نیاز است، پیاده سازی می کند.
کاتلین
/** 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}") } } } }
جاوا
/** 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()
مقادیر دلخواه تنظیم نکنید .
توجه: با معرفی ویژگی Multi-Window در اندروید 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>
در اکثر دستگاهها، جهت پیشفرض پیشنمایش دوربین، افقی است. این طرحبندی مثال، یک طرح افقی (منظره) را مشخص میکند و کد زیر جهتگیری برنامه را به منظره ثابت میکند. برای سهولت در ارائه پیشنمایش دوربین، باید جهتگیری فعالیت پیشنمایش برنامه خود را با افزودن موارد زیر به مانیفست خود به افقی تغییر دهید.
<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 Level 8)، میتوانید از متد setDisplayOrientation()
برای تنظیم چرخش تصویر پیشنمایش استفاده کنید. به منظور تغییر جهت پیشنمایش زمانی که کاربر گوشی را تغییر میدهد، در متد surfaceChanged()
کلاس پیشنمایش، ابتدا پیشنمایش را با Camera.stopPreview()
متوقف کنید، جهت را تغییر دهید و سپس پیشنمایش را دوباره با Camera.startPreview()
.
در فعالیت برای نمای دوربین خود، کلاس پیش نمایش خود را به عنصر FrameLayout
نشان داده شده در مثال بالا اضافه کنید. فعالیت دوربین شما همچنین باید اطمینان حاصل کند که هنگام توقف یا خاموش شدن، دوربین را آزاد می کند. مثال زیر نشان می دهد که چگونه می توان یک فعالیت دوربین را برای پیوست کردن کلاس پیش نمایش نشان داده شده در ایجاد کلاس پیش نمایش تغییر داد.
کاتلین
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) } } }
جاوا
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()
در مثال بالا به روش نمونه نشان داده شده در Accessing cameras اشاره دارد.
گرفتن عکس
هنگامی که یک کلاس پیش نمایش و یک طرح نمایش برای نمایش آن ایجاد کردید، آماده شروع به گرفتن تصاویر با برنامه خود هستید. در کد برنامه خود، باید شنوندههایی را برای کنترلهای رابط کاربری خود تنظیم کنید تا با گرفتن عکس به یک اقدام کاربر پاسخ دهند.
برای بازیابی تصویر، از متد Camera.takePicture()
استفاده کنید. این روش سه پارامتر را می گیرد که داده ها را از دوربین دریافت می کند. برای دریافت داده ها در فرمت JPEG، باید یک رابط Camera.PictureCallback
برای دریافت داده های تصویر و نوشتن آن در یک فایل پیاده سازی کنید. کد زیر یک پیاده سازی اساسی از رابط Camera.PictureCallback
برای ذخیره تصویر دریافت شده از دوربین را نشان می دهد.
کاتلین
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}") } }
جاوا
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
نشان می دهد.
کاتلین
val captureButton: Button = findViewById(R.id.button_capture) captureButton.setOnClickListener { // get an image from the camera mCamera?.takePicture(null, null, picture) }
جاوا
// 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.release()
شی Camera
آزاد کنید! برای اطلاعات در مورد نحوه آزاد کردن دوربین، رها کردن دوربین را ببینید.
فیلم برداری
ضبط ویدیو با استفاده از فریم ورک اندروید نیاز به مدیریت دقیق شی Camera
و هماهنگی با کلاس MediaRecorder
دارد. هنگام ضبط ویدیو با Camera
، باید تماسهای Camera.lock()
و Camera.unlock()
را مدیریت کنید تا به MediaRecorder
اجازه دسترسی به سختافزار دوربین، علاوه بر تماسهای Camera.open()
و Camera.release()
را بدهید.
توجه: با شروع Android 4.0 (سطح API 14)، تماسهای Camera.lock()
و Camera.unlock()
بطور خودکار برای شما مدیریت میشوند.
بر خلاف عکس گرفتن با دوربین دستگاه، فیلمبرداری نیاز به نظم تماس بسیار خاصی دارد. برای آماده سازی موفقیت آمیز و ضبط ویدیو با برنامه خود، همانطور که در زیر توضیح داده شده است، باید ترتیب خاصی از اجرا را دنبال کنید.
- Open Camera - از
Camera.open()
برای دریافت نمونه ای از شی دوربین استفاده کنید. - پیشنمایش اتصال - با اتصال
SurfaceView
به دوربین با استفاده ازCamera.setPreviewDisplay()
یک پیشنمایش تصویر زنده دوربین آماده کنید. - شروع پیشنمایش - با
Camera.startPreview()
تماس بگیرید تا تصاویر دوربین زنده را نمایش دهید. - شروع ضبط ویدیو - برای ضبط موفقیت آمیز ویدیو مراحل زیر باید انجام شود:
- قفل دوربین را باز کنید - با فراخوانی
Camera.unlock()
قفل دوربین را برای استفاده توسطMediaRecorder
باز کنید. - MediaRecorder را پیکربندی کنید - روش های
MediaRecorder
زیر را به این ترتیب فراخوانی کنید. برای اطلاعات بیشتر، به مستندات مرجعMediaRecorder
مراجعه کنید.-
setCamera()
- دوربین را طوری تنظیم کنید که برای فیلمبرداری استفاده شود، از نمونه فعلیCamera
خود در برنامه خود استفاده کنید. -
setAudioSource()
- منبع صوتی را تنظیم کنید، ازMediaRecorder.AudioSource.CAMCORDER
استفاده کنید. -
setVideoSource()
- منبع ویدیو را تنظیم کنید، ازMediaRecorder.VideoSource.CAMERA
استفاده کنید. - فرمت خروجی ویدیو و رمزگذاری را تنظیم کنید. برای Android 2.2 (API Level 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()
از روش مثال در بخش Saving Media Files استفاده کنید. -
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()
متوقف کنید. - Release Camera - دوربین را رها کنید تا سایر برنامه ها بتوانند با فراخوانی
Camera.release()
از آن استفاده کنند.
توجه: می توان بدون ایجاد پیش نمایش دوربین ابتدا از MediaRecorder
استفاده کرد و از چند مرحله اول این فرآیند صرف نظر کرد. با این حال، از آنجایی که کاربران معمولاً ترجیح می دهند قبل از شروع ضبط یک پیش نمایش را ببینند، این فرآیند در اینجا مورد بحث قرار نمی گیرد.
نکته: اگر برنامه شما معمولاً برای ضبط ویدیو استفاده میشود، قبل از شروع پیشنمایش، setRecordingHint(boolean)
را روی true
تنظیم کنید. این تنظیم می تواند به کاهش زمان شروع ضبط کمک کند.
پیکربندی MediaRecorder
هنگامی که از کلاس MediaRecorder
برای ضبط ویدیو استفاده می کنید، باید مراحل پیکربندی را به ترتیب خاصی انجام دهید و سپس متد MediaRecorder.prepare()
را برای بررسی و پیاده سازی پیکربندی فراخوانی کنید. کد مثال زیر نحوه صحیح پیکربندی و آماده سازی کلاس MediaRecorder
را برای ضبط ویدیو نشان می دهد.
کاتلین
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 }
جاوا
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 Level 8)، به جای استفاده از CamcorderProfile
، باید فرمت خروجی و پارامترهای فرمت های رمزگذاری را مستقیماً تنظیم کنید. این رویکرد در کد زیر نشان داده شده است:
کاتلین
// 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) }
جاوا
// 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
نشان می دهد.
توجه: هنگام تکمیل فیلمبرداری، دوربین را رها نکنید وگرنه پیش نمایش شما متوقف خواهد شد.
کاتلین
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 } } }
جاوا
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()
به کد مثال نشان داده شده در Configuring MediaRecorder اشاره دارد. این روش از قفل کردن دوربین، پیکربندی و آماده سازی نمونه MediaRecorder
مراقبت می کند.
رها کردن دوربین
دوربین ها منبعی هستند که توسط برنامه های کاربردی روی یک دستگاه به اشتراک گذاشته می شود. برنامه شما می تواند پس از دریافت نمونه Camera
از دوربین استفاده کند، و شما باید به ویژه مراقب باشید که وقتی برنامه شما استفاده از آن را متوقف می کند، و به محض اینکه برنامه شما متوقف می شود، شی دوربین را رها کنید ( Activity.onPause()
). اگر برنامه شما به درستی دوربین را آزاد نکند، تمام تلاشهای بعدی برای دسترسی به دوربین، از جمله تلاشهایی که توسط برنامه خودتان انجام میشود، با شکست مواجه میشوند و ممکن است باعث خاموش شدن شما یا سایر برنامهها شود.
برای انتشار یک نمونه از شی Camera
، از متد Camera.release()
استفاده کنید، همانطور که در کد مثال زیر نشان داده شده است.
کاتلین
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 } }
جاوا
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) ذخیره شوند تا فضای سیستم حفظ شود و کاربران بتوانند بدون دستگاه خود به این فایلها دسترسی داشته باشند. مکان های دایرکتوری زیادی برای ذخیره فایل های رسانه ای در دستگاه وجود دارد، با این حال تنها دو مکان استاندارد وجود دارد که باید به عنوان یک توسعه دهنده در نظر بگیرید:
-
Environment.getExternalStoragePublicDirectory
(Environment.DIRECTORY_PICTURES
) - این روش مکان استاندارد، مشترک و توصیه شده را برای ذخیره تصاویر و ویدیوها برمی گرداند. این دایرکتوری به اشتراک گذاشته شده است (عمومی)، بنابراین سایر برنامه ها می توانند به راحتی فایل های ذخیره شده در این مکان را کشف، خواندن، تغییر و حذف کنند. اگر برنامه شما توسط کاربر حذف نصب شود، فایل های رسانه ای ذخیره شده در این مکان حذف نخواهند شد. برای جلوگیری از تداخل با تصاویر و ویدیوهای موجود کاربران، باید یک دایرکتوری فرعی برای فایل های رسانه ای برنامه خود در این فهرست ایجاد کنید، همانطور که در نمونه کد زیر نشان داده شده است. این روش در Android 2.2 (سطح API 8) موجود است، برای تماسهای معادل در نسخههای قبلی API، به ذخیره فایلهای مشترک مراجعه کنید. -
Context.getExternalFilesDir
(Environment.DIRECTORY_PICTURES
) - این روش یک مکان استاندارد را برای ذخیره تصاویر و ویدیوهایی که با برنامه شما مرتبط هستند برمی گرداند. اگر برنامه شما حذف نصب شود، هر فایلی که در این مکان ذخیره شده است حذف می شود. امنیت برای فایلهای موجود در این مکان اعمال نمیشود و سایر برنامهها ممکن است آنها را بخوانند، تغییر دهند و حذف کنند.
کد مثال زیر نحوه ایجاد یک مکان File
یا Uri
را برای یک فایل رسانه ای نشان می دهد که می تواند هنگام فراخوانی دوربین دستگاه با Intent
یا به عنوان بخشی از ساختن یک برنامه دوربین استفاده شود.
کاتلین
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 } }
جاوا
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()
در اندروید 2.2 (سطح API 8) یا بالاتر موجود است. اگر دستگاههای دارای نسخههای قبلی اندروید را هدف قرار میدهید، به جای آن از Environment.getExternalStorageDirectory()
استفاده کنید. برای اطلاعات بیشتر، به ذخیره فایلهای مشترک مراجعه کنید.
برای اینکه URI از نمایه های کاری پشتیبانی کند، ابتدا URI فایل را به یک URI محتوا تبدیل کنید . سپس، URI محتوا را به EXTRA_OUTPUT
یک Intent
اضافه کنید.
برای اطلاعات بیشتر درباره ذخیره فایلها در دستگاه Android، به «ذخیرهسازی داده» مراجعه کنید.
ویژگی های دوربین
اندروید از طیف گسترده ای از ویژگی های دوربین پشتیبانی می کند که می توانید با برنامه دوربین خود کنترل کنید، مانند فرمت تصویر، حالت فلاش، تنظیمات فوکوس و بسیاری موارد دیگر. این بخش ویژگی های رایج دوربین را فهرست می کند و نحوه استفاده از آنها را به اختصار توضیح می دهد. اکثر ویژگی های دوربین را می توان با استفاده از شیء از طریق Camera.Parameters
قابل دسترسی و تنظیم کرد. با این حال، چندین ویژگی مهم وجود دارد که به تنظیماتی بیش از تنظیمات ساده در Camera.Parameters
نیاز دارند. این ویژگی ها در بخش های زیر پوشش داده شده است:
برای اطلاعات کلی در مورد نحوه استفاده از ویژگیهایی که از طریق Camera.Parameters
کنترل میشوند، بخش استفاده از ویژگیهای دوربین را مرور کنید. برای اطلاعات دقیق تر در مورد نحوه استفاده از ویژگی های کنترل شده از طریق شی پارامترهای دوربین، پیوندهای موجود در لیست ویژگی های زیر را به مستندات مرجع API دنبال کنید.
ویژگی | سطح API | توضیحات |
---|---|---|
تشخیص چهره | 14 | چهره انسان را در یک تصویر شناسایی کنید و از آنها برای فوکوس، نورسنجی و تعادل رنگ سفید استفاده کنید |
مناطق اندازه گیری | 14 | برای محاسبه تراز سفیدی یک یا چند ناحیه را در یک تصویر مشخص کنید |
مناطق تمرکز | 14 | یک یا چند ناحیه در یک تصویر را برای استفاده برای فوکوس تنظیم کنید |
White Balance Lock | 14 | توقف یا شروع تنظیمات خودکار تعادل رنگ سفید |
Exposure Lock | 14 | تنظیم خودکار نوردهی را متوقف یا شروع کنید |
Video Snapshot | 14 | هنگام فیلمبرداری عکس بگیرید (قاب گرفتن) |
فیلم تایم لپس | 11 | برای ضبط ویدیوی تایم لپس فریم هایی را با تأخیرهای تنظیم شده ضبط کنید |
Multiple Cameras | 9 | پشتیبانی از بیش از یک دوربین در یک دستگاه، از جمله دوربین های جلو و عقب |
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
را بدست آورید و بررسی کنید که آیا دوربین از ویژگی فوکوس خودکار پشتیبانی می کند یا خیر:
کاتلین
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 }
جاوا
// 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...()
برای تعیین اینکه آیا (و تا چه حد) یک ویژگی پشتیبانی می شود ارائه می دهد.
اگر برنامه شما به ویژگیهای دوربین خاصی نیاز دارد تا به درستی کار کند، میتوانید از طریق افزودنیهایی به مانیفست برنامه خود به آنها نیاز داشته باشید. وقتی استفاده از ویژگیهای خاص دوربین مانند فلاش و فوکوس خودکار را اعلام میکنید، Google Play نصب برنامه شما را بر روی دستگاههایی که از این ویژگیها پشتیبانی نمیکنند، محدود میکند. برای فهرستی از ویژگیهای دوربین که میتوان در مانیفست برنامهتان اعلام کرد، به مرجع ویژگیهای مانیفست مراجعه کنید.
استفاده از ویژگی های دوربین
اکثر ویژگی های دوربین با استفاده از یک شی Camera.Parameters
فعال و کنترل می شوند. شما این شی را با دریافت نمونه ای از شی Camera
، فراخوانی متد getParameters()
، تغییر آبجکت پارامتر برگشتی و سپس تنظیم مجدد آن در شی دوربین، همانطور که در کد مثال زیر نشان داده شده است، به دست می آورید:
کاتلین
val params: Camera.Parameters? = camera?.parameters params?.focusMode = Camera.Parameters.FOCUS_MODE_AUTO camera?.parameters = params
جاوا
// 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 Level 14) جهت پیشنمایش را میتوان بدون راهاندازی مجدد پیشنمایش تغییر داد.
سایر ویژگی های دوربین برای پیاده سازی به کد بیشتری نیاز دارند، از جمله:
- مناطق اندازه گیری و فوکوس
- تشخیص چهره
- ویدیوی تایم لپس
یک طرح کلی از نحوه پیاده سازی این ویژگی ها در بخش های بعدی ارائه شده است.
مناطق اندازه گیری و فوکوس
در برخی از سناریوهای عکاسی، فوکوس خودکار و نورسنجی ممکن است نتایج دلخواه را ایجاد نکند. با شروع Android 4.0 (API Level 14)، برنامه دوربین شما میتواند کنترلهای بیشتری را ارائه دهد تا به برنامه یا کاربران شما اجازه دهد مناطقی را در تصویر مشخص کنند تا از آن برای تعیین فوکوس یا تنظیمات سطح نور استفاده کنند و این مقادیر را به سختافزار دوربین برای استفاده در عکسبرداری منتقل کنند. تصاویر یا ویدیو
قسمتهای اندازهگیری و فوکوس بسیار شبیه به سایر ویژگیهای دوربین عمل میکنند، به این ترتیب که آنها را از طریق روشهایی در شی Camera.Parameters
کنترل میکنید. کد زیر تنظیم دو ناحیه نورسنجی را برای نمونه ای از Camera
نشان می دهد:
کاتلین
// 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 }
جاوا
// 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
شامل دو پارامتر داده است: یک شی Rect
برای مشخص کردن یک ناحیه در میدان دید دوربین و یک مقدار وزن، که به دوربین می گوید که این ناحیه در اندازه گیری نور یا محاسبات فوکوس چقدر اهمیت دارد.
فیلد Rect
در یک شی Camera.Area
یک شکل مستطیلی را توصیف می کند که روی یک شبکه 2000 x 2000 واحد نگاشت شده است. مختصات 1000-، 1000- نمایانگر گوشه بالا و سمت چپ تصویر دوربین و مختصات 1000، 1000 نمایانگر گوشه پایین و سمت راست تصویر دوربین است، همانطور که در تصویر زیر نشان داده شده است.
مرزهای این سیستم مختصات همیشه با لبه بیرونی تصویر قابل مشاهده در پیش نمایش دوربین مطابقت دارد و با سطح زوم کوچک یا بزرگ نمی شود. به طور مشابه، چرخش پیشنمایش تصویر با استفاده از Camera.setDisplayOrientation()
سیستم مختصات را مجدداً ترسیم نمیکند.
تشخیص چهره
برای عکسهایی که شامل افراد میشود، چهرهها معمولاً مهمترین بخش تصویر هستند و باید برای تعیین فوکوس و تعادل رنگ سفید هنگام ثبت یک تصویر استفاده شوند. چارچوب Android 4.0 (API Level 14) API هایی را برای شناسایی چهره ها و محاسبه تنظیمات تصویر با استفاده از فناوری تشخیص چهره ارائه می دهد.
توجه: هنگامی که ویژگی تشخیص چهره در حال اجرا است، setWhiteBalance(String)
، setFocusAreas(List<Camera.Area>)
و setMeteringAreas(List<Camera.Area>)
هیچ تاثیری ندارند.
استفاده از ویژگی تشخیص چهره در برنامه دوربین شما به چند مرحله کلی نیاز دارد:
- بررسی کنید که تشخیص چهره در دستگاه پشتیبانی میشود
- شنونده تشخیص چهره ایجاد کنید
- شنونده تشخیص چهره را به شی دوربین خود اضافه کنید
- شروع تشخیص چهره پس از پیش نمایش (و پس از هر پیش نمایش راه اندازی مجدد)
ویژگی تشخیص چهره در همه دستگاه ها پشتیبانی نمی شود. با فراخوانی getMaxNumDetectedFaces()
می توانید بررسی کنید که این ویژگی پشتیبانی می شود. نمونه ای از این بررسی در روش نمونه startFaceDetection()
در زیر نشان داده شده است.
برای اطلاع و پاسخ به تشخیص چهره، برنامه دوربین شما باید شنونده ای را برای رویدادهای تشخیص چهره تنظیم کند. برای انجام این کار، باید یک کلاس listener ایجاد کنید که رابط Camera.FaceDetectionListener
را همانطور که در کد مثال زیر نشان داده شده است، پیاده سازی کند.
کاتلین
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()}")) } } }
جاوا
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
برنامه خود تنظیم می کنید:
کاتلین
camera?.setFaceDetectionListener(MyFaceDetectionListener())
جاوا
camera.setFaceDetectionListener(new MyFaceDetectionListener());
هر بار که پیشنمایش دوربین را شروع (یا راهاندازی مجدد) میکنید، برنامه شما باید عملکرد تشخیص چهره را شروع کند. روشی برای شروع تشخیص چهره ایجاد کنید تا بتوانید در صورت نیاز آن را فراخوانی کنید، همانطور که در کد مثال زیر نشان داده شده است.
کاتلین
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() } } }
جاوا
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()
در کلاس پیش نمایش خود اضافه کنید ، همانطور که در کد نمونه زیر نشان داده شده است.
کاتلین
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}") } }
جاوا
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()
تشخیص چهره را شروع کنید ، زیرا پیش نمایش تا این مرحله در اجرای برنامه شما در دسترس نیست.
ویدیوی تایم لپس
Time Lapse Video به کاربران امکان می دهد کلیپ های ویدیویی ایجاد کنند که تصاویر چند ثانیه یا چند دقیقه از هم جدا می شوند. این ویژگی از MediaRecorder
برای ضبط تصاویر برای یک دنباله گذشت زمان استفاده می کند.
برای ضبط یک فیلم با گذشت زمان با MediaRecorder
، شما باید شیء ضبط را پیکربندی کنید که گویی در حال ضبط یک فیلم معمولی هستید ، قاب های ضبط شده در هر ثانیه را به تعداد کم تنظیم می کنید و از یکی از تنظیمات کیفیت با گذشت زمان استفاده می کنید ، همانطور که در مثال کد نشان داده شده است. زیر
کاتلین
mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH)) mediaRecorder.setCaptureRate(0.1) // capture a frame every 10 seconds
جاوا
// 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) یا بالاتر را اجرا می کنند ، برای دسترسی به مقادیر قسمتهای زیر که روش getCameraCharacteristics()
باز می گردد ، مجوز CAMERA
را دارند:
-
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 مراجعه کنید.