转载请指明出处@https://blog.csdn.net/qq_41912447
版权归博主所有

/**
**本文由自己搜集资料编程 如有错误请指明
**李紫洋著
*/

导引

相机成为了一个app必不可少的一个重要组成 它可以实现拍照,扫描二维码,视频聊天等 今天博主就来讲一下安卓开发相机 今天就带大家入门 更多资料请参考谷歌安卓开发官网android developers

  • 简介
    相机是属于系统资源 本身硬件就自带相机 你可以直接调用他来大大减少你的开发时间 像美颜相机这种app就需要自定义相机 现在大部分都有第三方平台 提供api供你使用 这同时大大减少你的代码量和团队创建的资金 第三方框架的使用大大减少你的工作量 同时他们的体系更加的完善 会减少bug的出现

  • 设备兼容的问题需要大家考虑 像小米 oppo vivo 华为等设备都对硬件系统做了一定的处理 用来优化他们的设备性能性 所以请参考他们这些设备的官网开发资料进行一定的处理

一般的处理方法是在功能清单注册这些设备的权限 在代码中对这些设备进行一定的处理

  • 同时6.0动态权限也需要大家考虑 让用户有一个高的体验 这的确是初学者的一个重大考验 你需要考虑所有会发生的情况
    1软件安装提示权限
    2
    <1.用户同意继续使用app
    <2.用户拒绝

    》》》1如果有必不可少的权限则退出 像相机app如果不给予相机权限只能强制退出软件了 这时就要提示用户如果拒绝则不再可以使用此软件
    》》》2如果此权限并不正常影响你的app正常启动 则可以选择在使用你的功能时再次询问是否打开权限 这时可以使用intent信使让用户跳转到系统权限打开的类手动打开权限
    》》为了避免多次对话框出现对用户体验造成影响 甚至会卸载app
    用户可能随时关闭权限 对你的app进行管理 有可能你的app是一个相机软件 用户不能理解你使用电话权限的理由 你可以在用户拒绝的时候提示用户此权限的意义 不要在权限申请的时候进行处理 过多的提示会降低用户的体验

3对手机系统版本做出判断 低版本安卓设备权限处理与6.0版本以上处理方法不同 主要是6.0动态权限加入危险权限和安全权限 安全权限则只需要在功能清单注册即可 一般一组权限只需要注册一个即可 用户同意则会给予你这组权限的所有

**需要对设备本地数据库具有一定的理解 用来存储一些重要数据永久保存 将在软件卸载的时候消失 同时也要对网络传输数据库有一定的理解 了解json xml传输数据 json有一个好的工具是谷歌的gson 后续会编写相关的博客

  • 6.0动态权限有一张步骤图 这里就不公告了 我用自己的理解把他用通俗的语言写出来了 请不要觉得文字太多 每个点都是需要考虑的

  • 注 所有资源请以谷歌开发者文档官网为标准
    好了废话不多说 现在来看我的一个简单示例代码
    这里示例调用系统相机 和自定义相机两个部分

调用系统相机

先来看布局文件来了解一下步骤

下面来示例这个java类的编码

package com.liziyang.dall;
//这里是自己的包名 必不可少的import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;import java.io.File;
import java.util.EventListener;
//这里是导入的api库 有些是安卓的 有些是java的 也可以是框架的库 在写本类的时候需要查看导入的库 别导错库public class MainActivity extends Activity {
//新建一个类的的初始格式  这个类继承了活动  用来实现UI界面的逻辑实现
//extends是继承属性  你可以根据需要继承所需的类 //声明控件private Button button,button2;private ImageView imageView;private TextView textView;private String fileName="";//定义一个 路径的字符串 这里是一个空值 下面将会用到//定义一个string类型的fileName方便以后使用  用来作为拍摄的图片名字@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate( savedInstanceState );//四大组件活动的生命周期 oncreate//UI界面控件的逻辑实现 需要在这里实现  setContentView( R.layout.activity_main );//设置上下文对象//当java类继承活动就需要设置上下文button=findViewById( R.id.button );button2=findViewById( R.id.button2 );imageView=findViewById( R.id.imageView );textView=findViewById( R.id.textView );//声明对象绑定UI控件IDbutton.setOnClickListener( new View.OnClickListener() {//按钮实现点击功能  不要在xml布局文件中使用onclick 可能会出现bug 部分机型不匹配的可能public void onClick(View view) {//使用intent启动组件//系统相机的activity位置 mediaStore.ACTION_IMAGE_CAPTURE//这里使用意图 将界面跳转到系统相机界面 这些系统界面的代码简写在官方文档查询 最好把他们下载下来 方便使用的时候查询Intent intent = new Intent( MediaStore.ACTION_IMAGE_CAPTURE  );//意图intent 也可以写成下面两行 相信大家都懂//Intent intent=new Intent(); //ntent.setClass(MainActivity.this,MediaStore.ACTION_IMAGE_CAPTURE .class);//定义一个file路径  设置为内存卡路径File dir= Environment.getExternalStorageDirectory();//存在sd卡上//如果没有sd卡或sd卡内存已满则会保存到手机设备中//最好把网络需要的图片缓存下来 像app内置图片最好保存到分配的内置包中 防止给用户带来差的体验 //假如你在自己相册看到你不想要的图片视频等 你就会卸载//命名图片 得到系统毫秒fileName="hey"+System.currentTimeMillis()+".jpg";//初始化路径 把是存在在sd卡上和 保存图片的名字设置进去File file=new File( dir,fileName );//封装路径 把文件路径和名字两个参数封装进去Uri fileuri=Uri.fromFile( file );//设置图片路径 可以为网络等 最好选择一个框架 例如glide和ImageLoader框架对图片进行优化 如果是网络获取文件 例如okHttp或xUtils 这些框架建议大家去了解一下//设置uri 其他需要图片解码 uri途径就是存储设备和图片名//选择拍摄照片存放位置 第二个可以给这个图片一个uri//将intent添加额外数据 额外 读出 uri位置intent.putExtra( MediaStore.EXTRA_OUTPUT,fileuri );//意图添加其他传输数据//需要接受的方法 用类似方法将他取出来//有返回启动activity intent传输 返回码为0 返回码是自己写的startActivityForResult( intent,0);//带传值的启动活动  这个方法常用  //startActivity不太常用 他不可以传值}} );/**启动系统相机的方法 只需要用intent启动系统组件 指明系统组件* 自定义存储位置 得到外部存储  定义路径 自定义图片名字 写一个string数组为图片名字 为了防止名字相同 使用毫秒* 将自定义名字和路径包装到uri中*指明intent需要的功能 回传数据*添加intent功能和uri地址* 带回传启动activity 指明intent和回传码*/button2.setOnClickListener( new View.OnClickListener() {@Overridepublic void onClick(View view) {//这里就直接使用意图跳转界面 所需的放在另一个类方法实现Intent intent=new Intent( MainActivity.this,Main2Activity.class );startActivity( intent );}} );}//有返回值会回调这个方法@Overrideprotected void onActivityResult(int requestCode,int resultCode,Intent data) {super.onActivityResult( requestCode,resultCode,data );//打印log 方便测试Log.i( "TEST","onActivityResult" );//如果回传码为0和回传码生成if(requestCode==0&&resultCode==RESULT_OK) {//指明路径File dir = Environment.getExternalStorageDirectory();//存在sd卡上//命名图片 得到系统毫秒File file = new File( dir,fileName );Uri fileuri = Uri.fromFile( file );//intent启动组件 返回数据的方法 onActivityResult//设置图片uri uri图片不用解码imageView.setImageURI( fileuri );//建议使用URI方法 不要需要解码否则可能会出现bug  要不然使用框架}}
}


布局不是很美观 只是一个demo 有需要可以参考网络资料 对布局优化
来看一下布局代码

<?xml version="1.0" encoding="utf-8"?>
<!--relativeLayout相对布局
这个布局可以让你更好的精确控制控件位置 最好使用谷歌新推出的布局   他避免了嵌套布局 加快了加载速度-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".Main2Activity"><!---使用surfaceView来当作相机的画面 注意要全屏设置 用来美化布局--><SurfaceViewandroid:id="@+id/surfaceView2"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_alignParentBottom="true" /><!--这里嵌套了一个布局 android:gravity="center" 把布局里的控件放到布局中心 如 --*-- --><LinearLayoutandroid:layout_width="match_parent"android:layout_height="80dp"android:gravity="center"android:layout_alignParentBottom="true"android:layout_alignParentLeft="true"><!--图片按钮 用来设置拍摄图片--><ImageButtonandroid:id="@+id/imageButton2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@android:drawable/btn_radio" /><!--图片控件进行预览--><ImageViewandroid:id="@+id/imageView3"android:layout_width="80dp"android:layout_height="80dp"android:src="@color/colorAccent" /></LinearLayout></RelativeLayout>

来看自定义相机的java具体实现类的代码编写

package com.liziyang.dall;import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.os.Bundle;
import android.app.Activity;
import android.os.Environment;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;public class Main2Activity extends Activity {//指明需要使用到相机//声明相机 因为需要用到自定义相机private Camera camera;//使用屏幕surface//只要是自定义的相机视频动画等需要用到屏幕viewprivate SurfaceView surfaceView;//屏幕管理者private SurfaceHolder surfaceHolder;//屏幕管理的方法名private ImageButton imageButton2;private ImageView imageView3;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate( savedInstanceState );setContentView( R.layout.activity_main2 );surfaceView=findViewById( R.id.surfaceView2 );surfaceHolder=surfaceView.getHolder();imageButton2=findViewById( R.id.imageButton2 );imageView3=findViewById( R.id.imageView3 );imageButton2.setOnClickListener( new View.OnClickListener() {@Overridepublic void onClick(View view) {//照片拍摄图片 照片回调//括号中需要传入几个参数camera.takePicture( null,null,new Camera.PictureCallback() {@Overridepublic void onPictureTaken(byte[] data,Camera camera) {//预览//bitmap位图  array数组 数据  数据的长度//得到数据bitmap  数组 数据为0  数据的长度Bitmap bitmap= BitmapFactory.decodeByteArray( data,0,data.length );//预览视图设置图片位图imageView3.setImageBitmap( bitmap );//这里把拍摄的图片设置到UI界面的图片上 //并没有进行处理 你也可以把他储存到内存卡上 把bitmap进行封装//buffer缓冲 outPut输出 steam流 缓冲输入流初始化BufferedOutputStream bufferedOutputStream=null;//对缓存进行初始化 //可能会出现bug  对可能出现的异常进行抛出try  {String fileName="hey"+System.currentTimeMillis()+".jpg";//设置文件名bufferedOutputStream = new BufferedOutputStream( new FileOutputStream( new File( Environment.getExternalStorageDirectory(),fileName ) )) ;//保存  100压缩率 按原图保存//compress压缩 format格式 100 缓冲输出流bitmap.compress( Bitmap.CompressFormat.JPEG,100,bufferedOutputStream );//对图片进行压缩  设置输出流为内容}catch (FileNotFoundException e){e.printStackTrace();}finally {//最后对所用到的东西进行关闭 以免内存泄漏//使用完毕假如缓冲输出流不是空值 关闭缓存输入流//防止使用后用户打开其他软件会出现bugif (bufferedOutputStream!=null){//判断输出流是否为空  try {//对输出流进行关闭bufferedOutputStream.close();} catch (IOException e) {//抛出异常e.printStackTrace();}}}}} );}} );//缓存持有者 添加回传surfaceHolder.addCallback( new SurfaceHolder.Callback(){//重写下面的方法@Overridepublic void surfaceCreated(SurfaceHolder surfaceHolder) {//缓存创建的时候//得到相机 初始化//得到相机对象 camera=getCamera();//如果相机不为空if (camera!=null){try {//preview预览 display显示 缓存持有者//设置缓存路径camera.setPreviewDisplay( surfaceHolder );//缓存开始预览//开始缓存camera.startPreview();} catch (IOException e) {e.printStackTrace();}}}@Overridepublic void surfaceChanged(SurfaceHolder surfaceHolder,int i,int i1,int i2) {}@Overridepublic void surfaceDestroyed(SurfaceHolder surfaceHolder) {//缓存销毁时 release释放//释放相机 以免再次使用相机出现被占用的现象releaseCamera();}} );//内容持有者设置种类surfaceHolder.setType( SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//得到相机camera=getCamera();//如果相机不为空if (camera!=null){try {//相机 设置preview预览 display显示camera.setPreviewDisplay( surfaceHolder );//相机开始预览  这是相机里的方法  调用//preview预览camera.startPreview();} catch (IOException e) {e.printStackTrace();}}}@Overrideprotected void onDestroy() {//release释放releaseCamera();super.onDestroy();}//得到相机private Camera getCamera() {//如果相机 为空if (camera == null) {try {//打开相机camera = Camera.open();//返回相机return camera;} catch (Exception ex) {return null;}}//不管怎么样  返回相机return camera;}//release释放private void releaseCamera(){//如果相机不为空 释放相机   初始化if (camera!=null){camera.release();camera=null;}}}

/***

  • 自定义相机的实现
  • 首先使用surface布局视图来显示自定义的画面
  • 得到画面缓存器 用来实现预览
  • 路径图片名字 压缩的处理
  • 使用surface回传
  • 软件进程关闭的处理 释放相机和画面持有者
    */

最后别忘了在功能清单注册权限

  • 注:6.0动态权限危险权限 需要特殊的处理
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.liziyang.dall"><!-- 如果不必须使用自定义相机改为false  required必须 --><uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.CAMERA2" /><uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-feature android:name="android.hardware.camera.any" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activityandroid:name=".Main2Activity"android:screenOrientation="landscape"android:label="@string/title_activity_main2"></activity></application></manifest>

注:自定义相机权限处理方法不同 读取内存卡 使用相机 为危险权限 请注意加以处理 这里不写 用户必须去打开相应的权限 才可以继续使用
假如进行拍摄录制 需要加入一个音频录制的权限 后续会写6.0动态权限的处理

 <!-- 如果不必须使用自定义相机改为false  required必须 --><uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.CAMERA2" /><uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-feature android:name="android.hardware.camera.any" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

欢迎大家来参考我的博客 如有错误 请评论指出

同时我简书和博客有些不同步 关注我的技术主题,每天都有优质技术文章推送 简书扫一扫下方二维码即可关注:

Android自定义相机相关推荐

  1. android 实现自动拍照,Android自定义相机实现定时拍照功能

    这篇博客为大家介绍Android自定义相机,并且实现倒计时拍照功能. 首先自定义拍照会用到SurfaceView控件显示照片的预览区域,以下是布局文件: activity_main.xml andro ...

  2. android 自定义相机源码,Android 自定义相机及分析源码

    Android 自定义相机及分析源码 使用Android 系统相机的方法: 要想让应用有相机的action,咱们就必须在清单文件中做一些声明,好让系统知道,如下 action的作用就是声明action ...

  3. android自动对焦第一次对焦,Android自定义相机实现自动对焦和手动对焦

    Android自定义相机实现自动对焦和手动对焦: 不调用系统相机,因为不同的机器打开相机呈现的界面不统一也不能满足需求. 所以为了让程序在不同的机器上呈现出统一的界面,并且可以根据需求进行布局,做了此 ...

  4. Android自定义相机实现定时拍照

    这篇博客为大家介绍Android自定义相机,并且实现倒计时拍照功能. 首先自定义拍照会用到SurfaceView控件显示照片的预览区域,以下是布局文件: activity_main.xml <F ...

  5. Android 自定义相机Demo 入门学习

    Android 自定义相机Demo 本文是参考网上一些自定义相机示例,再结合自己对相机的功能需求写的,基本上包含了很多基本功能,比如相机对焦.闪光灯,以及在手机预览界面上绘制自己想要绘制的图案. 话不 ...

  6. Android自定义相机拍照、图片裁剪的实现

    原文:Android自定义相机拍照.图片裁剪的实现 最近项目里面又要加一个拍照搜题的功能,也就是用户对着不会做的题目拍一张照片,将照片的文字使用ocr识别出来,再调用题库搜索接口搜索出来展示给用户,类 ...

  7. Android自定义相机,切换前后摄像头,照相机拍照

    Android自定义相机,简单实现切换前后摄像头,照相机拍照 Ctrl +C  Ctrl+V 可以直接 run 起来,注释比较详细;源码下载 <?xml version="1.0&qu ...

  8. android 自定义相机,Android自定义相机实现定时拍照功能

    这篇博客为大家介绍Android自定义相机,并且实现倒计时拍照功能. 首先自定义拍照会用到SurfaceView控件显示照片的预览区域,以下是布局文件: activity_main.xml andro ...

  9. Android自定义相机详细讲解

    使用surfaceview自定义相机,同时把自己踩过的坑分享给大家,希望大家有所收获. #写在前面的话 前一阵子负责一个自定义相机进行拍照并在另一个页面进行人脸识别的模块,相机部分需求并不怎么复杂,可 ...

  10. android 自定义相机,Camera,相机遮罩层

    实现效果:      实现方法:一个自定义view实现demo 一.自定义相机Camera,无API版本限制 (1).实现接口 implements SurfaceHolder.Callback pr ...

最新文章

  1. SQLite的数据类型总结
  2. 课题背景 一二三代测序技术
  3. 大数据、数据挖掘、机器学习三者的区别和联系
  4. 【转载】linux环境变量PS1的简介
  5. numpy笔记:random.permutation
  6. VC++的windows服务
  7. 我的物联网项目(十二) 单体应用架构不行?
  8. 前端开发知识点解答-HTML-面试
  9. 安装inotify-tools监控工具
  10. 数据结构串的基本操作及KMP算法
  11. SQL2008数据库可疑状态处理
  12. php 横屏和竖屏,面试问题,视频横屏与竖屏的设计差异?我是这样回答的
  13. 春节晚报 | 2月1日 星期二 | 快手推出首届“新春招工会”;罗永浩称“不做VR和元宇宙”;戴姆勒正式更名为梅赛德斯-奔驰...
  14. 基于MATLAB的一维条码二维码识别
  15. 转载:PhotoRobot之Sohu相册
  16. 后台管理界面-- 管理员管理[3]
  17. 三星游戏java ball_JavaBallGame 使用 语言设计的弹球游戏,可以学习 编写小 的方法。 Program 238万源代码下载- www.pudn.com...
  18. 记录:Warning C6385 : 从“p”中读取的数据无效: 可读大小为“n * sizeof(int)”个字节,但可能读取了“8”个字节。
  19. adobe xd_60秒内完成Adobe XD
  20. JAVA多线程实现和应用总结

热门文章

  1. 微信小程序——1、自定义顶部渐变色2、封装好的自定义顶部栏(父组件获取子组件的点击事件)
  2. display与visibility可见性、内补白与外补白
  3. Linux中的stdout和stderr
  4. 【解析】心田上的百合花开——心田花开
  5. linux信号函数signal(SIGCHLD, SIG_IGN)
  6. 计算机附件计算器的用法,计算机附件中的计算器使用方法.doc
  7. 七、vertical-align属性、透明度属性及兼容、ps常用工具、常见的图片格式、项目规范、命名参考、iconfont的使用
  8. 三星苹果还能笑多久?联想挑战智能手机全球霸主
  9. Nothing Phone官宣,手机厂新秀靠啥出圈?
  10. CnnDroid 优化加速原理