1. 概述
慈利網(wǎng)站建設(shè)公司成都創(chuàng)新互聯(lián),慈利網(wǎng)站設(shè)計制作,有大型網(wǎng)站制作公司豐富經(jīng)驗。已為慈利成百上千提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)網(wǎng)站建設(shè)要多少錢,請找那個售后服務(wù)好的慈利做網(wǎng)站的公司定做!最近在做一些關(guān)于人臉識別的項目,需要用到 Android 相機的預(yù)覽功能。網(wǎng)上查閱相關(guān)資料后,發(fā)現(xiàn) Android 5.0 及以后的版本中,原有的 Camera API 已經(jīng)被 Camera2 API 所取代。
全新的 Camera2 在 Camera 的基礎(chǔ)上進(jìn)行了改造,大幅提升了 Android 系統(tǒng)的拍照功能。它通過以下幾個類與方法來實現(xiàn)相機預(yù)覽時的工作過程:
?CameraManager :攝像頭管理器,主要用于檢測系統(tǒng)攝像頭、打開系統(tǒng)攝像頭等;
?CameraDevice : 用于描述系統(tǒng)攝像頭,可用于關(guān)閉相機、創(chuàng)建相機會話、發(fā)送拍照請求等;
?CameraCharacteristics :用于描述攝像頭所支持的各種特性;
?CameraCaptureSession :當(dāng)程序需要預(yù)覽、拍照時,都需要先通過 CameraCaptureSession 來實現(xiàn)。該會話通過調(diào)用方法 setRepeatingRequest() 實現(xiàn)預(yù)覽;
?CameraRequest :代表一次捕獲請求,用于描述捕獲圖片的各種參數(shù)設(shè)置;
?CameraRequest.Builder :負(fù)責(zé)生成 CameraRequest 對象。
2. 相機預(yù)覽
下面通過源碼來講解如何使用 Camera2 來實現(xiàn)相機的預(yù)覽功能。
2.1 相機權(quán)限設(shè)置
2.2 App 布局
?activity_main.xml
?fragment_camera.xml ?
2.3 相機自定義View
public?class?AutoFitTextureView?extends?TextureView?{?private?int?mRatioWidth?=?0;?private?int?mRatioHeight?=?0;?public?AutoFitTextureView(Context?context)?{?this(context,?null); ?}?public?AutoFitTextureView(Context?context,?AttributeSet?attrs)?{?this(context,?attrs,?0); ?}?public?AutoFitTextureView(Context?context,?AttributeSet?attrs,?int?defStyle)?{?super(context,?attrs,?defStyle); ?}?public?void?setAspectRatio(int?width,?int?height)?{?if?(width?0?||?height?0)?{?throw?new?IllegalArgumentException("Size?cannot?be?negative."); ?} ?mRatioWidth?=?width; ?mRatioHeight?=?height; ?requestLayout(); ?}?@Override ?protected?void?onMeasure(int?widthMeasureSpec,?int?heightMeasureSpec)?{?super.onMeasure(widthMeasureSpec,?heightMeasureSpec);?int?width?=?MeasureSpec.getSize(widthMeasureSpec);?int?height?=?MeasureSpec.getSize(heightMeasureSpec);?if?(0?==?mRatioWidth?||?0?==?mRatioHeight)?{ ?setMeasuredDimension(width,?height); ?}?else?{?if?(width?2.4 動態(tài)申請相機權(quán)限
public?class?MainActivity?extends?AppCompatActivity?{?private?static?final?int?REQUEST_PERMISSION?=?1;?@Override ?protected?void?onCreate(Bundle?savedInstanceState)?{?super.onCreate(savedInstanceState); ?setContentView(R.layout.activity_main);?if?(hasPermission())?{?if?(null?==?savedInstanceState)?{ ?setFragment(); ?} ?}?else?{ ?requestPermission(); ?} ?}?@Override ?public?void?onRequestPermissionsResult(int?requestCode,?String?permissions[],?int[]?grantResults)?{?if?(requestCode?==?REQUEST_PERMISSION)?{?if?(grantResults.length?==?1?&&?grantResults[0]?==?PackageManager.PERMISSION_GRANTED)?{ ?setFragment(); ?}?else?{ ?requestPermission(); ?} ?}?else?{?super.onRequestPermissionsResult(requestCode,?permissions,?grantResults); ?} ?}?//?權(quán)限判斷,當(dāng)系統(tǒng)版本大于23時,才有必要判斷是否獲取權(quán)限 ?private?boolean?hasPermission()?{?if?(Build.VERSION.SDK_INT?>=?Build.VERSION_CODES.M)?{?return?checkSelfPermission(Manifest.permission.CAMERA)?==?PackageManager.PERMISSION_GRANTED; ?}?else?{?return?true; ?} ?}?//?請求相機權(quán)限 ?private?void?requestPermission()?{?if?(Build.VERSION.SDK_INT?>=?Build.VERSION_CODES.M)?{?if?(shouldShowRequestPermissionRationale(Manifest.permission.CAMERA))?{ ?Toast.makeText(MainActivity.this,?"Camera?permission?are?required?for?this?demo",?Toast.LENGTH_LONG).show(); ?} ?requestPermissions(new?String[]{Manifest.permission.CAMERA},?REQUEST_PERMISSION); ?} ?}?//?啟動相機Fragment ?private?void?setFragment()?{ ?getSupportFragmentManager() ?.beginTransaction() ?.replace(R.id.container,?CameraFragment.newInstance()) ?.commitNowAllowingStateLoss(); ?} }2.5 開啟相機預(yù)覽
首先,在onResume()中,我們需要開啟一個 HandlerThread,然后利用該線程的 Looper 對象構(gòu)建一個 Handler 用于相機回調(diào)。
@Overridepublic?void?onResume()?{?super.onResume(); ?startBackgroundThread();?//?When?the?screen?is?turned?off?and?turned?back?on,?the?SurfaceTexture?is? ?//?already?available,?and?"onSurfaceTextureAvailable"?will?not?be?called.?In? ?//?that?case,?we?can?open?a?camera?and?start?preview?from?here?(otherwise,?we? ?//?wait?until?the?surface?is?ready?in?the?SurfaceTextureListener). ?if?(mTextureView.isAvailable())?{ ?openCamera(mTextureView.getWidth(),?mTextureView.getHeight()); ?}?else?{ ?mTextureView.setSurfaceTextureListener(mSurfaceTextureListener); ?} }private?void?startBackgroundThread()?{ ?mBackgroundThread?=?new?HandlerThread("CameraBackground"); ?mBackgroundThread.start(); ?mBackgroundHandler?=?new?Handler(mBackgroundThread.getLooper()); } 同時,在?onPause()?中有對應(yīng)的?HandlerThread?關(guān)閉方法。 當(dāng)屏幕關(guān)閉后重新開啟,SurfaceTexture?已經(jīng)就緒,此時不會觸發(fā)?onSurfaceTextureAvailable?回調(diào)。因此,我們判斷?mTextureView?如果可用,則直接打開相機,否則等待?SurfaceTexture?回調(diào)就緒后再開啟相機。private?void?openCamera(int?width,?int?height)?{?if?(ContextCompat.checkSelfPermission(getActivity(),?Manifest.permission.CAMERA) ?!=?PackageManager.PERMISSION_GRANTED)?{?return; ?} ?setUpCameraOutputs(width,?height); ?configureTransform(width,?height); ?Activity?activity?=?getActivity(); ?CameraManager?manager?=?(CameraManager)?activity.getSystemService(Context.CAMERA_SERVICE);?try?{?if?(!mCameraOpenCloseLock.tryAcquire(2500,?TimeUnit.MILLISECONDS))?{?throw?new?RuntimeException("Time?out?waiting?to?lock?camera?opening."); ?} ?manager.openCamera(mCameraId,?mStateCallback,?mBackgroundHandler); ?}?catch?(CameraAccessException?e)?{ ?e.printStackTrace(); ?}?catch?(InterruptedException?e)?{?throw?new?RuntimeException("Interrupted?while?trying?to?lock?camera?opening.",?e); ?} } 開啟相機時,我們首先判斷是否具備相機權(quán)限,然后調(diào)用?setUpCameraOutputs?函數(shù)對相機參數(shù)進(jìn)行設(shè)置(包括指定攝像頭、相機預(yù)覽方向以及預(yù)覽尺寸的設(shè)定等),接下來調(diào)用?configureTransform?函數(shù)對預(yù)覽圖片的大小和方向進(jìn)行調(diào)整,最后獲取?CameraManager?對象開啟相機。因為相機有可能會被其他進(jìn)程同時訪問,所以在開啟相機時需要加鎖。private?final?CameraDevice.StateCallback?mStateCallback?=?new?CameraDevice.StateCallback()?{?@Override ?public?void?onOpened(@NonNull?CameraDevice?cameraDevice)?{ ?mCameraOpenCloseLock.release(); ?mCameraDevice?=?cameraDevice; ?createCameraPreviewSession(); ?}?@Override ?public?void?onDisconnected(@NonNull?CameraDevice?cameraDevice)?{ ?mCameraOpenCloseLock.release(); ?cameraDevice.close(); ?mCameraDevice?=?null; ?}?@Override ?public?void?onError(@NonNull?CameraDevice?cameraDevice,?int?error)?{ ?mCameraOpenCloseLock.release(); ?cameraDevice.close(); ?mCameraDevice?=?null; ?Activity?activity?=?getActivity();?if?(null?!=?activity)?{ ?activity.finish(); ?} ?} };相機開啟時還會指定相機的狀態(tài)變化回調(diào)函數(shù) mStateCallback,如果相機成功開啟,則開始創(chuàng)建相機預(yù)覽會話。
private?void?createCameraPreviewSession()?{?try?{?//?獲取?texture?實例 ?SurfaceTexture?texture?=?mTextureView.getSurfaceTexture();?assert?texture?!=?null;?//?設(shè)置?TextureView?緩沖區(qū)大小 ?texture.setDefaultBufferSize(mPreviewSize.getWidth(),?mPreviewSize.getHeight());?//?獲取?Surface?顯示預(yù)覽數(shù)據(jù) ?Surface?surface?=?new?Surface(texture);?//?構(gòu)建適合相機預(yù)覽的請求 ?mPreviewRequestBuilder?=?mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);?//?設(shè)置?surface?作為預(yù)覽數(shù)據(jù)的顯示界面 ?mPreviewRequestBuilder.addTarget(surface);?//?創(chuàng)建相機捕獲會話用于預(yù)覽 ?mCameraDevice.createCaptureSession(Arrays.asList(surface),?new?CameraCaptureSession.StateCallback()?{??@Override ??public?void?onConfigured(@NonNull?CameraCaptureSession?cameraCaptureSession)?{??//?如果相機關(guān)閉則返回 ??if?(null?==?mCameraDevice)?{??return; ??}??//?如果會話準(zhǔn)備好則開啟預(yù)覽 ??mCaptureSession?=?cameraCaptureSession;??try?{??//?自動對焦 ??mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, ???CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); ??mPreviewRequest?=?mPreviewRequestBuilder.build();??//?設(shè)置反復(fù)捕獲數(shù)據(jù)的請求,預(yù)覽界面一直顯示畫面 ??mCaptureSession.setRepeatingRequest(mPreviewRequest,???null,?mBackgroundHandler); ??}?catch?(CameraAccessException?e)?{ ??e.printStackTrace(); ??} ??}??@Override ??public?void?onConfigureFailed( ??@NonNull?CameraCaptureSession?cameraCaptureSession)?{ ??showToast("Failed"); ??} ?},?null ?); ?}?catch?(CameraAccessException?e)?{ ?e.printStackTrace(); ?} }以上便是 Camera2 API 實現(xiàn)相機預(yù)覽的主要過程。有什么問題歡迎一起交流討論
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。
網(wǎng)站標(biāo)題:AndroidCamera2預(yù)覽功能實現(xiàn)-創(chuàng)新互聯(lián)
當(dāng)前網(wǎng)址:http://weahome.cn/article/dssehc.html