android Camera摄像头-Surface view 预览拍照 并将拍的照片插入到系统图库
2017-09-22 09:42
591 查看
由于最近项目需求,需要做一个摄像头预览拍照的功能。写完之后,来写下总结:
1.Android 利用系统Camera来预览拍照,步骤如下:
(1)调用Camera的open()方法打开相机。
(2)调用Camera的getParameters()获取拍照参数,该方法返回一个Cmera.Parameters对象。
(3)调用Camera.Parameters对象对照相的参数进行设置。
(4)调用Camera的setParameters(),并将Camera.Parameters对象作为参数传入,这样就可以对拍照进行参数控制,Android2.3.3以后不用设置。
(5)调用Camerade的startPreview()的方法开始预览取景,在之前需要调用Camera的setPreviewDisplay(SurfaceHolder holder)设置使用哪个SurfaceView来显示取得的图片。
(6)调用Camera的takePicture()方法进行拍照。
(7)程序结束时,要调用Camera的stopPreview()方法停止预览,并且通过Camera.release()来释放资源。
2.预览到的画面是通过SurfaceView进行显示的。然后SurfaceHolder是系统提供的一个用来设置SurfaceView的对象,可以通过SurfaceView对象的getHolder()方法来获得。SurfaceHolder.Callback是Holder用来显示SurfaceView数据的接口,接口有3个方法,分别代表不同的时候。
(1)SurfaceView 被创建的时候
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
(2)SurfaceView 改变的时候
public void surfaceCreated(SurfaceHolder holder)
(3)SurfaceView被销毁的时候
public void surfaceDestroyed(SurfaceHolder holder)
2.1根据以上分析可知其中(1)(2)(3)(4)(5)步可以在SurfaceView created的时候,也就是SurfaceHolder.Callback 接口的回调函数surfaceCreated(SurfaceHolder holder)那里。在设置预览大小和拍照图片大小的时候,如果你的屏幕方向不是固定的话,最好是可以根据屏幕实时的转向来选择不同的长宽,这样才不会出现预览拉伸的情况。还有就是设置预览大小和图片大小的时候,是有限制的,不能随便乱写。
例如以下这些:1920x1080 1280x720 800x480 768x432 720x480 640x480 576x432 480x320 384x288
352x288 320x240 240x160 176x144
2.2 当SurfaceView 改变的时候我们要做的就是重新打开预览(即停止预览,然后又重新打开预览)
2.3为了更好的进行内存管理,让app不至于有过多的内存碎片,因此在SurfaceView销毁的时候,我们应该停止预览,release Camera,然后告诉虚拟机回收不用的对象。
3.权限问题,由于系统的升级,对于一些敏感权限,系统要求你必须动态获取。而写权限和Camera就属于这类敏感权限,因此必须动态获取
权限回调的接口 重写Activity的onRequestPermissionResult()方法即可
AndroidManifest中静态申请的权限:
4.点击拍照按钮进行拍照 调用camera对象的takePicture方法即可。第三个参数是拍完照的时候的数据放回的接口。
在存储照片的时候,为了不影响主线程的流畅性,应该将写入的方法放到子线程中去。带写入完成的时候,插入到系统图库即可。
5.切换摄像头,一般手机都是默认有前后摄像头的,
6 demo效果图
7完整代码
布局代码:
Activity代码:
参考链接:http://blog.csdn.net/gf771115/article/details/19438409
以上就是摄像头预览拍照的所有介绍。希望对你有所帮助。也感谢其他博主的分享
1.Android 利用系统Camera来预览拍照,步骤如下:
(1)调用Camera的open()方法打开相机。
(2)调用Camera的getParameters()获取拍照参数,该方法返回一个Cmera.Parameters对象。
(3)调用Camera.Parameters对象对照相的参数进行设置。
(4)调用Camera的setParameters(),并将Camera.Parameters对象作为参数传入,这样就可以对拍照进行参数控制,Android2.3.3以后不用设置。
(5)调用Camerade的startPreview()的方法开始预览取景,在之前需要调用Camera的setPreviewDisplay(SurfaceHolder holder)设置使用哪个SurfaceView来显示取得的图片。
(6)调用Camera的takePicture()方法进行拍照。
(7)程序结束时,要调用Camera的stopPreview()方法停止预览,并且通过Camera.release()来释放资源。
2.预览到的画面是通过SurfaceView进行显示的。然后SurfaceHolder是系统提供的一个用来设置SurfaceView的对象,可以通过SurfaceView对象的getHolder()方法来获得。SurfaceHolder.Callback是Holder用来显示SurfaceView数据的接口,接口有3个方法,分别代表不同的时候。
(1)SurfaceView 被创建的时候
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
(2)SurfaceView 改变的时候
public void surfaceCreated(SurfaceHolder holder)
(3)SurfaceView被销毁的时候
public void surfaceDestroyed(SurfaceHolder holder)
2.1根据以上分析可知其中(1)(2)(3)(4)(5)步可以在SurfaceView created的时候,也就是SurfaceHolder.Callback 接口的回调函数surfaceCreated(SurfaceHolder holder)那里。在设置预览大小和拍照图片大小的时候,如果你的屏幕方向不是固定的话,最好是可以根据屏幕实时的转向来选择不同的长宽,这样才不会出现预览拉伸的情况。还有就是设置预览大小和图片大小的时候,是有限制的,不能随便乱写。
例如以下这些:1920x1080 1280x720 800x480 768x432 720x480 640x480 576x432 480x320 384x288
352x288 320x240 240x160 176x144
@Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub //当surfaceview创建时开启相机 if(camera == null) { camera = Camera.open(); try { //设置参数,开始预览 Camera.Parameters params = camera.getParameters(); params.setPictureFormat(PixelFormat.JPEG);//图片格式 params.setPreviewSize(PREVIEW_WIDTH, PREVIEW_HEIGHT);//预览 params.setPictureSize(PREVIEW_WIDTH, PREVIEW_HEIGHT);//图片大小 params.setJpegQuality(100); camera.setParameters(params);//将参数设置到我的camera camera.setPreviewDisplay(holder);//通过surfaceview显示取景画面 camera.startPreview();//开始预览 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
2.2 当SurfaceView 改变的时候我们要做的就是重新打开预览(即停止预览,然后又重新打开预览)
@Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // TODO Auto-generated method stub if (holder.getSurface() == null) { return; } try { camera.stopPreview(); } catch (Exception e) { e.printStackTrace(); } try { camera.setPreviewDisplay(holder); camera.startPreview(); } catch (Exception e) 1af88 { Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } }
2.3为了更好的进行内存管理,让app不至于有过多的内存碎片,因此在SurfaceView销毁的时候,我们应该停止预览,release Camera,然后告诉虚拟机回收不用的对象。
@Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub //当surfaceview关闭时,关闭预览并释放资源 camera.stopPreview(); camera.release(); camera = null; holder = null; surface = null; }
3.权限问题,由于系统的升级,对于一些敏感权限,系统要求你必须动态获取。而写权限和Camera就属于这类敏感权限,因此必须动态获取
private void requestPermission() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED ||ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED ) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.CAMERA}, REQUEST_EXTERNAL_STORAGE); } }
权限回调的接口 重写Activity的onRequestPermissionResult()方法即可
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (grantResults.length > 0 && requestCode == REQUEST_EXTERNAL_STORAGE && grantResults[0] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(MainActivity.this, R.string.granted, Toast.LENGTH_LONG).show(); } else { Toast.makeText(MainActivity.this, R.string.nogradnted, Toast.LENGTH_LONG).show(); } }
AndroidManifest中静态申请的权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera" />
4.点击拍照按钮进行拍照 调用camera对象的takePicture方法即可。第三个参数是拍完照的时候的数据放回的接口。
camera.autoFocus(new Camera.AutoFocusCallback() {//自动对焦 @Override public void onAutoFocus(boolean success, Camera camera) { // TODO Auto-generated method stub if(success) { camera.takePicture(null, null, picture_callback);//将拍摄到的照片给自定义的对象 } } });
在存储照片的时候,为了不影响主线程的流畅性,应该将写入的方法放到子线程中去。带写入完成的时候,插入到系统图库即可。
//创建jpeg图片回调数据对象 Camera.PictureCallback picture_callback = new Camera.PictureCallback() { @Override public void onPictureTaken(final byte[] data, Camera camera) { //将保存图片的放到子线程中去,别影响主线程 new Thread(new Runnable() { @Override public void run() { try { Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); //自定义文件保存路径 以拍摄时间区分命名 filepath = "/sdcard/myCamera/"+new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())+ ".jpg"; final File file = new File(filepath); if (!file.exists()) { file.getParentFile().mkdir(); } BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);//将图片压缩的流里面 bos.flush();// 刷新此缓冲区的输出流 bos.close();// 关闭此输出流并释放与此流有关的所有系统资源 bitmap.recycle();//回收bitmap空间 runOnUiThread(new Runnable() { @Override public void run() { try { //图片插入到系统图库中 MediaStore.Images.Media.insertImage(getContentResolver(), filepath, file.getName(), null); } catch (FileNotFoundException e) { e.printStackTrace(); } Toast.makeText(MainActivity.this, "照片保存成功" + filepath, Toast.LENGTH_SHORT).show(); } }); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); camera.stopPreview();//关闭预览 处理数据 camera.startPreview();//数据处理完后继续开始预览 } };
5.切换摄像头,一般手机都是默认有前后摄像头的,
//切换前后摄像头 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后置 camera.stopPreview();//停掉原来摄像头的预览 camera.release();//释放资源 camera = null;//取消原来摄像头 camera = Camera.open(i);//打开当前选中的摄像头 try { camera.setPreviewDisplay(holder);//通过surfaceview显示取景画面 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } camera.startPreview();//开始预览 cameraPosition = 0; break; } } else { //现在是前置, 变更为后置 if(cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {/ // /代表摄像头的方位,CAMERA_FACING_FRONT前置 // CAMERA_FACING_BACK后置 camera.stopPreview();//停掉原来摄像头的预览 camera.release();//释放资源 camera = null;//取消原来摄像头 camera = Camera.open(i);//打开当前选中的摄像头 try { camera.setPreviewDisplay(holder);//通过surfaceview显示取景画面 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } camera.startPreview();//开始预览 cameraPosition = 1; break; } } }
6 demo效果图
7完整代码
布局代码:
<?xml version="1.0" encoding="utf-8"?> <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" > <SurfaceView android:layout_centerInParent="true" android:id="@+id/cp_surface" android:layout_width="match_parent" android:layout_height="match_parent" /> <ImageView android:layout_alignLeft="@+id/cp_surface" android:layout_alignTop="@+id/cp_surface" android:id="@+id/iv_back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" android:src="@mipmap/back"/> <ImageView android:layout_alignRight="@+id/cp_surface" android:layout_alignTop="@+id/cp_surface" android:id="@+id/iv_switch_camera" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" android:src="@mipmap/swap"/> <ImageView android:layout_alignBottom="@+id/cp_surface" android:layout_centerHorizontal="true" android:layout_margin="10dp" android:id="@+id/iv_shutter" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/take_photo"/> </RelativeLayout>
Activity代码:
import android.Manifest;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback{
private static final String TAG = "MainActivity";
private static final int REQUEST_EXTERNAL_STORAGE = 10086;
private static final int PREVIEW_WIDTH = 1920;
private static final int PREVIEW_HEIGHT = 1080;
private ImageView iv_back, iv_switch_camera;//返回和切换前后置摄像头
private SurfaceView surface;
private ImageView iv_shutter;//快门
private SurfaceHolder holder;
private Camera camera;//声明相机
private String filepath = "";//照片保存路径
private int cameraPosition = 1;//0代表前置摄像头,1代表后置摄像头
@Override
protected 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);//拍照过程屏幕一直处于高亮
//设置手机屏幕朝向,一共有7种
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
//SCREEN_ORIENTATION_BEHIND: 继承Activity堆栈中当前Activity下面的那个Activity的方向
//SCREEN_ORIENTATION_LANDSCAPE: 横屏(风景照) ,显示时宽度大于高度
//SCREEN_ORIENTATION_PORTRAIT: 竖屏 (肖像照) , 显示时高度大于宽度
//SCREEN_ORIENTATION_SENSOR 由重力感应器来决定屏幕的朝向,它取决于用户如何持有设备,当设备被旋转时方向会随之在横屏与竖屏之间变化
//SCREEN_ORIENTATION_NOSENSOR: 忽略物理感应器——即显示方向与物理感应器无关,不管用户如何旋转设备显示方向都不会随着改变("unspecified"设置除外)
//SCREEN_ORIENTATION_UNSPECIFIED: 未指定,此为默认值,由Android系统自己选择适当的方向,选择策略视具体设备的配置情况而定,因此不同的设备会有不同的方向选择
//SCREEN_ORIENTATION_USER: 用户当前的首选方向
setContentView(R.layout.activity_main);
initView();
setListener();
requestPermission();
}
private void initView() {
iv_back = (ImageView) findViewById(R.id.iv_back);
iv_switch_camera = (ImageView) findViewById(R.id.iv_switch_camera);
surface = (SurfaceView) findViewById(R.id.cp_surface);
iv_shutter = (ImageView) findViewById(R.id.iv_shutter);
holder = surface.getHolder();//获得句柄
holder.addCallback(this);//添加回调
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//surfaceview不维护自己的缓冲区,等待屏幕渲染引擎将内容推送到用户面前
}
private void setListener() {
//设置监听
iv_back.setOnClickListener(listener);
iv_switch_camera.setOnClickListener(listener);
iv_shutter.setOnClickListener(listener);
}
private void requestPermission() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED ||ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED ) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.CAMERA}, REQUEST_EXTERNAL_STORAGE); } }
//响应点击事件
View.OnClickListener listener = new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.iv_back:
//返回
MainActivity.this.finish();
break;
case R.id.iv_switch_camera:
//切换前后摄像头
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后置
camera.stopPreview();//停掉原来摄像头的预览
camera.release();//释放资源
camera = null;//取消原来摄像头
camera = Camera.open(i);//打开当前选中的摄像头
try {
camera.setPreviewDisplay(holder);//通过surfaceview显示取景画面
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
camera.startPreview();//开始预览
cameraPosition = 0;
break;
}
} else {
//现在是前置, 变更为后置
if(cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表摄像头的方位,CAMERA_FACING_FRONT前置 CAMERA_FACING_BACK后置
camera.stopPreview();//停掉原来摄像头的预览
camera.release();//释放资源
camera = null;//取消原来摄像头
camera = Camera.open(i);//打开当前选中的摄像头
try {
camera.setPreviewDisplay(holder);//通过surfaceview显示取景画面
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
camera.startPreview();//开始预览
cameraPosition = 1;
break;
}
}
}
break;
case R.id.iv_shutter:
//快门
camera.autoFocus(new Camera.AutoFocusCallback() {//自动对焦 @Override public void onAutoFocus(boolean success, Camera camera) { // TODO Auto-generated method stub if(success) { camera.takePicture(null, null, picture_callback);//将拍摄到的照片给自定义的对象 } } });
break;
}
}
};
/*surfaceHolder他是系统提供的一个用来设置surfaceView的一个对象,而它通过surfaceView.getHolder()这个方法来获得。
Camera提供一个setPreviewDisplay(SurfaceHolder)的方法来连接*/
//SurfaceHolder.Callback,这是个holder用来显示surfaceView 数据的接口,他必须实现以下3个方法
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
if (holder.getSurface() == null) {
return;
}
try {
camera.stopPreview();
} catch (Exception e) {
e.printStackTrace();
}
try {
camera.setPreviewDisplay(holder);
camera.startPreview();
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
@Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub //当surfaceview创建时开启相机 if(camera == null) { camera = Camera.open(); try { //设置参数,开始预览 Camera.Parameters params = camera.getParameters(); params.setPictureFormat(PixelFormat.JPEG);//图片格式 params.setPreviewSize(PREVIEW_WIDTH, PREVIEW_HEIGHT);//预览 params.setPictureSize(PREVIEW_WIDTH, PREVIEW_HEIGHT);//图片大小 params.setJpegQuality(100); camera.setParameters(params);//将参数设置到我的camera camera.setPreviewDisplay(holder);//通过surfaceview显示取景画面 camera.startPreview();//开始预览 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
@Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub //当surfaceview关闭时,关闭预览并释放资源 camera.stopPreview(); camera.release(); camera = null; holder = null; surface = null; }
//创建jpeg图片回调数据对象 Camera.PictureCallback picture_callback = new Camera.PictureCallback() { @Override public void onPictureTaken(final byte[] data, Camera camera) { //将保存图片的放到子线程中去,别影响主线程 new Thread(new Runnable() { @Override public void run() { try { Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); //自定义文件保存路径 以拍摄时间区分命名 filepath = "/sdcard/myCamera/"+new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())+ ".jpg"; final File file = new File(filepath); if (!file.exists()) { file.getParentFile().mkdir(); } BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);//将图片压缩的流里面 bos.flush();// 刷新此缓冲区的输出流 bos.close();// 关闭此输出流并释放与此流有关的所有系统资源 bitmap.recycle();//回收bitmap空间 runOnUiThread(new Runnable() { @Override public void run() { try { //图片插入到系统图库中 MediaStore.Images.Media.insertImage(getContentResolver(), filepath, file.getName(), null); } catch (FileNotFoundException e) { e.printStackTrace(); } Toast.makeText(MainActivity.this, "照片保存成功" + filepath, Toast.LENGTH_SHORT).show(); } }); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); camera.stopPreview();//关闭预览 处理数据 camera.startPreview();//数据处理完后继续开始预览 } };
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (grantResults.length > 0 && requestCode == REQUEST_EXTERNAL_STORAGE && grantResults[0] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(MainActivity.this, R.string.granted, Toast.LENGTH_LONG).show(); } else { Toast.makeText(MainActivity.this, R.string.nogradnted, Toast.LENGTH_LONG).show(); } }
}
参考链接:http://blog.csdn.net/gf771115/article/details/19438409
以上就是摄像头预览拍照的所有介绍。希望对你有所帮助。也感谢其他博主的分享
相关文章推荐
- 基于Android TextureView与SurfaceTexture实现相机Camera拍照预览与保存照片
- 基于Android TextureView与SurfaceTexture实现相机Camera拍照预览与保存照片
- Android surfaceview 自定义相机 拍照(闪光灯、前后摄像头)
- 利用SurfaceView预览,拍照且保存至相册
- 玩转Android Camera开发(一):Surfaceview预览Camera,基础拍照功能完整demo
- 玩转Android Camera开发(一):Surfaceview预览Camera,基础拍照功能完整demo
- 调用Android系统摄像头进行拍照以及从图库选择图片
- Android相机(摄像头)圆形预览窗口,圆形SurfaceView
- 摄像头预览的背景带矩形框效果的实现(原理:双surfaceview,顶层画矩形框,底层预览视频)
- 调用手机摄像头拍照和从图库中选取照片以及得到照片后的备份
- 玩转Android Camera开发(一):Surfaceview预览Camera,基础拍照功能完整demo
- Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整实现(原理:底层SurfaceView+上层绘制ImageView)
- android拍照选择图库后将照片剪裁压缩显示到imageview上
- Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整实现(原理:底层SurfaceView+上层绘制ImageView)
- 通过Camera、SurfaceView、自己实现拍照及预览效果
- Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整实现(原理:底层SurfaceView+上层绘制ImageView)
- Android开发 摄像头SurfaceView预览 背景带矩形框 实现(原理:双surfaceview,顶层画矩形框,底层预览视频)
- 玩转Android Camera开发(一):Surfaceview预览Camera,基础拍照功能完整demo
- Android7.0调用系统相机拍照、读取系统相册照片+CropImageView剪裁、旋转、翻转照片
- android开发摄像头开发,在自己的SurfaceView里预览,并且解决摄像头预览变形问题--懒人笔记02