前言

拍照功能在智能机中已经是标配了,市场上也充斥着形形色色的相机应用,足以说明相机功能目前的火爆程度。作为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. CF1B Spreadsheets
  2. $(document).ready() 和 window.onload 的区别
  3. 基于顺序存储结构的图书信息表的图书去重(C++)
  4. linux下darknet指定opencv4编译安装
  5. Kafka API: TopicMetadata
  6. SpringCloud(一)
  7. 文本关键词提取算法总结
  8. iOS 更改导航栏返回button文字
  9. 嵌入式linux设计报告,嵌入式Linux程设计报告.doc
  10. 【RTD】AD7793三线式铂电阻PT100/PT1000应用
  11. 2021年9月国产数据库大事记-墨天轮
  12. 百度地图大头针图片的自定义
  13. word文件文档文本恢复转换器
  14. openwrt wifi 出现missing ACKs和deauthenticated due to inactivity 频繁掉线问题解决方案
  15. oracle数据前面补0,Oracle 数字前面自动补0
  16. IDEA配置Git教程
  17. Android 信号查看,安卓Android手机怎么快速查看系统信号强度
  18. office2013安装包
  19. ACS服务器的备份和恢复
  20. Bugtags 远程配置功能介绍

热门文章

  1. 用户画像(真实脱敏数据)
  2. LeetCode 8. String to Integer (atoi)(字符串)
  3. 无人机实时流怎么开_如何用吉影水下无人机做到水下实时直播?
  4. UBUT ER-X路由器多WAN,故障转移/查看会话数
  5. 《学习记录》“Python”判断奇数偶数
  6. 解决Mybatis-Plus或PageHelper多表分页查询总条数不对问题
  7. ShaderForge-火焰溶解
  8. U盘格式化写保护?重新让U盘恢复生机的方法
  9. 我所知道的十大常用算法之普里姆算法(最小生成树)
  10. 什么蓝牙耳机性价比高?目前最值得入手的蓝牙耳机