亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

Android Camera2 實現預覽功能

2019-10-21 21:35:41
字體:
來源:轉載
供稿:網友

1. 概述

最近在做一些關于人臉識別的項目,需要用到 Android 相機的預覽功能。網上查閱相關資料后,發現 Android 5.0 及以后的版本中,原有的 Camera API 已經被 Camera2 API 所取代。

全新的 Camera2 在 Camera 的基礎上進行了改造,大幅提升了 Android 系統的拍照功能。它通過以下幾個類與方法來實現相機預覽時的工作過程:

•CameraManager :攝像頭管理器,主要用于檢測系統攝像頭、打開系統攝像頭等;
•CameraDevice : 用于描述系統攝像頭,可用于關閉相機、創建相機會話、發送拍照請求等;
•CameraCharacteristics :用于描述攝像頭所支持的各種特性;
•CameraCaptureSession :當程序需要預覽、拍照時,都需要先通過 CameraCaptureSession 來實現。該會話通過調用方法 setRepeatingRequest() 實現預覽;
•CameraRequest :代表一次捕獲請求,用于描述捕獲圖片的各種參數設置;
•CameraRequest.Builder :負責生成 CameraRequest 對象。

2. 相機預覽

下面通過源碼來講解如何使用 Camera2 來實現相機的預覽功能。

2.1 相機權限設置

<uses-permission android:name="android.permission.CAMERA" />

2.2 App 布局

•activity_main.xml

<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#000" tools:context=".MainActivity"></FrameLayout>•fragment_camera.xml<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".CameraFragment"> <com.lightweh.camera2preview.AutoFitTextureView android:id="@+id/textureView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_centerHorizontal="true" /></RelativeLayout>

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 < height * mRatioWidth / mRatioHeight) { setMeasuredDimension(width, width * mRatioHeight / mRatioWidth); } else { setMeasuredDimension(height * mRatioWidth / mRatioHeight, height); } } }}

2.4 動態申請相機權限

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); } } // 權限判斷,當系統版本大于23時,才有必要判斷是否獲取權限 private boolean hasPermission() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { return checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED; } else { return true; } } // 請求相機權限 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 開啟相機預覽

首先,在onResume()中,我們需要開啟一個 HandlerThread,然后利用該線程的 Looper 對象構建一個 Handler 用于相機回調。

@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() 中有對應的 HandlerThread 關閉方法。

當屏幕關閉后重新開啟,SurfaceTexture 已經就緒,此時不會觸發 onSurfaceTextureAvailable 回調。因此,我們判斷 mTextureView 如果可用,則直接打開相機,否則等待 SurfaceTexture 回調就緒后再開啟相機。

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); }}

開啟相機時,我們首先判斷是否具備相機權限,然后調用 setUpCameraOutputs 函數對相機參數進行設置(包括指定攝像頭、相機預覽方向以及預覽尺寸的設定等),接下來調用 configureTransform 函數對預覽圖片的大小和方向進行調整,最后獲取 CameraManager 對象開啟相機。因為相機有可能會被其他進程同時訪問,所以在開啟相機時需要加鎖。

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(); } }};

相機開啟時還會指定相機的狀態變化回調函數 mStateCallback,如果相機成功開啟,則開始創建相機預覽會話。

private void createCameraPreviewSession() { try { // 獲取 texture 實例 SurfaceTexture texture = mTextureView.getSurfaceTexture(); assert texture != null; // 設置 TextureView 緩沖區大小 texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); // 獲取 Surface 顯示預覽數據 Surface surface = new Surface(texture); // 構建適合相機預覽的請求 mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); // 設置 surface 作為預覽數據的顯示界面 mPreviewRequestBuilder.addTarget(surface); // 創建相機捕獲會話用于預覽 mCameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {  @Override  public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {  // 如果相機關閉則返回  if (null == mCameraDevice) {  return;  }  // 如果會話準備好則開啟預覽  mCaptureSession = cameraCaptureSession;  try {  // 自動對焦  mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,   CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);  mPreviewRequest = mPreviewRequestBuilder.build();  // 設置反復捕獲數據的請求,預覽界面一直顯示畫面  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 實現相機預覽的主要過程。

3. Demo 源碼

Github:Camera2Preview

4. 參考

• https://github.com/googlesamples/android-Camera2Basic   

總結

以上所述是小編給大家介紹的Android Camera2 實現預覽功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對VEVB武林網網站的支持!


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲精品99久久久久| 亚洲成人黄色在线| 亚洲国产精彩中文乱码av在线播放| 久久久久久久久久久免费| 国产福利成人在线| 色综合久久久888| 国产精品视频久久| 日韩欧美在线国产| 日韩中文字幕免费视频| 日韩欧美999| 亚洲精品有码在线| 欧美一级免费看| 欧美黑人狂野猛交老妇| 国产精品99久久久久久白浆小说| 成人性生交大片免费观看嘿嘿视频| 久久中文字幕一区| 永久555www成人免费| 亚州国产精品久久久| 亚洲欧洲xxxx| 亚洲一区二区三区xxx视频| 日韩视频在线观看免费| 精品人伦一区二区三区蜜桃免费| 色老头一区二区三区| 国内精品久久久久伊人av| 国产在线视频不卡| 久久精品国产亚洲7777| 黄色成人av网| 国产精品综合不卡av| 亚洲japanese制服美女| 亚洲精品免费一区二区三区| 激情亚洲一区二区三区四区| 日韩国产精品亚洲а∨天堂免| 日韩美女在线播放| 伊人激情综合网| 在线精品国产欧美| 亚洲第一福利在线观看| 久久久国产精彩视频美女艺术照福利| 国产精品视频yy9099| 亚洲欧美成人网| 日韩av中文字幕在线免费观看| 亚洲人成亚洲人成在线观看| 在线精品国产成人综合| 国产精品久久一| 人体精品一二三区| 国产aⅴ夜夜欢一区二区三区| 色综合导航网站| 国产精品观看在线亚洲人成网| 91色中文字幕| 色妞在线综合亚洲欧美| 精品久久久国产精品999| 国产成人极品视频| 国产日韩欧美91| 色播久久人人爽人人爽人人片视av| 久热99视频在线观看| 久久久久久一区二区三区| 国产精品草莓在线免费观看| 97高清免费视频| 欧美在线视频免费播放| 中文日韩在线观看| 国产69精品久久久久9999| 久久精品视频在线| 国产精品男女猛烈高潮激情| 久久福利视频网| 欧美一级大片在线免费观看| xxxx欧美18另类的高清| 久久综合伊人77777尤物| 国产精品久久久久久亚洲调教| 欧美日韩在线一区| 色婷婷久久一区二区| 国外视频精品毛片| 1769国内精品视频在线播放| 亚洲第一色中文字幕| 一区二区欧美激情| 中文字幕久精品免费视频| 国产大片精品免费永久看nba| 精品国产91久久久久久老师| 91精品在线观看视频| 久久久久久九九九| 亚洲成人精品视频| 日韩精品中文字幕在线观看| 91精品视频播放| 91超碰中文字幕久久精品| 亚洲男人av电影| 亚洲字幕一区二区| 亚洲日本中文字幕免费在线不卡| 亚洲999一在线观看www| 亚洲午夜激情免费视频| 91国产精品电影| 欧美成人激情在线| 国产91|九色| 国产日产亚洲精品| 7777kkkk成人观看| 成人精品久久一区二区三区| 欧美精品免费在线| 精品久久久久久亚洲国产300| 免费av在线一区| 国产亚洲成av人片在线观看桃| 97欧美精品一区二区三区| 欧美猛男性生活免费| 亚洲电影免费观看高清完整版在线| 国产主播在线一区| 亚洲精品视频二区| 欧美日韩亚洲视频一区| 久久视频这里只有精品| 黄色一区二区在线观看| 成人精品久久av网站| 九九久久久久99精品| 久久久精品在线| 97人人模人人爽人人喊中文字| 欧美亚洲成人xxx| 国产精品jvid在线观看蜜臀| 亚洲人成网站999久久久综合| 国产精品91一区| 亚洲图片欧洲图片av| 色综合91久久精品中文字幕| 清纯唯美亚洲综合| 亚洲精品电影网站| 性视频1819p久久| 亚洲国产一区二区三区四区| 九九精品在线播放| 国产精品久久久久久久久免费看| 久久亚洲影音av资源网| 欧美国产高跟鞋裸体秀xxxhd| 久久精品久久精品亚洲人| 日韩小视频网址| 欧美丝袜一区二区三区| 色综合久久88色综合天天看泰| 亚洲视频网站在线观看| 久久成人18免费网站| 亚洲一区二区三区毛片| 欧美激情综合色综合啪啪五月| 久久久这里只有精品视频| 国产区亚洲区欧美区| 国产噜噜噜噜噜久久久久久久久| 亚洲人成电影网站色…| 亚洲天天在线日亚洲洲精| 成人h视频在线| 久久久人成影片一区二区三区观看| 国产亚洲精品久久| 亚洲男女性事视频| 国产成人免费av| 亚洲精品720p| 亚洲欧洲激情在线| 久久久精品国产一区二区| 久久中国妇女中文字幕| 伊人成人开心激情综合网| 亚洲在线免费观看| 欧美中文字幕视频在线观看| 亚洲国产精品电影| 亚洲毛片在线看| 国产精品视频地址| 欧美亚洲国产视频小说| 国产精品第三页| 国产视频在线观看一区二区| 亚洲国产小视频| 欧美亚洲视频在线看网址| 国产精品美女网站| 亚洲性av在线| 青青草一区二区| 国产精品美腿一区在线看| 亚洲视频在线免费观看| 国产精品极品美女在线观看免费| 亚洲国产精品专区久久| 国产精品久久久久久久天堂|