چارچوب Android شامل پشتیبانی از دوربینهای مختلف و ویژگیهای دوربین موجود در دستگاهها است، که به شما امکان میدهد عکسها و ویدیوها را در برنامههای خود ضبط کنید. این سند درباره رویکردی سریع و ساده برای ضبط تصویر و ویدیو بحث میکند و رویکردی پیشرفته برای ایجاد تجربههای سفارشی دوربین برای کاربران شما ارائه میدهد.
توجه:
این صفحه کلاس
Camera
را شرح میدهد که منسوخ شده است. توصیه میکنیم از کتابخانه Jetpack
CameraX یا، برای موارد استفاده خاص، از کلاس
camera2
استفاده کنید. CameraX و Camera2 هر دو در Android 5.0 (سطح API ۲۱) و
بالاتر کار میکنند.
به منابع مرتبط زیر مراجعه کنید:
ملاحظات
قبلاز فعال کردن برنامهتان برای استفاده از دوربینها در دستگاههای Android، باید چند سؤال را درباره نحوه استفاده برنامهتان از این ویژگی سختافزاری درنظر بگیرید.
- الزامات دوربین - آیا استفاده از دوربین برای برنامه شما آنقدر مهم است که نمیخواهید برنامهتان در دستگاهی که دوربین ندارد نصب شود؟ اگر اینطور است، باید الزام دوربین را در مانیفست خود اعلام کنید.
- عکس فوری یا دوربین سفارشی - برنامه شما چگونه از دوربین استفاده خواهد کرد؟ آیا فقط به گرفتن عکس فوری یا کلیپ ویدیویی علاقه دارید یا برنامهتان روش جدیدی برای استفاده از دوربینها ارائه میدهد؟ برای گرفتن عکس یا کلیپ سریع، استفاده از برنامههای دوربین موجود را درنظر بگیرید. برای توسعه ویژگی سفارشی دوربین، بخش ساختن برنامه دوربین را بررسی کنید.
- الزامات سرویسهای پیشزمینهای - برنامهتان چه زمانی با دوربین تعامل برقرار میکند؟ در Android نسخه ۹ (سطح API ۲۸) و بالاتر، برنامههایی که در پسزمینه اجرا میشوند نمیتوانند به دوربین دسترسی داشته باشند. بنابراین، باید از دوربین یا زمانیکه برنامهتان در پیشزمینه است یا بهعنوان بخشی از سرویس پیشزمینهای استفاده کنید.
- فضای ذخیرهسازی - آیا تصاویر یا ویدیوهایی که برنامهتان تولید میکند فقط برای برنامهتان قابلمشاهده است یا همرسانی میشود تا برنامههای دیگر مثل «گالری» یا دیگر برنامههای رسانهای و اجتماعی بتوانند از آنها استفاده کنند؟ آیا میخواهید عکسها و ویدیوها حتی درصورت حذف نصب برنامهتان دردسترس باشند؟ برای دیدن نحوه پیادهسازی این گزینهها، بخش ذخیره کردن فایلهای رسانهای را بررسی کنید.
اصول اولیه
چارچوب Android از ضبط تصاویر و ویدیو ازطریق
android.hardware.camera2 API یا دوربین 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 ۲۹) یا نسخههای پایینتر را هدف قرار دهد و موارد زیر را در مانیفست مشخص کند، میتواند تصاویر یا ویدیوها را در فضای ذخیرهسازی خارجی دستگاه (کارت SD) ذخیره کند.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- اجازه ضبط صدا - برای ضبط صدا همراه با ضبط ویدیو، برنامه شما باید اجازه ضبط صدا را درخواست کند.
<uses-permission android:name="android.permission.RECORD_AUDIO" />
-
اجازه مکان - اگر برنامه شما تصاویر را با اطلاعات مکان GPS برچسبگذاری میکند، باید اجازه
ACCESS_FINE_LOCATIONرا درخواست کنید. توجه داشته باشید که اگر برنامه شما Android نسخه ۵.۰ (سطح میانای برنامهسازی کاربردی ۲۱) یا بالاتر را هدف قرار میدهد، باید اعلام کنید که برنامهتان از 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را پیادهسازی کند. این کلاس تصاویر زنده را از دوربین پیشنمایش میکند. - ساختن چیدمان پیشنمایش - وقتی کلاس پیشنمایش دوربین را داشتید، چیدمان نمایی ایجاد کنید که پیشنمایش و کنترلهای میانای کاربر موردنظرتان را دربرگیرد.
- راهاندازی شنوندگان برای ضبط - شنوندگان را برای کنترلهای میانای خود متصل کنید تا ضبط تصویر یا ویدیو را در پاسخ به کنشهای کاربر، مانند فشار دادن دکمه، شروع کنید.
- ضبط و ذخیره فایلها - کد را برای ضبط عکس یا ویدیو و ذخیره کردن خروجی راهاندازی کنید.
- آزاد کردن دوربین - پساز استفاده از دوربین، برنامه شما باید آن را بهدرستی آزاد کند تا برنامههای دیگر بتوانند از آن استفاده کنند.
سختافزار دوربین منبعی مشترک است که باید بهدقت مدیریت شود تا برنامهتان با برنامههای دیگری که ممکن است بخواهند از آن استفاده کنند تداخل نداشته باشد. بخشهای زیر درباره نحوه شناسایی سختافزار دوربین، نحوه درخواست دسترسی به دوربین، نحوه گرفتن عکس یا ویدیو، و نحوه آزاد کردن دوربین پساز اتمام استفاده برنامه از آن بحث میکند.
احتیاط: فراموش نکنید که وقتی کار برنامهتان با شیء Camera تمام شد، آن را با فراخوانی Camera.release() آزاد کنید! اگر برنامه شما دوربین را بهدرستی آزاد نکند، همه تلاشهای بعدی برای دسترسی به دوربین، ازجمله تلاشهای برنامه خودتان، ناموفق خواهد بود و ممکن است باعث بسته شدن برنامه شما یا برنامههای دیگر شود.
درحال شناسایی سختافزار دوربین
اگر برنامه شما بهطور خاص به دوربینی که از اعلامیه مانیفست استفاده میکند نیاز ندارد،
باید بررسی کنید که آیا دوربین در زمان اجرا دردسترس است یا نه. برای انجام این بررسی، از روش 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 میتوانند چند دوربین داشته باشند، برای مثال دوربین پشت برای عکاسی و دوربین جلو برای تماسهای تصویری. Android 2.3 (سطح API ۹) و نسخههای جدیدتر به شما امکان میدهد
تعداد دوربینهای دردسترس در دستگاه را بااستفاده از روش 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 (سطح میانای برنامهسازی کاربردی ۹) یا بالاتر استفاده میکنند، میتوانید بااستفاده از
Camera.open(int) به دوربینهای خاصی دسترسی پیدا کنید. کد نمونه بالا به اولین دوربین پشت در دستگاهی با بیشاز یک دوربین دسترسی پیدا میکند.
درحال بررسی ویژگیهای دوربین
وقتی به دوربین دسترسی پیدا کردید، میتوانید بااستفاده از روش Camera.getParameters() و بررسی شیء Camera.Parameters برگرداندهشده برای قابلیتهای پشتیبانیشده، اطلاعات بیشتری درباره قابلیتهای آن کسب کنید. هنگام استفاده از
سطح API ۹ یا بالاتر، از 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() تنظیم نکنید.
توجه:
با معرفی ویژگی
چندپنجرهای در Android نسخه ۷.۰ (سطح میانای برنامهسازی کاربردی ۲۴) و بالاتر، دیگر نمیتوانید
فرض کنید نسبت ابعادی پیشنمایش با فعالیت شما یکسان است،
حتی پساز فراخوانی 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 ۸) به بعد، میتوانید از روش 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() در مثال بالا
به روش نمونه نشاندادهشده در دسترسی به دوربینها اشاره دارد.
درحال گرفتن عکس
پساز ساختن کلاس پیشنمایش و چیدمان نمایشی که در آن نمایش داده شود، آمادهاید تا با برنامهتان شروع به ضبط تصاویر کنید. در کد برنامهتان، باید شنوندگانی را برای کنترلهای میانای کاربرتان تنظیم کنید تا با گرفتن عکس به کنش کاربر پاسخ دهند.
برای بازیابی تصویر، از روش 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 تمام شد، آن را با فراخوانی Camera.release() آزاد کنید! برای کسب اطلاعات درباره نحوه رها کردن دوربین، به رها کردن دوربین مراجعه کنید.
گرفتن ویدیو
ضبط ویدیو بااستفاده از چارچوب Android مستلزم مدیریت دقیق شیء Camera و هماهنگی با کلاس MediaRecorder است. هنگام ضبط ویدیو با Camera، باید تماسهای Camera.lock() و Camera.unlock() را مدیریت کنید تا به MediaRecorder اجازه دهید به سختافزار دوربین دسترسی داشته باشد،
علاوهبر تماسهای Camera.open() و Camera.release().
توجه: از Android 4.0 (سطح API ۱۴) به بعد، تماسهای Camera.lock() و Camera.unlock() بهطور خودکار برای شما مدیریت میشوند.
برخلاف عکس گرفتن با دوربین دستگاه، ضبط ویدیو به ترتیب فراخوانی بسیار خاصی نیاز دارد. برای آمادهسازی و ضبط موفقیتآمیز ویدیو با برنامهتان، باید ترتیب اجرای خاصی را دنبال کنید، همانطور که در زیر بهطور مفصل توضیح داده شده است.
- باز کردن دوربین - از
Camera.open()برای دریافت نمونهای از شیء دوربین استفاده کنید. - پیشنمایش اتصال - با متصل کردن
SurfaceViewبه دوربین بااستفاده ازCamera.setPreviewDisplay()، پیشنمایش تصویر دوربین زنده را آماده کنید. - شروع پیشنمایش - با
Camera.startPreview()تماس بگیرید تا نمایش تصاویر زنده دوربین شروع شود. - شروع ضبط ویدیو - مراحل زیر باید بهترتیب تکمیل شوند تا ویدیو با موفقیت ضبط شود:
- باز کردن قفل دوربین - قفل دوربین را برای استفاده
MediaRecorderبا فراخوانیCamera.unlock()باز کنید. - پیکربندی MediaRecorder - روشهای
MediaRecorderزیر را به این ترتیب فراخوانی کنید. برای اطلاعات بیشتر، به اسناد مرجعMediaRecorderمراجعه کنید.setCamera()- دوربین را برای استفاده در ضبط ویدیو تنظیم کنید، از نمونه فعلی برنامهCameraاستفاده کنید.setAudioSource()- تنظیم منبع صوتی، ازMediaRecorder.AudioSource.CAMCORDERاستفاده کنید.setVideoSource()- Set the video source, useMediaRecorder.VideoSource.CAMERA.- قالب و کدبندی خروجی ویدیو را تنظیم کنید. برای Android 2.2 (سطح میانای برنامهسازی کاربردی ۸) و
بالاتر، از روش
MediaRecorder.setProfileاستفاده کنید و بااستفاده ازCamcorderProfile.get()، نمونه نمایه دریافت کنید. برای نسخههای Android قبل از 2.2، باید قالب خروجی ویدیو و پارامترهای کدبندی را تنظیم کنید:setOutputFormat()- قالب خروجی را تنظیم کنید، تنظیم پیشفرض یاMediaRecorder.OutputFormat.MPEG_4را مشخص کنید.setAudioEncoder()- نوع کدبندی صدا را تنظیم کنید، تنظیم پیشفرض یاMediaRecorder.AudioEncoder.AMR_NBرا مشخص کنید.setVideoEncoder()- نوع کدبندی ویدیو را تنظیم کنید، تنظیم پیشفرض یاMediaRecorder.VideoEncoder.MPEG_4_SPرا مشخص کنید.
setOutputFile()- فایل خروجی را تنظیم کنید، ازgetOutputMediaFile(MEDIA_TYPE_VIDEO).toString()در روش نمونه در بخش ذخیره کردن فایلهای رسانهای استفاده کنید.setPreviewDisplay()- عنصر چیدمان پیشنمایشSurfaceViewرا برای برنامهتان مشخص کنید. از همان شیئی استفاده کنید که برای پیشنمایش اتصال مشخص کردهاید.
احتیاط: باید این
MediaRecorderروشهای پیکربندی را به این ترتیب فراخوانی کنید، درغیراینصورت برنامه شما با خطا مواجه میشود و ضبط انجام نمیشود. - آمادهسازی MediaRecorder -
MediaRecorderرا با تنظیمات پیکربندی ارائهشده با فراخوانیMediaRecorder.prepare()آماده کنید. - شروع MediaRecorder - ضبط ویدیو را با فراخوانی
MediaRecorder.start()شروع کنید.
- باز کردن قفل دوربین - قفل دوربین را برای استفاده
- توقف ضبط ویدیو - برای تکمیل موفقیتآمیز ضبط ویدیو، روشهای زیر را بهترتیب فراخوانی کنید:
- توقف MediaRecorder - توقف ضبط ویدیو با فراخوانی
MediaRecorder.stop(). - بازنشانی MediaRecorder - درصورت تمایل، با فراخوانی
MediaRecorder.reset()، تنظیمات پیکربندی را از ضبطکننده بردارید. - Release MediaRecorder - Release the
MediaRecorderby callingMediaRecorder.release(). - قفل کردن دوربین - دوربین را قفل کنید تا جلسههای
MediaRecorderآینده بتوانند با فراخوانیCamera.lock()از آن استفاده کنند. از Android 4.0 (سطح API ۱۴) به بعد، این فراخوانی لازم نیست مگراینکهMediaRecorder.prepare()فراخوانی ناموفق باشد.
- توقف MediaRecorder - توقف ضبط ویدیو با فراخوانی
- متوقف کردن پیشنما - وقتی فعالیتتان استفاده از دوربین را تمام کرد، پیشنما را بااستفاده از
Camera.stopPreview()متوقف کنید. - Release Camera - Release the camera so that other applications can use
it by calling
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 (میانای برنامهسازی کاربردی سطح ۸)، باید پارامترهای قالب خروجی و قالبهای کدبندی را
مستقیماً تنظیم کنید، بهجای اینکه از 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()
به کد نمونه نشاندادهشده در پیکربندی 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 (سطح میانای برنامهسازی کاربردی ۸) دردسترس است، برای تماسهای معادل در نسخههای قبلی میانای برنامهسازی کاربردی، به ذخیره کردن فایلهای مشترک مراجعه کنید.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() در Android نسخه ۲.۲ (سطح میانای برنامهسازی کاربردی ۸) یا بالاتر دردسترس است. اگر دستگاههای دارای نسخههای قدیمیتر Android را هدفیابی میکنید، بهجای آن از Environment.getExternalStorageDirectory()
استفاده کنید. برای اطلاعات بیشتر، به ذخیره کردن فایلهای همرسانیشده مراجعه کنید.
برای اینکه URI از نمایه کاری پشتیبانی کند، ابتدا
URI فایل را به URI محتوا تبدیل کنید. سپس، شناسه منبع یکسان محتوا را به
EXTRA_OUTPUT
Intent اضافه کنید.
برای اطلاعات بیشتر درباره ذخیره کردن فایلها در دستگاه Android، به ذخیرهسازی داده مراجعه کنید.
ویژگیهای دوربین
Android از طیف گستردهای از ویژگیهای دوربین پشتیبانی میکند که میتوانید آنها را با برنامه دوربینتان کنترل کنید،
ازجمله قالب تصویر، حالت فلاش، تنظیمات فوکوس، و موارد دیگر. این بخش ویژگیهای رایج دوربین را فهرست میکند و بهطور خلاصه نحوه استفاده از آنها را شرح میدهد. اکثر ویژگیهای دوربین را میتوان بااستفاده از شیء Camera.Parameters
دسترسی و تنظیم کرد. بااینحال، چندین ویژگی مهم وجود دارد که به چیزی بیشتر از تنظیمات ساده در Camera.Parameters نیاز دارد. این ویژگیها در بخشهای زیر پوشش داده شدهاند:
برای اطلاعات کلی درباره نحوه استفاده از ویژگیهایی که ازطریق Camera.Parameters کنترل میشوند، بخش استفاده از ویژگیهای دوربین را مرور کنید. برای اطلاعات دقیقتر درباره نحوه استفاده از ویژگیهای کنترلشده ازطریق
شیء پارامترهای دوربین، پیوندهای موجود در فهرست ویژگیهای زیر را به سند مرجع
میانای برنامهسازی کاربردی دنبال کنید.
جدول ۱. ویژگیهای رایج دوربین براساس سطح میانای برنامهسازی کاربردی Android که در آن معرفی شدهاند مرتب شدهاند.
| ویژگی | سطح ایپیآی | شرح |
|---|---|---|
| تشخیص چهره | 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 14) به بعد، جهت پیشنمایش را میتوان بدون بازراهاندازی پیشنمایش تغییر داد.
سایر ویژگیهای دوربین برای پیادهسازی به کد بیشتری نیاز دارند، ازجمله:
- نواحی نورسنجی و فوکوس
- تشخیص چهره
- ویدیوِ زمانگریز
در بخشهای زیر، طرح کلی سریعی از نحوه پیادهسازی این ویژگیها ارائه شده است.
نواحی نورسنجی و فوکوس
در برخیاز سناریوهای عکاسی، فوکوس خودکار و نورسنجی ممکن است نتایج مطلوب را بههمراه نداشته باشد. از Android نسخه ۴.۰ (سطح میانای برنامهسازی کاربردی ۱۴) به بعد، برنامه دوربین شما میتواند کنترلهای بیشتری ارائه دهد تا به برنامه یا کاربران شما اجازه دهد نواحیای را در تصویر مشخص کنند تا برای تعیین تنظیمات سطح نور یا فوکوس استفاده شود و این مقادیر را به سختافزار دوربین منتقل کند تا برای ضبط تصاویر یا ویدیو استفاده شود.
نواحی نورسنجی و فوکوس بسیار شبیه به دیگر ویژگیهای دوربین کار میکنند، از این جهت که شما آنها را ازطریق روشهایی در شیء 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
شکل مستطیلی را توصیف میکند که روی شبکه واحد ۲۰۰۰ × ۲۰۰۰ نگاشت شده است. مختصات -۱۰۰۰، -۱۰۰۰
نشاندهنده گوشه بالا سمت چپ تصویر دوربین است و مختصات ۱۰۰۰، ۱۰۰۰ نشاندهنده
گوشه پایین سمت راست تصویر دوربین است، همانطور که در تصویر زیر نشان داده شده است.
شکل ۱. خطوط قرمز سیستم مختصات را برای مشخص کردن
Camera.Area در پیشنمایش دوربین نشان میدهد. کادر آبی مکان و شکل ناحیه دوربین را با مقادیر Rect 333,333,667,667 نشان میدهد.
حدود این سیستم مختصات همیشه با لبه بیرونی تصویر قابلمشاهده در پیشنمای دوربین مطابقت دارد و با سطح بزرگنمایی کوچک یا بزرگ نمیشود. بهطور مشابه، چرخش پیشنمایش تصویر
بااستفاده از Camera.setDisplayOrientation()
سیستم مختصات را بازنگاشت نمیکند.
تشخیص چهره
برای عکسهایی که شامل افراد هستند، چهرهها معمولاً مهمترین بخش تصویر هستند و باید برای تعیین فوکوس و توازن سفیدی هنگام ثبت تصویر استفاده شوند. چارچوب Android 4.0 (سطح میانای برنامهسازی کاربردی ۱۴) میاناهای برنامهسازی کاربردیای برای شناسایی چهرهها و محاسبه تنظیمات تصویر بااستفاده از فناوری تشخیص چهره ارائه میدهد.
توجه: وقتی ویژگی تشخیص چهره درحال اجرا است،
setWhiteBalance(String)،
setFocusAreas(List<Camera.Area>) و
setMeteringAreas(List<Camera.Area>) تأثیری ندارند.
استفاده از ویژگی تشخیص چهره در برنامه دوربین چند مرحله کلی دارد:
- بررسی کنید که تشخیص چهره در دستگاه پشتیبانی میشود
- ایجاد شنونده تشخیص چهره
- شنونده تشخیص چهره را به شیء دوربین اضافه کنید
- شروع تشخیص چهره پساز پیشنمایش (و پساز هر بازراهاندازی پیشنمایش)
ویژگی تشخیص چهره در همه دستگاهها پشتیبانی نمیشود. با تماس با getMaxNumDetectedFaces() میتوانید بررسی کنید که این ویژگی پشتیبانی میشود یا نه. نمونهای از این بررسی در روش نمونه startFaceDetection() در زیر نشان داده شده است.
In order to be notified and respond to the detection of a face, your camera application must set
a listener for face detection events. برای انجام این کار، باید کلاس شنوندهای ایجاد کنید که
رابط 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() فعالیت اصلی برنامه دوربینتان،
برای شروع تشخیص چهره تلاش نکنید،
زیرا پیشنمایش در این مرحله از اجرای برنامه دردسترس نیست.
ویدیوِ زمانگریز
ویدیو زمانگریز به کاربران امکان میدهد کلیپهای ویدیویی ایجاد کنند که عکسهای گرفتهشده با فاصله چند ثانیه یا چند دقیقه را ترکیب میکند. این ویژگی از 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 استفاده از میاناهای برنامهسازی کاربردی پوششدادهشده در این صفحه را بیشتر نشان میدهند.
فیلدهای دوربین که به اجازه نیاز دارند
برنامههایی که Android نسخه ۱۰ (سطح میانای برنامهسازی کاربردی ۲۹) یا بالاتر را اجرا میکنند باید اجازه
CAMERA را داشته باشند تا بتوانند
به مقادیر فیلدهای زیر که روش
getCameraCharacteristics()
برمیگرداند دسترسی داشته باشند:
LENS_POSE_ROTATIONLENS_POSE_TRANSLATIONLENS_INTRINSIC_CALIBRATIONLENS_RADIAL_DISTORTIONLENS_POSE_REFERENCELENS_DISTORTIONLENS_INFO_HYPERFOCAL_DISTANCELENS_INFO_MINIMUM_FOCUS_DISTANCESENSOR_REFERENCE_ILLUMINANT1SENSOR_REFERENCE_ILLUMINANT2SENSOR_CALIBRATION_TRANSFORM1SENSOR_CALIBRATION_TRANSFORM2SENSOR_COLOR_TRANSFORM1SENSOR_COLOR_TRANSFORM2SENSOR_FORWARD_MATRIX1SENSOR_FORWARD_MATRIX2
کدگذاری نمونه بیشتر
برای بارگیری برنامههای نمونه، نمونه Camera2Basic و برنامه نمونه رسمی CameraX را ببینید.