讓您的相機支援多螢幕預覽,同步更新。
最近有個專案做刷臉人證識別機器,有主屏和客顯屏兩個螢幕。在人臉識別的時候,主屏和客顯屏都需要展示相機資料。開始專案使用的Camera,找了好多方法都沒有搞定這個需求,最後在強大的搜尋引擎和api2的引領下使用Camera2解決了此問題。
特此記錄。
一、Camera2簡介
Camera2是Google在Android 5.0後推出的一個全新的相機API,Camera2和Camera沒有繼承關係,是完全重新設計的,且Camera2支援的功能也更加豐富,但是提供了更豐富的功能的同時也增加了使用的難度。Google的官方Demo:https://github.com/googlesamples/android-Camera2Basic
二、Camera2 VS Camera
以下分別是使用Camera2和Camera開啟相機進行預覽並獲取預覽資料的流程圖。
可以看到,和Camera相比,Camera2的呼叫明顯複雜得多,但同時也提供了更強大的功能:
- 支援在非UI執行緒獲取預覽資料
- 可以獲取更多的預覽幀
- 對相機的控制更加完備
- 支援更多格式的預覽資料
- 支援高速連拍
但是具體能否使用還要看裝置的廠商有無實現。
三、如何支援多個螢幕或者View展示同一相機資料(不瞭解Camera2的同學請先檢視下資料)
1. 直接上乾貨,先看佈局檔案,其中texture、texture2是基於TextureView的兩個用來展示資料的:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="300dp"
android:orientation="horizontal">
<com.lm.camerademo.AutoFitTextureView
android:id="@+id/texture"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="fill_parent" />
<com.lm.camerademo.AutoFitTextureView
android:id="@+id/texture2"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_marginLeft="5dp"
android:layout_height="fill_parent" />
</LinearLayout>
<FrameLayout
android:id="@+id/control"
android:layout_width="match_parent"
android:layout_height="112dp"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:visibility="visible">
<Button
android:id="@+id/picture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="visible"
android:text="拍照" />
<ImageButton
android:id="@+id/info"
android:contentDescription="描述"
style="@android:style/Widget.Material.Light.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible"
android:layout_gravity="center_vertical|right"
android:padding="20dp"
android:src="@mipmap/ic_launcher" />
</FrameLayout>
</RelativeLayout>
2. 首先不要忘記許可權
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
3. 接下來就是Camera2的使用了。使用流程。
- 通過
context.getSystemService(Context.CAMERA_SERVICE)
獲取CameraManager
. - 呼叫
CameraManager .open()
方法在回撥中得到CameraDevice
. - 通過
CameraDevice.createCaptureSession()
在回撥中獲取CameraCaptureSession
. - 構建
CaptureRequest
, 有三種模式可選 預覽/拍照/錄影. - 通過
CameraCaptureSession
傳送CaptureRequest
, capture表示只發一次請求, setRepeatingRequest表示不斷髮送請求. - 拍照資料可以在
ImageReader.OnImageAvailableListener
回撥中獲取,CaptureCallback
中則可獲取拍照實際的引數和Camera當前狀態.
上程式碼開啟攝像頭,其中mCameraId是攝像頭ID一般就是前後兩個攝像頭,stateCallBack是個相機狀態的監聽:
// 開啟攝像頭
private void openCamera(int width, int height) {
setUpCameraOutputs(width, height);
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
// 開啟攝像頭
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
return;
}
manager.openCamera(mCameraId, stateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
// 攝像頭被開啟時激發該方法
@Override
public void onOpened(CameraDevice cameraDevice) {
MainActivity.this.cameraDevice = cameraDevice;
// 開始預覽
createCameraPreviewSession();
}
// 攝像頭斷開連線時激發該方法
@Override
public void onDisconnected(CameraDevice cameraDevice) {
cameraDevice.close();
MainActivity.this.cameraDevice = null;
}
// 開啟攝像頭出現錯誤時激發該方法
@Override
public void onError(CameraDevice cameraDevice, int error) {
cameraDevice.close();
MainActivity.this.cameraDevice = null;
MainActivity.this.finish();
}
};
重點來了,我們在createCameraPreviewSession的設定展示的資料繫結介面。
private void createCameraPreviewSession() {
try {
SurfaceTexture texture = autoCompleteTextView.getSurfaceTexture();
SurfaceTexture texture2 = autoCompleteTextView2.getSurfaceTexture();
texture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
texture2.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
Surface surface = new Surface(texture);
Surface surface2 = new Surface(texture2);
// 建立作為預覽的CaptureRequest.Builder
previewRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
// 將textureView的surface作為CaptureRequest.Builder的目標
previewRequestBuilder.addTarget(surface);
previewRequestBuilder.addTarget(surface2);
previewRequestBuilder.addTarget(imageReader.getSurface());
// 建立CameraCaptureSession,該物件負責管理處理預覽請求和拍照請求
cameraDevice.createCaptureSession(Arrays.asList(surface, surface2, imageReader.getSurface()), new CameraCaptureSession.StateCallback()
{
@Override
public void onConfigured(CameraCaptureSession cameraCaptureSession) {
// 如果攝像頭為null,直接結束方法
if (null == cameraDevice) {
return;
}
// 當攝像頭已經準備好時,開始顯示預覽
captureSession = cameraCaptureSession;
try {
// 設定自動對焦模式
previewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
// 設定自動曝光模式
previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
// 開始顯示相機預覽
previewRequest = previewRequestBuilder.build();
// 設定預覽時連續捕獲影像資料
captureSession.setRepeatingRequest(previewRequest,
null, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
Toast.makeText(MainActivity.this, "配置失敗!"
, Toast.LENGTH_SHORT).show();
}
}, null
);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
這樣就完成了預覽資料輸出到兩個surfaceview上面。上張圖片。
DEMO傳送門
相關文章
- Android Fragment生命週期——多螢幕支援AndroidFragment
- 讓你的應用支援新iPad的Retina螢幕iPad
- win10預覽版Skype UWP更新:帶來單應用螢幕分享功能Win10
- 如何讓您的php也支援pthreads多執行緒PHPthread執行緒
- 多螢幕切換
- Flutter之支援不同的螢幕尺寸和方向Flutter
- 讓大模型理解手機螢幕,蘋果多模態Ferret-UI用自然語言操控手機大模型蘋果UI
- 使用瀏覽器錄製螢幕瀏覽器
- 螢幕顯示機制
- iOS支援螢幕方向問題說明iOS
- 保護您的Flutter應用程式:實現隱私螢幕Flutter
- Win10怎麼讓電腦螢幕變黑而不關機 膝上型電腦如何關螢幕不關機Win10
- Mac 多螢幕視窗管理神器Mac
- iOS開發之使用Storyboard預覽UI在不同螢幕上執行效果iOSUI
- LayUI多檔案上傳,支援歷史上傳預覽UI
- 使用 Finder預覽功能,讓你可以快速瀏覽多個檔案!
- win10 如何去掉待機螢幕 win10去掉待機螢幕方法Win10
- js獲取div相對螢幕的座標位置JS
- 支援多檔案上傳,預覽,拖拽,基於bootstrap的上傳外掛fileinput的ajax非同步上傳boot非同步
- YouGov:研究顯示多螢幕為廣告商帶來機會Go
- 讓您的應用支援新式的 Emoji 符號吧!符號
- Deskreen 1.0.2 –將電腦螢幕共享到瀏覽器中,做第二塊螢幕瀏覽器
- 迴歸小螢幕手機 蘋果下代新品或配4寸螢幕蘋果
- 多點觸控式螢幕驅動
- 支援多視窗 Android N預覽版映象公佈Android
- Millward Brown :預測2015年第二螢幕同步廣告將迅猛發展
- [外掛擴充套件]左右markdown編輯器0.2(更新同步預覽)套件
- 徠卡釋出沒螢幕的M10-D相機 將極簡進行到底
- JavaScript獲取瀏覽器、元素、螢幕的寬高尺寸JavaScript瀏覽器
- iOS 手機螢幕手勢鎖iOS
- WebRTC本地分享螢幕,錄製螢幕Web
- CSS 讓捲軸不佔用螢幕寬度CSS
- 讓應用程式禁止Windows螢幕保護 (轉)Windows
- 國產OLED螢幕被認可,蘋果讓京東方獲得iPhone供應螢幕資格蘋果iPhone
- iQOO手機怎麼設定捂住螢幕靜音?iQOO手機捂住螢幕靜音的設定方法
- Vue.js@2.6.10更新內建錯誤處機制,Fundebug同步支援相應錯誤監控Vue.js
- 微軟將公佈Win10手機預覽版支援機型微軟Win10
- 如何將 MacBook 的外接螢幕設定為主螢幕的方法Mac