中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

AndroidCamera2怎么實(shí)現(xiàn)預(yù)覽功能-創(chuàng)新互聯(lián)

這篇文章主要介紹Android Camera2怎么實(shí)現(xiàn)預(yù)覽功能,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

創(chuàng)新互聯(lián)建站成立于2013年,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都做網(wǎng)站、網(wǎng)站制作網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢想脫穎而出為使命,1280元紅崗做網(wǎng)站,已為上家服務(wù),為紅崗各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:18982081108

1. 概述

最近在做一些關(guān)于人臉識(shí)別的項(xiàng)目,需要用到 Android 相機(jī)的預(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)的拍照功能。它通過以下幾個(gè)類與方法來實(shí)現(xiàn)相機(jī)預(yù)覽時(shí)的工作過程:

?CameraManager :攝像頭管理器,主要用于檢測系統(tǒng)攝像頭、打開系統(tǒng)攝像頭等;
?CameraDevice : 用于描述系統(tǒng)攝像頭,可用于關(guān)閉相機(jī)、創(chuàng)建相機(jī)會(huì)話、發(fā)送拍照請(qǐng)求等;
?CameraCharacteristics :用于描述攝像頭所支持的各種特性;
?CameraCaptureSession :當(dāng)程序需要預(yù)覽、拍照時(shí),都需要先通過 CameraCaptureSession 來實(shí)現(xiàn)。該會(huì)話通過調(diào)用方法 setRepeatingRequest() 實(shí)現(xiàn)預(yù)覽;
?CameraRequest :代表一次捕獲請(qǐng)求,用于描述捕獲圖片的各種參數(shù)設(shè)置;
?CameraRequest.Builder :負(fù)責(zé)生成 CameraRequest 對(duì)象。

2. 相機(jī)預(yù)覽

下面通過源碼來講解如何使用 Camera2 來實(shí)現(xiàn)相機(jī)的預(yù)覽功能。

2.1 相機(jī)權(quán)限設(shè)置

<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 相機(jī)自定義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 動(dòng)態(tài)申請(qǐng)相機(jī)權(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時(shí),才有必要判斷是否獲取權(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;
 }
 }
 // 請(qǐng)求相機(jī)權(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);
 }
 }
 // 啟動(dòng)相機(jī)Fragment
 private void setFragment() {
 getSupportFragmentManager()
 .beginTransaction()
 .replace(R.id.container, CameraFragment.newInstance())
 .commitNowAllowingStateLoss();
 }
}

2.5 開啟相機(jī)預(yù)覽

首先,在onResume()中,我們需要開啟一個(gè) HandlerThread,然后利用該線程的 Looper 對(duì)象構(gòu)建一個(gè) Handler 用于相機(jī)回調(diào)。

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

同時(shí),在 onPause() 中有對(duì)應(yīng)的 HandlerThread 關(guān)閉方法。

當(dāng)屏幕關(guān)閉后重新開啟,SurfaceTexture 已經(jīng)就緒,此時(shí)不會(huì)觸發(fā) onSurfaceTextureAvailable 回調(diào)。因此,我們判斷 mTextureView 如果可用,則直接打開相機(jī),否則等待 SurfaceTexture 回調(diào)就緒后再開啟相機(jī)。

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

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

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

相機(jī)開啟時(shí)還會(huì)指定相機(jī)的狀態(tài)變化回調(diào)函數(shù) mStateCallback,如果相機(jī)成功開啟,則開始創(chuàng)建相機(jī)預(yù)覽會(huì)話。

private void createCameraPreviewSession() {
 try {
 // 獲取 texture 實(shí)例
 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)建適合相機(jī)預(yù)覽的請(qǐng)求
 mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
 // 設(shè)置 surface 作為預(yù)覽數(shù)據(jù)的顯示界面
 mPreviewRequestBuilder.addTarget(surface);
 // 創(chuàng)建相機(jī)捕獲會(huì)話用于預(yù)覽
 mCameraDevice.createCaptureSession(Arrays.asList(surface),
 new CameraCaptureSession.StateCallback() {
  @Override
  public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
  // 如果相機(jī)關(guān)閉則返回
  if (null == mCameraDevice) {
  return;
  }
  // 如果會(huì)話準(zhǔn)備好則開啟預(yù)覽
  mCaptureSession = cameraCaptureSession;
  try {
  // 自動(dòng)對(duì)焦
  mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
   CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
  mPreviewRequest = mPreviewRequestBuilder.build();
  // 設(shè)置反復(fù)捕獲數(shù)據(jù)的請(qǐng)求,預(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();
 }
}
Android是什么

Android是一種基于Linux內(nèi)核的自由及開放源代碼的操作系統(tǒng),主要使用于移動(dòng)設(shè)備,如智能手機(jī)和平板電腦,由美國Google公司和開放手機(jī)聯(lián)盟領(lǐng)導(dǎo)及開發(fā)。

以上是“Android Camera2怎么實(shí)現(xiàn)預(yù)覽功能”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

當(dāng)前題目:AndroidCamera2怎么實(shí)現(xiàn)預(yù)覽功能-創(chuàng)新互聯(lián)
當(dāng)前鏈接:http://www.rwnh.cn/article14/hsjge.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開發(fā)移動(dòng)網(wǎng)站建設(shè)、手機(jī)網(wǎng)站建設(shè)、App開發(fā)、網(wǎng)站維護(hù)網(wǎng)站導(dǎo)航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)
余姚市| 东乡| 郎溪县| 门头沟区| 安西县| 徐闻县| 封丘县| 汉阴县| 锦屏县| 通城县| 赤城县| 靖宇县| 天柱县| 峨山| 泌阳县| 黑水县| 奉贤区| 雷州市| 嫩江县| 兴业县| 通河县| 巴林右旗| 乌拉特前旗| 上杭县| 白城市| 肇州县| 绥江县| 日喀则市| 磐石市| 富平县| 宝坻区| 临清市| 新昌县| 杭锦旗| 崇阳县| 靖边县| 仁寿县| 宁化县| 石河子市| 工布江达县| 怀来县|