Android自定义相机,简单实现切换前后摄像头,照相机拍照

Ctrl +C  Ctrl+V 可以直接 run 起来,注释比较详细;源码下载

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.tomorrow_p.camera_p"><!-- 调用摄像头权限 --><uses-permission android:name="android.permission.CAMERA" /><!-- 挂载sd卡 --><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /><!-- sd卡读写权限 --><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"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><activity android:name="com.tomorrow_p.camera_p.PreviewImageActivity"></activity></application></manifest>

android6.0及以上需要 动态申请相机权限:

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1);}
package com.tomorrow_p.camera_p;import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Toast;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;public class MainActivity extends Activity {private static final String TAG = "ansen";private View mRelativeLayout;private Camera mCamera;private Camera.Parameters mParameters = null;private int cameraPosition = 1;//0代表前置摄像头,1代表后置摄像头private SurfaceHolder mHolder;Bundle bundle = null; // 声明一个Bundle对象,用来存储数据@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
//        requestWindowFeature(Window.FEATURE_NO_TITLE);//没有标题
//        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//设置全屏
//        this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//拍照过程屏幕一直处于高亮setContentView(R.layout.activity_main);mRelativeLayout = findViewById(R.id.relativeLayout);SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView);surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);surfaceView.getHolder().setFixedSize(176, 144); //设置Surface分辨率surfaceView.getHolder().setKeepScreenOn(true);// 屏幕常亮surfaceView.getHolder().addCallback(new SurfaceCallback());//为SurfaceView的句柄添加一个回调函数}public void takePhoto(View v) {if (mCamera != null) {// 获取到拍照的图片数据后回调PictureCallback,PictureCallback可以对相片进行保存或传入网络mCamera.takePicture(null, null, new MyPictureCallback());}}public void change(View v) {//切换前后摄像头int cameraCount = 0;Camera.CameraInfo cameraInfo = new Camera.CameraInfo();cameraCount = Camera.getNumberOfCameras();//得到摄像头的个数for (int i = 0; i < cameraCount; i++) {Camera.getCameraInfo(i, cameraInfo);//得到每一个摄像头的信息if (cameraPosition == 1) {//现在是后置,变更为前置if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表摄像头的方位,CAMERA_FACING_FRONT前置      CAMERA_FACING_BACK后置mCamera.stopPreview();//停掉原来摄像头的预览mCamera.release();//释放资源mCamera = null;//取消原来摄像头mCamera = Camera.open(i);//打开当前选中的摄像头try {mCamera.setPreviewDisplay(mHolder);//通过surfaceview显示取景画面} catch (IOException e) {e.printStackTrace();}mCamera.startPreview();//开始预览cameraPosition = 0;break;}} else {//现在是前置, 变更为后置if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表摄像头的方位,CAMERA_FACING_FRONT前置      CAMERA_FACING_BACK后置mCamera.stopPreview();//停掉原来摄像头的预览mCamera.release();//释放资源mCamera = null;//取消原来摄像头mCamera = Camera.open(i);//打开当前选中的摄像头try {mCamera.setPreviewDisplay(mHolder);//通过surfaceview显示取景画面} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}mCamera.startPreview();//开始预览cameraPosition = 1;break;}}}}/*** 图片被点击触发的时间** @param v*/public void imageClick(View v) {if (bundle == null) {Toast.makeText(getApplicationContext(), "没有数据", Toast.LENGTH_SHORT).show();} else {Intent intent = new Intent(this, PreviewImageActivity.class);intent.putExtras(bundle);startActivity(intent);}}private final class MyPictureCallback implements Camera.PictureCallback {@Overridepublic void onPictureTaken(byte[] data, Camera camera) {try {bundle = new Bundle();bundle.putByteArray("bytes", data); //将图片字节数据保存在bundle当中,实现数据交换saveToSDCard(data); // 保存图片到sd卡中Toast.makeText(getApplicationContext(), "success", Toast.LENGTH_SHORT).show();
//                camera.startPreview(); // 拍完照后,重新开始预览} catch (Exception e) {e.printStackTrace();}}}public void saveToSDCard(byte[] data) throws IOException {Log.d(TAG, "saveToSDCard");Date date = new Date();SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); // 格式化时间String filename = format.format(date) + ".jpg";File fileFolder = new File(Environment.getExternalStorageDirectory() + "/ansen/");// Environment.getRootDirectory()if (!fileFolder.exists()) {fileFolder.mkdir();}File jpgFile = new File(fileFolder, filename);FileOutputStream outputStream = new FileOutputStream(jpgFile); // 文件输出流outputStream.write(data);outputStream.close();mCamera.startPreview(); // 拍完照后,重新开始预览if (false) {Bitmap b = byteToBitmap(data);// 获取手机屏幕的宽高WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);int windowWidth = windowManager.getDefaultDisplay().getWidth();int windowHight = windowManager.getDefaultDisplay().getHeight();Bitmap bitmap = Bitmap.createBitmap(b, 0, 0, windowWidth, windowHight);// 图片压缩bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);outputStream.flush();}}/*** 把图片byte流转换成bitmap*/private Bitmap byteToBitmap(byte[] data) {BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;Bitmap b = BitmapFactory.decodeByteArray(data, 0, data.length, options);int i = 0;while (true) {if ((options.outWidth >> i <= 1000)&& (options.outHeight >> i <= 1000)) {options.inSampleSize = (int) Math.pow(2.0D, i);options.inJustDecodeBounds = false;b = BitmapFactory.decodeByteArray(data, 0, data.length, options);break;}i += 1;}return b;}/*** 显示surfaceView 数据的接口*/private class SurfaceCallback implements SurfaceHolder.Callback {@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {Log.d(TAG, "surfaceChanged");mParameters = mCamera.getParameters(); // 获取各项参数mParameters.setPictureFormat(PixelFormat.JPEG); // 设置图片格式mParameters.setPreviewSize(width, height); // 设置预览大小mParameters.setPreviewFrameRate(5);  //设置每秒显示4帧mParameters.setPictureSize(width, height); // 设置保存的图片尺寸mParameters.setJpegQuality(80); // 设置照片质量}@Overridepublic void surfaceCreated(SurfaceHolder holder) {Log.d(TAG, "surfaceCreated");mHolder = holder;// SurfaceHolder是系统提供用来设置surfaceView的对象try {mCamera = Camera.open(); // 打开摄像头mCamera.setPreviewDisplay(holder); //通过surfaceview显示取景画面mCamera.setDisplayOrientation(getPreviewDegree(MainActivity.this));// 设置相机的方向mCamera.startPreview(); // 开始预览} catch (Exception e) {e.printStackTrace();Log.e(TAG, "surfaceCreated >>  Exception: " + e.getMessage());}}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {Log.d(TAG, "surfaceDestroyed");if (mCamera != null) {mCamera.release(); // 释放照相机mCamera = null;}}}/*** 点击手机屏幕是,显示两个按钮*/@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:mRelativeLayout.setVisibility(ViewGroup.VISIBLE); // 设置视图可见break;}return true;}@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {switch (keyCode) {case KeyEvent.KEYCODE_CAMERA:if (mCamera != null && event.getRepeatCount() == 0) {// 获取到拍照的图片数据后回调PictureCallback,PictureCallback可以对相片进行保存或传入网络mCamera.takePicture(null, null, new MyPictureCallback());}}return super.onKeyDown(keyCode, event);}// 用于根据手机方向获得相机预览画面旋转的角度public static int getPreviewDegree(Activity activity) {int degree = 0;// 获得手机的方向int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();Log.d(TAG, "rotation : " + rotation);// 根据手机的方向计算相机预览画面应该选择的角度switch (rotation) {case Surface.ROTATION_0:degree = 90;break;case Surface.ROTATION_90:degree = 0;break;case Surface.ROTATION_180:degree = 270;break;case Surface.ROTATION_270:degree = 180;break;}return degree;}
}
<?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:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.tomorrow_p.camera_p.MainActivity"><SurfaceViewandroid:id="@+id/surfaceView"android:layout_width="match_parent"android:layout_height="match_parent" /><LinearLayoutandroid:id="@+id/relativeLayout"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"android:visibility="gone"><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="change"android:text="切换" /><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="takePhoto"android:text="拍照" /><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="imageClick"android:text="预览" /></LinearLayout>
</FrameLayout>
package com.tomorrow_p.camera_p;import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.os.Bundle;
import android.widget.ImageView;public class PreviewImageActivity extends Activity {private ImageView ivPic = null; // 显示图片控件@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.preview_image);ivPic = (ImageView) findViewById(R.id.imageView);setImageBitmap(getImageFormBundle());}public void setImageBitmap(byte[] bytes) {Bitmap cameraBitmap = byte2Bitmap();// 根据拍摄的方向旋转图像(纵向拍摄时要需要将图像选择90度)Matrix matrix = new Matrix();matrix.setRotate(MainActivity.getPreviewDegree(this));cameraBitmap = Bitmap.createBitmap(cameraBitmap, 0, 0, cameraBitmap.getWidth(),cameraBitmap.getHeight(), matrix, true);ivPic.setImageBitmap(cameraBitmap);}public byte[] getImageFormBundle() {Intent intent = getIntent();Bundle data = intent.getExtras();byte[] bytes = data.getByteArray("bytes");return bytes;}/*** 将字节数组的图形数据转换为Bitmap*/private Bitmap byte2Bitmap() {byte[] data = getImageFormBundle();// 将byte数组转换成Bitmap对象Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);return bitmap;}
}

Android自定义相机,切换前后摄像头,照相机拍照相关推荐

  1. Android 自定义相机(可外接摄像头)

    Camera## 相信大家对相机的使用都不陌生吧,下面我给大家分享一下自定义相机 Android提供了Camera来控制拍照,步骤如下: (1)调用Camera的open()方法打开相机. (2)调用 ...

  2. android自定义相机添加蒙板,拍照剪切

    前几天,我写了一篇自定义相机加取景框的文章,这几天,我又研究了一下,进一步写了蒙板,并且拍照出来剪切只留取景框的照片. 加上对之前代码的调整.现在又记录下来 现在的效果是这样的 布局文件 <?x ...

  3. Android 自定义相机 切换相机 参考线(辅助线) 闪光灯 缩放 自动聚焦 Demo

    https://github.com/louisgeek/LouisCustomCameraDemo

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

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

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

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

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

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

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

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

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

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

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

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

最新文章

  1. OpenCV+python:膨胀和腐蚀
  2. 发布Apworks应用开发框架(Alpha版本)
  3. 编程笔试(解析及代码实现):国内各大银行(招商银行/浦发银行等)在线笔试常见题目(猴子吃桃/字符串逆序输出/一段话输出字的个数/单词大小转换等)及其代码实现(Java/Python/C#等)之详细攻略
  4. MATLAB中的wavedec、wrcoef函数简析
  5. android activity启动流程_Activity 启动流程(二)
  6. php中对象的遍历输出,PHP中的对象遍历技巧
  7. git——学习笔记(三)分支管理
  8. 在Linux下编写C程序,怎么检查程序是否有内存泄漏?
  9. hdu 2191悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(多重背包)
  10. Bluetooth L2CAP介绍
  11. IIS5.1安装设置-Sql Sever2008安装设置-移动端设置等必读
  12. 抛弃手册,开启TongWeb+TongLINK/Q的开发方式
  13. java游戏征途2008_醉剑逍遥-征途天下
  14. 微软project下载安装及激活教程
  15. Android ListView 异步加载图片
  16. 链安团队漏洞分析连载(第一期)一一溢出漏洞
  17. lumen时间不准确,少8个小时
  18. Upload 上传:图片上传
  19. 车窗内观春运 镜头记录旅客百态心情
  20. 【智能优化算法】基于全局优化的改进鸡群算法求解单目标优化问题(ECSO)附matlab代码

热门文章

  1. 什么软件可以搜python题_哪个手机软件有python题库
  2. bcs转10 c语言,小弟刚学习C语言,怎么把下段汇编代码转化为C语言程序,请高手指教!!!单片机89c52...
  3. GeoGebra介绍
  4. 计算机上贴硬币图片,为什么商店的计算器要粘个硬币?原来如此!
  5. Linux使用split命令切割大型日志文件 保留文件结尾删除前面的内容
  6. 老子简介(函谷关道德经)
  7. 前端 Git CRLF 与 LF格式的批量转换
  8. C语言指针数组和数组指针详解
  9. 百度站长平台VIP俱乐部服务全面升级
  10. 拓扑排序和关键路径的图形化显示