最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android自定義Camera實(shí)現(xiàn)拍照功能

 更新時(shí)間:2022年05月19日 10:52:56   作者:忙碌的咖啡  
這篇文章主要為大家詳細(xì)介紹了Android自定義Camera實(shí)現(xiàn)拍照功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文記錄了用自定義Camera實(shí)現(xiàn)的簡(jiǎn)單拍照功能。

Camera類在5.0以后不推薦使用了,取而代之的是android.hardware.camera2包下的類,本文使用Camera。
我們首先自定義一個(gè)View去繼承SurfaceView:

public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Camera.AutoFocusCallback {
 private SurfaceHolder mHolder;
 private Camera mCamera;
 private static final int ORIENTATION = 90;
 private int mScreenWidth;
 private int mScreenHeight;
 private boolean isOpen;

 public CameraSurfaceView(Context context, AttributeSet attrs) {
  super(context, attrs);
  getScreenMatrix(context);
  mHolder = getHolder();
  mHolder.addCallback(this);
  mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
 }

 private void getScreenMatrix(Context context) {
  WindowManager WM = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
  DisplayMetrics outMetrics = new DisplayMetrics();
  WM.getDefaultDisplay().getMetrics(outMetrics);
  mScreenWidth = outMetrics.widthPixels;
  mScreenHeight = outMetrics.heightPixels;
 }

 public void takePicture(Camera.ShutterCallback mShutterCallback, Camera.PictureCallback rawPictureCallback, Camera.PictureCallback jpegPictureCallback) {
  if (mCamera != null)
   mCamera.takePicture(mShutterCallback, rawPictureCallback, jpegPictureCallback);
 }

 public void startPreview() {
  mCamera.startPreview();
 }

 @Override
 public void surfaceCreated(SurfaceHolder holder) {
  if (!checkCameraHardware(getContext()))
   return;
  if (mCamera == null) {
   isOpen = safeCameraOpen(Camera.CameraInfo.CAMERA_FACING_BACK);
  }
  if (!isOpen) {
   return;
  }
  mCamera.setDisplayOrientation(ORIENTATION);
  try {
   mCamera.setPreviewDisplay(holder);

  } catch (IOException e) {
   e.printStackTrace();
  }
 }

 @Override
 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
  if (mCamera != null) {
   setCameraParams(mScreenWidth, mScreenHeight);
   mCamera.startPreview();
  }
 }

 @Override
 public void surfaceDestroyed(SurfaceHolder holder) {
  releaseCameraAndPreview();
 }

 private boolean safeCameraOpen(int id) {
  boolean qOpened = false;
  try {
   releaseCameraAndPreview();
   mCamera = Camera.open(id);
   qOpened = (mCamera != null);
  } catch (Exception e) {
   e.printStackTrace();
  }

  return qOpened;
 }

 private void releaseCameraAndPreview() {
  if (mCamera != null) {
   mCamera.stopPreview();
   mCamera.release();
   mCamera = null;
  }
 }

 private boolean checkCameraHardware(Context context) {
  if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
   return true;
  } else {
   return false;
  }
 }


 @Override
 public void onAutoFocus(boolean success, Camera camera) {

 }

 private void setCameraParams(int width, int height) {
  Camera.Parameters parameters = mCamera.getParameters();
  // 獲取攝像頭支持的PictureSize列表
  List<Camera.Size> pictureSizeList = parameters.getSupportedPictureSizes();
  /**從列表中選取合適的分辨率*/
  Camera.Size picSize = getProperSize(pictureSizeList, ((float) height / width));
  if (null == picSize) {
   picSize = parameters.getPictureSize();
  }
  // 根據(jù)選出的PictureSize重新設(shè)置SurfaceView大小
  float w = picSize.width;
  float h = picSize.height;
  parameters.setPictureSize(picSize.width, picSize.height);
  this.setLayoutParams(new RelativeLayout.LayoutParams((int) (height * (h / w)), height));
  // 獲取攝像頭支持的PreviewSize列表
  List<Camera.Size> previewSizeList = parameters.getSupportedPreviewSizes();
  Camera.Size preSize = getProperSize(previewSizeList, ((float) height) / width);
  if (null != preSize) {
   parameters.setPreviewSize(preSize.width, preSize.height);
  }

  parameters.setJpegQuality(100); // 設(shè)置照片質(zhì)量
  if (parameters.getSupportedFocusModes().contains(android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
   parameters.setFocusMode(android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);// 連續(xù)對(duì)焦模式
  }

  mCamera.setDisplayOrientation(90);// 設(shè)置PreviewDisplay的方向,效果就是將捕獲的畫面旋轉(zhuǎn)多少度顯示
  mCamera.setParameters(parameters);

 }

 /**
  * 選取合適的分辨率
  */
 private Camera.Size getProperSize(List<Camera.Size> pictureSizeList, float screenRatio) {
  Camera.Size result = null;
  for (Camera.Size size : pictureSizeList) {
   float currentRatio = ((float) size.width) / size.height;
   if (currentRatio - screenRatio == 0) {
    result = size;
    break;
   }
  }

  if (null == result) {
   for (Camera.Size size : pictureSizeList) {
    float curRatio = ((float) size.width) / size.height;
    if (curRatio == 4f / 3) {// 默認(rèn)w:h = 4:3
     result = size;
     break;
    }
   }
  }

  return result;
 }
}

代碼沒(méi)什么難度,在View創(chuàng)建的時(shí)候完成Camera的初始化,然后對(duì)Camera進(jìn)行參數(shù)的設(shè)置(圖片尺寸,質(zhì)量之類的),最后別忘了在View銷毀的時(shí)候?qū)Y源進(jìn)行釋放。

控件定義完了之后我們就要去使用它,在布局文件中添加就OK:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/activity_main"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 >

 <com.padoon.cameratest.CameraSurfaceView
  android:id="@+id/sv_camera"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:layout_weight="4"/>

 <ImageView
  android:id="@+id/img_take_photo"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_alignParentBottom="true"
  android:layout_alignParentRight="true"
  android:layout_gravity="bottom"
  android:layout_marginBottom="10dp"
  android:layout_marginRight="10dp"
  android:src="@mipmap/icon_camera"/>
</RelativeLayout>

然后在Activity中去完成拍照功能:

 

public class CameraActivity extends AppCompatActivity {
 private boolean isClick = true;
 private static final String PATH_IMAGES = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "easy_check";
 private CameraSurfaceView mCameraSurfaceView;
 //拍照快門的回調(diào)
 private Camera.ShutterCallback mShutterCallback = new Camera.ShutterCallback() {
  @Override
  public void onShutter() {

  }
 };
 //拍照完成之后返回原始數(shù)據(jù)的回調(diào)
 private Camera.PictureCallback rawPictureCallback = new Camera.PictureCallback() {
  @Override
  public void onPictureTaken(byte[] data, Camera camera) {

  }
 };
 //拍照完成之后返回壓縮數(shù)據(jù)的回調(diào)
 private Camera.PictureCallback jpegPictureCallback = new Camera.PictureCallback() {
  @Override
  public void onPictureTaken(byte[] data, Camera camera) {
   mCameraSurfaceView.startPreview();
   saveFile(data);
   Toast.makeText(CameraActivity.this, "拍照成功", Toast.LENGTH_SHORT).show();
   isClick = true;

  }
 };

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  ImageView img_take_photo = (ImageView) findViewById(R.id.img_take_photo);
  mCameraSurfaceView = (CameraSurfaceView) findViewById(R.id.sv_camera);
  img_take_photo.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    takePhoto();
   }
  });
 }

 public void takePhoto() {
  if (isClick) {
   isClick = false;
   mCameraSurfaceView.takePicture(mShutterCallback, rawPictureCallback, jpegPictureCallback);
  }
 }
 //保存圖片到硬盤
 public void saveFile(byte[] data) {
  String fileName = UUID.randomUUID().toString() + ".jpg";
  FileOutputStream outputStream = null;
  try {
   File file = new File(PATH_IMAGES);
   if (!file.exists()) {
    file.mkdirs();
   }
   outputStream = new FileOutputStream(PATH_IMAGES + File.separator + fileName);
   BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
   bufferedOutputStream.write(data, 0, data.length);
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   try {
    outputStream.close();
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
 }
}

最后記得添加拍照跟磁盤操作權(quán)限:

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

到這一個(gè)非常簡(jiǎn)單的拍照Demo就完成了,只能當(dāng)做Demo使用,離開(kāi)發(fā)正式使用還有一段的距離,再次特地記錄一下。

下載:源碼

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • android中實(shí)現(xiàn)手機(jī)號(hào)碼的校驗(yàn)的示例代碼

    android中實(shí)現(xiàn)手機(jī)號(hào)碼的校驗(yàn)的示例代碼

    本篇文章主要介紹了android中實(shí)現(xiàn)手機(jī)號(hào)碼的校驗(yàn)的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-09-09
  • Android EditText實(shí)現(xiàn)輸入表情

    Android EditText實(shí)現(xiàn)輸入表情

    editText是TextView的子類,TextView能用的工具EditText都能用,接下來(lái)通過(guò)實(shí)例代碼給大家分享Android EditText實(shí)現(xiàn)輸入表情功能,感興趣的朋友一起看看吧
    2017-08-08
  • Android 對(duì)話框 Dialog使用實(shí)例講解

    Android 對(duì)話框 Dialog使用實(shí)例講解

    對(duì)話框是在當(dāng)前的頁(yè)面之上彈出的小窗口, 用于顯示一些重要的提示信息, 提示用戶的輸入,確認(rèn)信息,或顯示某種狀態(tài).如 : 顯示進(jìn)度條對(duì)話框, 退出提示.接下來(lái)通過(guò)本文給大家介紹android dialog對(duì)話框知識(shí),感興趣的朋友一起看看吧
    2016-09-09
  • Android?內(nèi)存優(yōu)化知識(shí)點(diǎn)梳理總結(jié)

    Android?內(nèi)存優(yōu)化知識(shí)點(diǎn)梳理總結(jié)

    這篇文章主要介紹了Android?內(nèi)存優(yōu)化知識(shí)點(diǎn)梳理總結(jié),Android?操作系統(tǒng)給每個(gè)進(jìn)程都會(huì)分配指定額度的內(nèi)存空間,App?使用內(nèi)存來(lái)進(jìn)行快速的文件訪問(wèn)交互,長(zhǎng)時(shí)間如此便需要優(yōu)化策略,文章分享優(yōu)化知識(shí)點(diǎn)總結(jié),需要的朋友可以參考一下
    2022-06-06
  • Android判斷某個(gè)權(quán)限是否開(kāi)啟的方法

    Android判斷某個(gè)權(quán)限是否開(kāi)啟的方法

    今天小編就為大家分享一篇Android判斷某個(gè)權(quán)限是否開(kāi)啟的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • 利用Flutter繪制出3D效果動(dòng)畫

    利用Flutter繪制出3D效果動(dòng)畫

    本文主要介紹了Flutter繪圖的Path的應(yīng)用。Flutter的Path類提供了一個(gè)三維空間的變換方法,可以實(shí)現(xiàn)路徑在三維空間的平移、旋轉(zhuǎn)等操作,從而可以實(shí)現(xiàn)3D繪制的效果,感興趣的可以了解一下
    2022-08-08
  • Android定制自己的EditText輕松改變底線顏色

    Android定制自己的EditText輕松改變底線顏色

    這篇文章主要介紹了Android如何定制自己的EditText,如何輕松改變底線顏色,感興趣的小伙伴們可以參考一下
    2015-12-12
  • Android 仿硅谷新聞下拉刷新/上拉加載更多

    Android 仿硅谷新聞下拉刷新/上拉加載更多

    這篇文章主要介紹了Android 仿硅谷新聞下拉刷新/上拉加載更多的實(shí)現(xiàn)代碼,非常不錯(cuò)具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2016-10-10
  • Android 仿QQ頭像自定義截取功能

    Android 仿QQ頭像自定義截取功能

    在我們的qq聊天工具中,經(jīng)常會(huì)使用qq頭像截取功能,基于代碼是怎么實(shí)現(xiàn)的呢?下面小編通過(guò)本文給大家分享android 仿qq頭像自定義截取功能的思路分析及編碼實(shí)現(xiàn)過(guò)程,感興趣的朋友一起學(xué)習(xí)吧
    2016-10-10
  • Kotlin中?和!!的區(qū)別詳細(xì)對(duì)比

    Kotlin中?和!!的區(qū)別詳細(xì)對(duì)比

    這篇文章主要給大家介紹了關(guān)于Kotlin中?和!!區(qū)別的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05

最新評(píng)論

明光市| 陵川县| 和硕县| 贵德县| 沧源| 布尔津县| 丽水市| 天长市| 廊坊市| 邮箱| 布尔津县| 铅山县| 新建县| 宁蒗| 盐源县| 博罗县| 高雄县| 治县。| 吕梁市| 垦利县| 长垣县| 萍乡市| 虹口区| 高密市| 镇安县| 桂林市| 雷山县| 武功县| 广宗县| 泽库县| 鄢陵县| 九龙坡区| 苏尼特右旗| 新竹市| 中方县| 棋牌| 海门市| 察雅县| 涞源县| 昌吉市| 新河县|