前言

拍照功能在智能机中已经是标配了,市场上也充斥着形形色色的相机应用,足以说明相机功能目前的火爆程度。作为Android开发者拍照相关的API也是程序员必备的技能,现在就来学习一下Android系统为开发者提供的拍照相关的技术。

6.0+权限申请

由于相机权限和SDCard外部存储权限到了6.0+版本都属于危险权限,需要用户手动打开权限才能使用相机和保存照片到外部存储。在6.0+系统使用相机通常都要添加动态权限申请的逻辑,首先要在AndroidManifest文件中声明权限。

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

然后在Activity里需要申请权限的地方添加权限是否申请和没有权限申请权限的功能:

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {if (ContextCompat.checkSelfPermission(IndexActivity.this,Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&ContextCompat.checkSelfPermission(IndexActivity.this,Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {// 如果已经申请到权限直接做操作} else {// 没有权限申请权限ActivityCompat.requestPermissions(IndexActivity.this,new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA }, REQUEST_WRITE_STORAGE);}
}

用户点击权限申请的按钮后会产生回调事件,在权限回调中检查用户是否赋予权限,赋予了拍照权限之后才可以继续操作。

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (requestCode == REQUEST_WRITE_STORAGE && grantResults != null && grantResults.length > 0) {if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {// 如果相机和外部存储都已经授权}}
}

系统相机

打开系统相机只需要简单的设置Intent的action为MediaStore.ACTION_IMAGE_CAPTURE,如果用户需要接收系统相机拍照得到的照片数据就要使用startActivityResult调起系统相机在onActivityResult里获取照片数据。

public void startCamera() {Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);startActivityForResult(intent, REQUEST_TAKE_PHOTO);
}@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == REQUEST_TAKE_PHOTO && resultCode == Activity.RESULT_OK) {Bundle bundle = data.getExtras();// 取出的数据其实是缩略图Bitmap bitmap = (Bitmap) bundle.get("data");imageView.setImageBitmap(bitmap);
}

现在智能机屏幕越来越大,拍摄的照片清晰度也越来越高,但是Android的Intent最大只能方1M的数据,超过就会抛出异常,所以Intent里取出来的照片只是真实照片的缩略图。如果希望得到真实的照片数据,需要向系统相机传递接收照片的本地图片文件Uri。

public void startCamera2() {Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(filePath)));startActivityForResult(intent, REQUEST_TAKE_PHOTO2);
}@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == REQUEST_TAKE_PHOTO2 && resultCode == Activity.RESULT_OK) {Bitmap bitmap = BitmapFactory.decodeFile(filePath);imageView.setImageBitmap(bitmap);}
}

自定义拍照

系统相机使用非常简单明了,但是交互方式太过于单一,界面也很粗糙,难以满足高级用户的需求。开发者通过自定义拍照功能可以很好的提高用户体验,实现更加人性化的拍照效果。

相机捕获的数据量非常大,使用普通的View控件根本无法高效的展示实时图片;SurfaceView能用来承担这项任务,不过需要在它的生命周期里打开和关闭相机,防止出现意外情况。Camera本身是硬件服务,如果有用户申请到了就会以独占的方式使用,只要用户为释放Camera就会导致其他用户永远无法申请到Camera,用户需要处理Camera的申请和释放工作。

takePicture = (Button) findViewById(R.id.takePicture);
surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
holder = surfaceView.getHolder();
holder.addCallback(this);// 初始化Camera对象
private Camera getCamera() {Camera camera;try {camera = Camera.open();} catch (Exception e) {camera = null;e.printStackTrace();}return camera;
}// 开始相机预览功能
private void setStartPreview(Camera camera, SurfaceHolder holder) {try {camera.setPreviewDisplay(holder);// 旋转角度使之竖屏展示camera.setDisplayOrientation(90);camera.startPreview();} catch (IOException e) {e.printStackTrace();}
}// 释放申请到的相机
private void releaseCamera() {if (camera != null) {camera.setPreviewCallback(null);camera.stopPreview();camera.release();camera = null;}
}

在Activity退到后台就不需要相机捕获数据,这时需要释放相机,Activity进入前台这时可以请求相机并且开始预览效果。当然SurfaceView的Surface创建时可以开始预览效果,如果Surface改变就需要先暂停Camera再重新开始预览功能。

@Override
protected void onPause() {super.onPause();releaseCamera();
}@Override
protected void onResume() {super.onResume();if (camera == null) {camera = getCamera();if (holder != null) {setStartPreview(camera, holder);}}}@Override
public void surfaceCreated(SurfaceHolder holder) {setStartPreview(camera, holder);
}@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {camera.stopPreview();setStartPreview(camera, holder);
}@Override
public void surfaceDestroyed(SurfaceHolder holder) {releaseCamera();
}

定义好了Camera对象和SurfaceView生命周期交互,就可以开始真实的拍照了,camera.takePhoto();方法实现了拍照功能而且提供了图片回调,在回调内部可以获取到照片Jpg数据。

private void capture() {// 设置相机的参数Camera.Parameters parameters = camera.getParameters();// 相机图片格式为jpegparameters.setPictureFormat(PixelFormat.JPEG);// 初始大小parameters.setPreviewSize(800, 400);// 聚焦模式parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);// 开始拍照camera.takePicture(null, null, new Camera.PictureCallback() {// 获取拍照返回的jpg图片数据@Overridepublic void onPictureTaken(byte[] data, Camera camera) {File tmpFile = new File("/sdcard/temp.png");try {FileOutputStream fos = new FileOutputStream(tmpFile);fos.write(data);fos.close();// 将图片放到另外一个Activity中展示Intent intent = new Intent(CustomCameraActivity.this, ResultActivity.class);intent.putExtra("filePath", tmpFile.getAbsolutePath());startActivity(intent);finish();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}});
}

Camera功能强大实现简单,不过从5.0之后系统废弃了这套逻辑开始使用Camera2来实现拍照功能,后面将会使用Camera2接口重新定制一个简单的相机功能。

Android Camera相机基础使用相关推荐

  1. Android Camera相机开发示例、Android 开发板 USB摄像头采集、定期拍照、定时拍照,安卓调用摄像头拍照、Android摄像头预览、监控,USB摄像头开发、摄像头监控代码

    我们有个需求,在机器上加个摄像头,定时拍照: 我到网上搜索,发现没有快速上手和简单使用的: 个人感觉,大部分博客写得很乱,或者长篇大论: 而我只想简单实现功能,并不打算学习多少理论: 下面代码是我写来 ...

  2. 【转】Android Camera 相机开发详解

    在Android 5.0(SDK 21)中,Google使用Camera2替代了Camera接口.Camera2在接口和架构上做了巨大的变动, 但是基于众所周知的原因,我们还必须基于 Android ...

  3. Android camera相机开发拍照功能

    在Android 5.0(SDK 21)中,Google使用Camera2替代了Camera接口.Camera2在接口和架构上做了巨大的变动,但是基于众所周知的原因,我们还必须基于 Android 4 ...

  4. Android Camera相机预览,拍照 ,横屏竖屏的处理

    功能分别是: 1.竖屏的前置,后置显示 加 拍照 2.横屏的前置,后置显示 加 拍照 整个项目的代码贴出来了,里面加了有备注,不理解的也可以去参考官网点击跳转到官网 首先选择前置后置布局效果如下 布局 ...

  5. Android Camera 预览、拍照、保存照片 实现

    和你一起终身学习,这里是程序员Android 经典好文推荐,通过阅读本文,您将收获以下知识点: 一.Camera2架构概述 二.Camera2中比较重要的类及方法 三.具体实现步骤 四.初始化相关参数 ...

  6. android camera 显示过程,Android相机Camera基础知识

    一.概述本章节主要讲述的Android相机Camera的相关知识点,主要包含三个方面,Android启动系统相机生成缩略图.Android启动系统相机生成原图以及Android自定义相机等. 二.An ...

  7. Android camera(4)---Android Camera开发之基础知识篇

    Android Camera开发之基础知识篇 转自:https://blog.csdn.net/feiduclear_up/article/details/51968975#jump5 概述 Andr ...

  8. Android Camera开发(一)之基础知识

    概述 Android手机关于Camera的使用,一是拍照,二是摄像,由于Android提供了强大的组件功能,为此对于在Android手机系统上进行Camera的开发,我们可以使用两类方法:一是借助In ...

  9. camera相机 its_[Android] Camera ITS/CTS Verifier测试

    ITS:Android Camera Imaging Test Suite / CTS Verifier Android相机成像测试套件,属于CTS测试的一部分 ITS是一个测试框架,用于在camer ...

最新文章

  1. 高并发大流量专题---8、动态语言的并发处理
  2. 关于编码、unicode、utf-8的讨论
  3. linux内核网络初始化,Linux内核--网络栈实现分析
  4. 【组合数学】递推方程 ( 非齐次部分是指数的情况 | 非齐次部分是指数的情况示例 )
  5. 图解SQL Server 2008入门总结
  6. 从0搭建在线聊天室,只需4步!
  7. CentOS7 下安装 Redis
  8. poj 1039 Pipe (判断 直线和 线段 是否相交 并 求交点)
  9. SLAM--求解2D-2D图像间的运动
  10. 简单的maven引入外部jar项目打包
  11. JSP文件的中文在浏览器上显示乱码解决方法
  12. 2022年11月编程排行榜
  13. 【ZYNQ】从入门到秃头02 ZYNQ硬件介绍和Vivado开发流程
  14. 一:计算机中加法的电路实现
  15. svm神经网络葡萄酒matlab,SVM神经网络的数据分类预测--葡萄酒种类识别
  16. ip地址合不合法怎么看_如何判断IP地址的合法性
  17. 《VoIP技术构架(第2版·修订版)》一1.7 小结
  18. php常用系统函数库,PHP常用函数大全
  19. 密码学之数字签名是什么
  20. QT自定义简单表盘(完整代码)

热门文章

  1. gRPC client端请求响应速度慢问题
  2. Python.__getitem__方法
  3. 笔记/Linux运维面试常见问题
  4. pt08函数式编程lambda
  5. 崽崽是什么?崽崽游戏玩法以及攻略
  6. 二维码的基础原理是什么?
  7. 变步长梯形求解微分方程
  8. k8s 之 Deployment 介绍与使用流程
  9. nn.BatchNorm1d
  10. 惠普打印机共享故障两例