Android相机开发详解(一)

Android相机开发详解(一)

请支持原创,尊重原创,转载请注明出处:http://blog.csdn.net/kangweijian(来自kangweijian的csdn博客)

Android相机开发能够实现打开相机,前后摄像头切换,摄像预览,保存图片,浏览已拍照图片等相机功能。

Android相机开发详解(一)主要实现打开相机,摄像预览,前后置摄像头切换,保存图片等四个功能。

Android相机开发详解(二)主要实现翻页浏览相片,触控缩放浏览图片,删除图片,发送图片等四个功能。

Android相机开发详解(三)主要实现录像,视频保存,自动对焦,闪光灯控制等四个功能

效果图:

1、 CameraActivity的布局文件,使用FrameLayout布局(activity_camera.xml)

<RelativeLayout 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=".CameraActivity" >

    <FrameLayout
        android:id="@+id/fragmentContainer_camera"
        android:layout_width="match_parent"
        android:layout_height="match_parent"  />

</RelativeLayout>

2、 CameraActivity相机不存在的布局文件(activity_no_camera.xml)

<RelativeLayout 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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".CameraActivity" >

    <TextView
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="未检查到本地有摄像头"  />

</RelativeLayout>

3、 CameraActivity类(CameraActivity.java)

a)      请求窗口特性:无标题

b)     添加窗口特性:全屏

c)      检查摄像头是否存在。根据检查结果进行布局

package com.example.camerademo;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;

public class CameraActivity extends FragmentActivity {

	private final static int REQUEST_DELETE_PHOTO = 1;

	@SuppressLint("NewApi")
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub

		//请求窗口特性:无标题
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		//添加窗口特性:全屏
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

		super.onCreate(savedInstanceState);

		//检查摄像头是否存在。
		PackageManager pm = getPackageManager();
		boolean hasCamera = pm.hasSystemFeature(PackageManager.FEATURE_CAMERA) ||
				pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT) ||
				Build.VERSION.SDK_INT>Build.VERSION_CODES.GINGERBREAD ||
				Camera.getNumberOfCameras()>0;

		//根据检查结果进行布局
		if (!hasCamera) {
			setContentView(R.layout.activity_no_camera);
			return;
		} 

		setContentView(R.layout.activity_camera);

		android.support.v4.app.FragmentManager fm = getSupportFragmentManager();
		android.support.v4.app.Fragment fragment = fm.findFragmentById(R.id.fragmentContainer_camera);

		if (fragment==null) {

			fragment = new CameraFragment();
			fm.beginTransaction().add(R.id.fragmentContainer_camera, fragment).commit();
		}

	} 

}

4、 CameraFragment的布局文件(fragment_camera.xml)

a)      使用FrameLayout布局,双层布局

b)     顶层亦是FrameLayout布局,包含一个ProgressBar进度条控件

c)      底层是LinearLayout布局,左边SurfaceView,右边两个ImageButton

<?xml version="1.0" encoding="UTF-8"?>
<FrameLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="match_parent"
	android:layout_height="match_parent"> 

	<SurfaceView
		android:id="@+id/camera_surfaceView"
	    android:layout_width="match_parent"
	    android:layout_height="match_parent"
	    android:layout_weight="1"/> 

	<FrameLayout
		android:layout_width="match_parent"
		android:layout_height="match_parent"
		android:clickable="true"> 

	    <ImageButton
		    android:id="@+id/camera_rotationview_button"
		    android:layout_width="wrap_content"
		    android:layout_height="wrap_content"
		    android:layout_gravity="left|top"
		    android:layout_marginTop="16dp"
		    android:layout_marginLeft="16dp"
		    android:background="@drawable/button_camera_rotationview"
		    />

		<ImageButton  

		    android:id="@+id/camera_takepicture_button"
		    android:layout_width="wrap_content"
		    android:layout_height="wrap_content"
		    android:layout_gravity="right|top"
		    android:layout_marginTop="16dp"
		    android:layout_marginRight="16dp"
		    android:background="@drawable/button_camera_takepicture"
		    />

		<ImageButton
		    android:id="@+id/camera_view_button"
		    android:layout_width="wrap_content"
		    android:layout_height="wrap_content"
		    android:layout_gravity="right|bottom"
		    android:layout_marginBottom="16dp"
		    android:layout_marginRight="16dp"
		    android:background="@drawable/button_camera_view"
		    />

		<ProgressBar
		    android:id="@+id/camera_progressContainer"
	            style="@android:style/Widget.ProgressBar.Large"
	            android:layout_width="wrap_content"
		    android:layout_height="wrap_content"
		    android:layout_gravity="center"
		    />	    

	</FrameLayout>

</FrameLayout>

5、 CameraFragment类(CameraFragment.java)

a)      相机是一种系统级别的重要资源,因此,很重要一点:需要时使用,用完及时释放。如果忘记释放,除非重启设备,否则其他应用将无法使用相机。

b)     保险起见,我们在onResume()方法中打开相机,在onPause()方法中释放相机。Camera类中打开相机的方法有两个。

i.         open()方法在API第9级以下的级别使用。

ii.         open(int)方法在第9级及第9级以上的级别使用,传入参数0开打设备可用的第一相机(通常指的是后置相机),传入参数1开打设备可用的第二相机(通常指的是前置相机)

c)      使用SurfaceView类配合相机来实现摄像预览。需要实现SurfaceHolder接口,并设置Surface类型:setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS)。但该方法和该常量在API第11级别就已经被弃用。我们使用@SuppressWarnings("deprecation")注解来消除弃用代码的相关警告。

d)     SurfaceHolder是我们与Surface对象联系的纽带。Surface对象代表着原始像素数据的缓冲区。SurfaceView出现在屏幕上时,会创建Surface,这时我们需要把Camera连接到SurfaceHolder上;SurfaceView从屏幕上消失时,Surface随机被销毁,我们再将Camera从SurfaceHolder断开。注意:Surface不存在时,必须保证没有任何内容要在它上面绘制。理想工作状态如图:

e)     为了完成以上任务,SurfaceHolder提供了另一个接口:SurfaceHolder.Callback。该接口有三个方法用来监听Surface生命周期中的事件。

i.         包含SurfaceView的视图层级结构被放到屏幕上时调用该方法。也是与Camera进行关联的地方。

public voidsurfaceCreated(SurfaceHolder surfaceHolder)

ii.         Surface首次显示在屏幕上时调用该方法。通过传入的参数,可以知道Surface的像素格式以及它的宽度和高度。

public voidsurfaceChanged(SurfaceHolder holder, int format, int w, int h)

iii.         SurfaceView从屏幕上移除时,Surface也随即被销毁。也是Camera与其断开关联的地方

public voidsurfaceDestroyed(SurfaceHolder holder)

f)      为了能与SurfaceView无缝贴合,Camera也提供了不同的方法。

i.         为了连接Camera和Surface,设置Surface被实时预览使用setPreviewDisplay(SurfaceHolder holder)

ii.         开始捕捉和绘制预览帧到屏幕上

startPreview()

iii.         停止捕捉和绘制预览帧到屏幕上

stopPreview()

g)     使用Camera的内部类Camera.Parameters来确定预览图片和保存图片的大小

i.         getParameters()返回这个相机的当前参数设置。

ii.             setParameters(Camera.Parameters params)改变这个相机的当前参数设置。

iii.         然后自定义一个找出设备支持的最佳尺寸的方法getBestSupportedSize(List<Size> sizes,int width,int height),接受一组预览尺寸,然后穷举法找出具有最大数目像素的尺寸。

iv.         调用Camera.Parameters类的方法。

1.        getSupportedPictureSizes()得到图片支持的尺寸

2.        getSupportedPreviewSizes()得到预览图片支持的尺寸

3.        setPictureSize(int
width, int height)设置图片的大小尺寸

4.     
setPreviewSize(int
width, int height)设置预览图片的大小尺寸

h)     使用Camera类见名知意的拍照方法takePicture(Camera.ShutterCallback shutter, Camera.PictureCallback raw, Camera.PictureCallback postview, Camera.PictureCallback jpeg)方法

i.         该方法会触发一个异步的图像捕捉,触发相机初始化一系列的回调机制应用于图像捕捉进程中

ii.         该方法有四个回调方法。Camera.ShutterCallback shutter在图像被捕捉时刻触发,它会触发一个快门声音告知用户;PictureCallback raw在未加工图像有效时触发;Camera.PictureCallback postview在被按比例缩放图像有效时触发;Camera.PictureCallback jpeg在压缩图像有效时触发。

iii.         该方法只有在 startPreview()方法调用之后才有效。该方法调用之后预览效果将会停止,如果想要再次预览或者拍摄更多相片,需要再次调用startPreview()方法。

package com.example.camerademo;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.hardware.Camera.Size;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageButton;

public class CameraFragment extends Fragment{

	//startActivityForResult的请求常量
	private final static int REQUEST_DELETE_PHOTO = 1;

	//自定义时间类
	private MyTime mTime=new MyTime(); 

	//相机类
	private Camera mCamera; 

	//预览视图的接口
	private SurfaceHolder mSurfaceHolder;

	//进度条控件
	private View mProgressContainer; 

	//当前打开的是哪一个摄像头
	private int switchCamera=0;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
	} 

	@SuppressWarnings("deprecation")
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		// TODO Auto-generated method stub 

		//生成fragment视图
		View v = inflater.inflate(R.layout.fragment_camera, container,false);

		//隐藏进度条控件
		mProgressContainer = v.findViewById(R.id.camera_progressContainer);
		mProgressContainer.setVisibility(View.INVISIBLE);

		//显示最新照片的缩略图的按钮实例化
		ImageButton viewButton = (ImageButton) v.findViewById(R.id.camera_view_button);
		//最新照片的缩略图的按钮监听器
		viewButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub

				//  跳转ViewPagerActivity,请求ViewPagerActivity执行删除图片操作
				Intent i = new Intent();
				i.setClass(getActivity(), ViewPagerActivity.class);
				startActivityForResult(i, REQUEST_DELETE_PHOTO);

			}
		}); 

		//切换镜头按钮实例化
		ImageButton rotationViewButton = (ImageButton) v.findViewById(R.id.camera_rotationview_button);
		//切换镜头按钮监听器
		rotationViewButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub

				//如果摄像头数目小于等于1,该按钮无效,返回
				if (Camera.getNumberOfCameras() <= 1) {
					return ;
				}

                if(switchCamera == 1) {
                	//停掉原来摄像头的预览,并释放原来摄像头
                	mCamera.stopPreview();
                    mCamera.release();
                    mCamera = null; 

                    //打开当前选中的摄像头
                    switchCamera = 0;
                    mCamera = Camera.open(switchCamera);
                    try {
                    	//通过surfaceview显示取景画面
                      	mCamera.setPreviewDisplay(mSurfaceHolder);
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                  //开始预览
                    mCamera.startPreview();
                 }else {
                	//停掉原来摄像头的预览,并释放原来摄像头
                	mCamera.stopPreview();
                	mCamera.release();
                	mCamera = null;

                	//打开当前选中的摄像头
                	switchCamera = 1;
                	mCamera = Camera.open(switchCamera);

                    try {
                    	//通过surfaceview显示取景画面
                    	mCamera.setPreviewDisplay(mSurfaceHolder);
                    } catch (IOException e) {
                            // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    //开始预览
                    mCamera.startPreview();
                }
			}

		});

		//照相按钮实例化
		ImageButton takePictureButton = (ImageButton) v.findViewById(R.id.camera_takepicture_button);
		//照相按钮监听器
		takePictureButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub 

				if (mCamera!=null) {
					//相机的拍照方法
					mCamera.takePicture(

							//第一个回调方法,快门回调方法
							new ShutterCallback() {
								@Override
								public void onShutter() {
									// TODO Auto-generated method stub
									//该方法回触发快门声音告知用户,并设置进度条显示
									mProgressContainer.setVisibility(View.VISIBLE);
								}
							}
							//第二个,第三个回调方法为空
							, null,null,
							//最后一个回调方法,jpg图像回调方法
							new PictureCallback() {

								@Override
								public void onPictureTaken(byte[] date, Camera camera) {
									// TODO Auto-generated method stub

									//根据当前时间自定义格式生成文件名
									String filename = mTime.getYMDHMS()+".jpg";
									//文件输出流
									FileOutputStream os = null;
									//默认文件保存成功
									boolean success = true;

									try {
										//私有打开应用沙盒文件夹下文件
										os = getActivity().openFileOutput(filename, Context.MODE_PRIVATE);
										//写文件
										os.write(date);

									} catch (Exception e) {
										// TODO: handle exception
										success = false;
									}finally{

										try {
											if (os != null) {
												os.close();
											}
										} catch (Exception e) {
											// TODO: handle exception
											success = false;
										}
									}

									if (success) {
										//如果文件保存成功,进度条隐藏
										mProgressContainer.setVisibility(View.INVISIBLE);
										//再次预览
										try {
											mCamera.startPreview();
										} catch (Exception e) {
											// TODO: handle exception
											mCamera.release();
											mCamera=null;
										}
									}
								}
							});
				}

			}
		});  

		//预览视图实例化
		SurfaceView mSurfaceView = (SurfaceView) v.findViewById(R.id.camera_surfaceView);
		//得到预览视图接口
		mSurfaceHolder = mSurfaceView.getHolder();
		//设置预览视图接口类型
		mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
		//添加预览视图接口的回调程序,监听视图的生命周期
		mSurfaceHolder.addCallback(new Callback() {

			@Override
			public void surfaceCreated(SurfaceHolder surfaceHolder) {
				// TODO Auto-generated method stub

				//当SurfaceView的视图层级结构被放到屏幕上时候,连接Camera和Surface
				try {

					if (mCamera!=null) {
						mCamera.setPreviewDisplay(surfaceHolder);
					}

				} catch (Exception e) {
					// TODO: handle exception
				}

			}

			@Override
			public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
				// TODO Auto-generated method stub 

				//当Surface首次显示在屏幕上时候,设置好相机参数,开始预览
				if (mCamera==null) {
					return;
				} 

				Camera.Parameters parameters = mCamera.getParameters();
				Size s = getBestSupportedSize(parameters.getSupportedPreviewSizes(), w, h);

				parameters.setPreviewSize(s.width, s.height); 

				s = getBestSupportedSize(parameters.getSupportedPictureSizes(), w, h);

				parameters.setPictureSize(s.width, s.height); 

				mCamera.setParameters(parameters);

				try {
					mCamera.startPreview();
				} catch (Exception e) {
					// TODO: handle exception
					mCamera.release();
					mCamera=null;
				}
			}
			@Override
			public void surfaceDestroyed(SurfaceHolder holder) {
				// TODO Auto-generated method stub

				//当视图从屏幕上移除的时候,停止预览
				if (mCamera!=null) {
					mCamera.stopPreview();
				}
			}

		});

		return v;
	}

	/******************************************]
	 *
	 * 穷举法找出具有最大数目像素的尺寸
	 *
	 * @param sizes
	 * @param width
	 * @param height
	 * @return
	 */
	public Size getBestSupportedSize(List<Size> sizes,int width,int height) {
		Size bestSize = sizes.get(0);
		int largestArea = bestSize.width*bestSize.height;
		for (Size s :sizes) {
			int area =s.width*s.height;
			if (area>largestArea) {
				bestSize=s;
				largestArea = area;
			}
		}
		return bestSize;
	}

	//接收活动结果,响应startActivityForResult()
	@Override
	public void onActivityResult(int request, int result, Intent mIntent) {
		// TODO Auto-generated method stub 

		if (request == REQUEST_DELETE_PHOTO) {

			if (result == Activity.RESULT_OK) {

				//  跳转ViewPagerActivity,请求ViewPagerActivity执行删除图片操作
				int requestCode = 1;
				Intent i = new Intent();
				i.setClass(getActivity(), ViewPagerActivity.class);
				startActivityForResult(i, requestCode);

			}

		}

	}

	@Override
	public void onPause() {
		// TODO Auto-generated method stub
		super.onPause();
		System.out.println("onPause");
		//程序中止暂停时,释放Camera
		if (mCamera!=null) {
			mCamera.release();
			mCamera=null;
		}

	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		System.out.println("onDestroy");
	}

	@Override
	public void onStop() {
		// TODO Auto-generated method stub
		super.onStop();
		System.out.println("onStop");
	}

	@SuppressLint("NewApi")
	@Override
	public void onResume() {
		// TODO Auto-generated method stub
		super.onResume(); 

		//程序运行时,打开Camera
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
			mCamera = Camera.open(switchCamera);
		}else {
			mCamera = Camera.open();
		}

	}

}

6、 添加权限和Activity特性(AndroidMainfest.xml)

a)      权限:

<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android:hardware.camera"/>
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>  

b)     Activity特性:

android:screenOrientation="landscape"

请支持原创,尊重原创,转载请注明出处:http://blog.csdn.net/kangweijian(来自kangweijian的csdn博客)

学习《Android编程权威指南》心得与笔记                    by2015.2.10早

时间: 2024-10-25 13:16:17

Android相机开发详解(一)的相关文章

Android 相机开发详解

在android中应用相机功能,一般有两种:一种是直接调用系统相机,一种自己写的相机.我将分别演示两种方式的使用:第一种:是使用Intent跳转到系统相机,action为:android.media.action.STILL_IMAGE_CAMERA关键代码: Intent intent = new Intent(); //调用照相机 intent.setAction("android.media.action.STILL_IMAGE_CAMERA"); startActivity(i

Android开发经典书籍下载——《Android 4高级编程》《疯狂Android讲义》《Android应用开发详解(郭宏志)》《Android应用案例开发大全》《Android 3D游戏开发技术》

这是我收集的关于android开发方面的经典书籍,高清PDF电子版,可以在我的百度网盘免费下载,希望对需要的朋友有帮助. 目录: <Android 4高级编程>(附完整源代码) <疯狂Android讲义> <Android应用开发详解(郭宏志)> <Android应用案例开发大全> <Android 3D游戏开发技术> <Android内核剖析 柯元旦> <深入理解Android  卷1> <深入理解Android

Android WebView 开发详解

Android WebView 开发详解 1.概览: Android WebView 做为承载网页的载体控件,他在网页显示的过程中会产生一些事件,并回调给我们的应用程序,以便我们在网页加载过程中做应用程序想处理的事情.比如说客户端需要显示网页加载的进度.网页加载发生错误等等事件. WebView提供两个事件回调类给应用层,分别为WebViewClient,WebChromeClient开发者可以继承这两个类,接手相应事件处理.WebViewClient 主要提供网页加载各个阶段的通知,比如网页开

【转】【Android应用开发详解】第01期:第三方授权认证(一)实现第三方授权登录、分享以及获取用户资料

转载请注明出处:http://blog.csdn.net/yangyu20121224/article/details/9057257 由于公司项目的需要,要实现在项目中使用第三方授权登录以及分享文字和图片等这样的效果,几经波折,查阅了一番资料,做了一个Demo.实现起来的效果还是不错的,不敢独享,决定写一个总结的教程,供大家互相交流.学习和参考,博主只求能和大家共同进步.希望能多多支持! 这篇文章中,我们使用到了Share SDK,它是为iOS.Android.WP8的APP提供社会化功能的一

Android WebView 开发详解(一)

转载请注明出处  http://blog.csdn.net/typename/article/details/39030091 powered by meichal zhao 概览: Android WebView在Android平台上是一个特殊的View, 他能用来显示网页,这个类可以被用来在你的app中仅仅显示一张在线的网页,还可以用来开发浏览器.WebView内部实现是采用渲染引擎来展示view的内容,提供网页前进后退,网页放大,缩小,搜索,前端开发者可以使用web inspector(A

Android Widget 开发详解(二)

转载请标明出处:http://blog.csdn.net/sk719887916/article/details/47027263 不少开发项目中都会有widget功能,别小瞧了它,他也是android的七大组件之一,对widget陌生的朋友可以阅读下我的上篇文章< Android Widget工作原理详解(一)> 今天我们就实现一个可以滑动的widet,熟悉下一个普通widget的开发. 一 创建AppWidgetProvider 此类是widget的控制核心,主要控制添加,删除,更新等.他

Android WebView 开发详解(二)

转载请注明出处  http://blog.csdn.net/typename/article/details/39495409 powered by meichal zhao 概览: Android WebView 做为承载网页的载体控件,他在网页显示的过程中会产生一些事件,并回调给我们的应用程序,以便我们在网页加载过程中做应用程序想处理的事情.比如说客户端需要显示网页加载的进度.网页加载发生错误等等事件. WebView提供两个事件回调类给应用层,分别为WebViewClient,WebChr

Android WebView 开发详解(三)

转载请注明出处   http://blog.csdn.net/typename/article/details/40302351 powered by miechal zhao 概览 Android WebView提供展示网页,也提供我们应用程序对网页加载的一些定制,比如我们为了减少网络数据可以设置当前加载的页面不能显示图片,如果是pc网址在pad上访问我们可以提供用户一种概览模式的浏览方式,可以提供放大网页字体等定制功能.Android 提供管理WebView的一些setting的类WebSe

【转】Android Camera 相机开发详解

在Android 5.0(SDK 21)中,Google使用Camera2替代了Camera接口.Camera2在接口和架构上做了巨大的变动, 但是基于众所周知的原因,我们还必须基于 Android 4.+ 系统进行开发.本文介绍的是Camera接口开发及其使用方法,通过本文章,你将全面地学会Camera接口的开发流程. 本图文与GitHubPages原文均为本人原创 Paste_Image.png 调用系统相机/其它App完成拍摄操作 如果你的App的需求只是调用摄像头拍照并拿到照片,老司机的