当前位置: 代码迷 >> Android >> Android 照相机实例
  详细解决方案

Android 照相机实例

热度:23   发布时间:2016-05-01 16:55:00.0
Android 相机实例
在android中应用相机功能,一般有两种:一种是直接调用系统相机,一种自己写的相机。我将分别演示两种方式的使用:

       第一种:是使用Intent跳转到系统相机,action为:android.media.action.STILL_IMAGE_CAMERA

关键代码:

Java代码:
01.Intent intent = new Intent(); //调用照相机

02.intent.setAction("android.media.action.STILL_IMAGE_CAMERA");

03.startActivity(intent);
复制代码      例子:CameraTest_2.java

Java代码:

01.import android.app.Activity;

02.import android.content.Intent;

03.import android.os.Bundle;

04.

05.public class CameraTest_2 extends Activity {

06./** Called when the activity is first created. */

07.@Override

08.public void onCreate(Bundle savedInstanceState) {

09.super.onCreate(savedInstanceState);

10.setContentView(R.layout.main);

11.Intent intent = new Intent(); //调用照相机

12.intent.setAction("android.media.action.STILL_IMAGE_CAMERA");

13.startActivity(intent);

14.}

15.

16.}
复制代码
       想要测试的,可以直接新建一个项目,并且把主activity的代码换成上面的,然后运行,我测试了一下,上面这个代码并不需要权限,毕竟只是调用系统自带的程序。
       当然网上还有一些其他相关的调用方法,只要设置对了action,那么系统就会调用系统自带的相机.

       第二种:
     (1)首先我们要自己创建一个照相,必须考虑用什么控件显示照相机中的预览效果,显然android已经帮我们做好了选择,那就是SurfaceView,而控制SurfaceView则需要一个surfaceHolder,他是系统提供的一个用来设置surfaceView的一个对象,而它通过surfaceView.getHolder()这个方法来获得。而Camera提供一个setPreviewDisplay(SurfaceHolder)的方法来连接.surfaceHolder,并通过他来控制surfaceView,而我们则使用android的Camera类提供了startPreview()和stopPreview()来开启和关闭预览.

       关系如下:
       Camera -- -->SurfaceHolder------>SurfaceView.
     (2)知道怎么预览,当然也要知道怎么开启相机.Camera.open()这是个静态方法,如果相机没有别人用着,则会返回一个 相机引用,如果被人用着,则会抛出异常。很奇怪的是,这个方法,不能随便放,如放在构造方法或者onCreate()方法中,都会照成没有预览效果.
     (3)SurfaceHolder.Callback,这是个holder用来显示surfaceView 数据的接口,他分别必须实现3个方法
       surfaceCreated()这个方法是surface 被创建后调用的
       surfaceChanged()这个方法是当surfaceView发生改变后调用的
       surfaceDestroyed()这个是当surfaceView销毁时调用的.
       surfaceHolde通过addCallBack()方法将响应的接口绑定到他身上.
       surfaceHolder还必须设定一个setType()方法,查看api的时候,发现这个方法已经过时,但是没有写,又会报错。。各种奇怪。
     (4)我用以上知识写了一个MySurfaceView类,他继承于SurfaceView,并在里面实现了照相机的预览功能.这个我觉得最简单的照相机预览代码:

MySurfaceView.java

Java代码:

01.import java.io.IOException;

02.import android.content.Context;

03.import android.graphics.PixelFormat;

04.import android.hardware.Camera;

05.import android.util.Log;

06.import android.view.SurfaceHolder;

07.import android.view.SurfaceView;

08.

09.public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback{

10.SurfaceHolder holder;

11.Camera myCamera;

12.

13.public MySurfaceView(Context context) {

14.super(context);

15.holder = getHolder();//获得surfaceHolder引用

16.holder.addCallback(this);

17.holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//设置类型

18.}

19.

20.@Override

21.public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

22.myCamera.startPreview();

23.}

24.@Override

25.public void surfaceCreated(SurfaceHolder holder) {

26.// TODO Auto-generated method stub

27.if(myCamera == null) {

28.myCamera = Camera.open();//开启相机,不能放在构造函数中,不然不会显示画面.

29.try {

30.myCamera.setPreviewDisplay(holder);

31.} catch (IOException e) {

32.// TODO Auto-generated catch block

33.e.printStackTrace();

34.}

35.}

36.}

37.

38.@Override

39.public void surfaceDestroyed(SurfaceHolder holder) {

40.// TODO Auto-generated method stub

41.myCamera.stopPreview();//停止预览

42.myCamera.release();//释放相机资源

43.myCamera = null;

44.Log.d("ddd", "4");

45.}

46.}
复制代码
       CameraTest_3.java

Java代码:

01.import android.app.Activity;

02.import android.os.Bundle;

03.import android.view.View;

04.import android.view.View.OnClickListener;

05.

06.public class CameraTest_3 extends Activity {

07./** Called when the activity is first created. */

08.MySurfaceView mySurface;

09.@Override

10.public void onCreate(Bundle savedInstanceState) {

11.super.onCreate(savedInstanceState);

12.mySurface = new MySurfaceView(this);

13.setContentView(mySurface);

14.}

15.

16.}


而且必须给应用添加权限: <uses-permission android:name="android.permission.CAMERA"></uses-permission>
        (5)能够预览了,接下来就是拍照了,拍照用到了一个camera.tackPiture()这个方法,这个方法,有三个参数分别是ShutterCallBack shutter,PictureCallBack raw,PictureCallBack jpeg.

        下面是对他们的实现

Java代码:

01.private ShutterCallback shutter = new ShutterCallback() {

02.@Override

03.public void onShutter() {

04.// TODO Auto-generated method stub

05.Log.d("ddd", "shutter");

06.}

07.};

08.

09.private PictureCallback raw = new PictureCallback() {

10.@Override

11.public void onPictureTaken(byte[] data, Camera camera) {

12.// TODO Auto-generated method stub

13.Log.d("ddd", "raw");

14.}

15.};

16.

17.

18.private PictureCallback jpeg = new PictureCallback() {

19.@Override

20.public void onPictureTaken(byte[] data, Camera camera) {

21.// TODO Auto-generated method stub

22.Log.d("ddd","jpeg");

23.}

24.};
复制代码
       当开始拍照时,会依次调用shutter的onShutter()方法,raw的onPictureTaken方法,jpeg的onPictureTaken方法.三个参数的作用是shutter--拍照瞬间调用,raw--获得没有压缩过的图片数据,jpeg---返回jpeg的图片数据
当你不需要对照片进行处理,可以直接用null代替.
注意,当调用camera.takePiture方法后,camera关闭了预览,这时需要调用startPreview()来重新开启预览。


       我用以上知识,加到上面的那个例子,就形成了下面的代码:

       MySurfaceView.java

Java代码:

01.package eoe.wjh.camera;

02.

03.import java.io.IOException;

04.import android.content.Context;

05.import android.graphics.PixelFormat;

06.import android.hardware.Camera;

07.import android.hardware.Camera.PictureCallback;

08.import android.hardware.Camera.ShutterCallback;

09.import android.util.Log;

10.import android.view.SurfaceHolder;

11.import android.view.SurfaceView;

12.

13.

14.public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback{

15.SurfaceHolder holder;

16.Camera myCamera;

17.private ShutterCallback shutter = new ShutterCallback() {

18.@Override

19.public void onShutter() {

20.// TODO Auto-generated method stub

21.Log.d("ddd", "shutter");

22.}

23.};

24.

25.private PictureCallback raw = new PictureCallback() {

26.@Override

27.public void onPictureTaken(byte[] data, Camera camera) {

28.// TODO Auto-generated method stub

29.Log.d("ddd", "raw");

30.}

31.};

32.private PictureCallback jpeg = new PictureCallback() {

33.@Override

34.public void onPictureTaken(byte[] data, Camera camera) {

35.// TODO Auto-generated method stub

36.Log.d("ddd","jpeg");

37.}

38.};

39.public MySurfaceView(Context context) {

40.super(context);

41.holder = getHolder();//获得surfaceHolder引用

42.holder.addCallback(this);

43.holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//设置类型

44.}

45.public void tackPicture()  {

46.myCamera.takePicture(null,null,null);

47.}

48.public void voerTack() {

49.myCamera.startPreview();

50.}

51.@Override

52.public void surfaceChanged(SurfaceHolder holder, int format, int width,  int height) {

53.myCamera.startPreview();

54.}

55.@Override

56.public void surfaceCreated(SurfaceHolder holder) {

57.// TODO Auto-generated method stub

58.if(myCamera == null) {

59.myCamera = Camera.open();//开启相机,不能放在构造函数中,不然不会显示画面.

60.try {

61.myCamera.setPreviewDisplay(holder);

62.} catch (IOException e) {

63.// TODO Auto-generated catch block

64.e.printStackTrace();

65.}

66.}

67.}

68.

69.@Override

70.public void surfaceDestroyed(SurfaceHolder holder) {

71.// TODO Auto-generated method stub

72.myCamera.stopPreview();//停止预览

73.myCamera.release();//释放相机资源

74.myCamera = null;

75.}

76.}
复制代码
       CameraTest_3.java

Java代码:

01.import android.app.Activity;

02.import android.os.Bundle;

03.import android.view.View;

04.import android.view.View.OnClickListener;

05.

06.public class CameraTest_3 extends Activity implements OnClickListener {

07./** Called when the activity is first created. */

08.MySurfaceView mySurface;

09.boolean isClicked = false;

10.@Override

11.public void onCreate(Bundle savedInstanceState) {

12.super.onCreate(savedInstanceState);

13.mySurface = new MySurfaceView(this);

14.setContentView(mySurface);

15.mySurface.setOnClickListener(this);

16.}

17.

18.@Override

19.public void onClick(View v) {

20.// TODO Auto-generated method stub

21.if(!isClicked)

22.{

23.mySurface.tackPicture();

24.isClicked = true;

25.}else {

26.mySurface.voerTack();

27.isClicked = false;

28.}

29.

30.}


这样就是实现了拍照的功能,那么怎样要图片保存呢?那么这是就需要在那个参数中的jpeg的
方法里面进行处理了,那个方法的data参数,就是相片的数据。
       我们通过BitmapFactory.decodeByteArray(data, 0, data.length)来获得图片并通过io处理,将图片保存到想要保存的位置
       下面这段代码,是将照片保存到/sdcard/wjh.jpg;并把一些没有用到的代码全部删掉,剩下一些必须的代码

       MySurfaceView.java

Java代码:

01.package eoe.wjh.camera;

02.

03.import java.io.BufferedInputStream;

04.import java.io.BufferedOutputStream;

05.import java.io.File;

06.import java.io.FileOutputStream;

07.import java.io.OutputStream;

08.import android.content.Context;

09.import android.graphics.Bitmap;

10.import android.graphics.BitmapFactory;

11.import android.graphics.PixelFormat;

12.import android.hardware.Camera;

13.import android.hardware.Camera.PictureCallback;

14.import android.hardware.Camera.ShutterCallback;

15.import android.util.Log;

16.import android.view.SurfaceHolder;

17.import android.view.SurfaceView;

18.

19.public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback{

20.SurfaceHolder holder;

21.Camera myCamera;

22.private PictureCallback jpeg = new PictureCallback() {

23.@Override

24.public void onPictureTaken(byte[] data, Camera camera) {

25.// TODO Auto-generated method stub

26.try  {

27.Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length);

28.File file = new File("/sdcard/wjh.jpg");

29.BufferedOutputStream bos  = new BufferedOutputStream(new FileOutputStream(file));

30.bm.compress(Bitmap.CompressFormat.JPEG,100,bos);

31.bos.flush();

32.bos.close();

33.}catch(Exception e) {

34.e.printStackTrace();

35.}

36.};

37.public MySurfaceView(Context context) {

38.super(context);

39.holder = getHolder();//获得surfaceHolder引用

40.holder.addCallback(this);

41.holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//设置类型

42.}

43.public void tackPicture() {

44.myCamera.takePicture(null,null,jpeg);

45.}

46.public void voerTack() {

47.myCamera.startPreview();

48.}

49.

50.@Override

51.public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

52.myCamera.startPreview();

53.}

54.@Override

55.public void surfaceCreated(SurfaceHolder holder) {

56.if(myCamera == null) {

57.myCamera = Camera.open();//开启相机,不能放在构造函数中,不然不会显示画面.

58.try {

59.myCamera.setPreviewDisplay(holder);

60.} catch (IOException e) {

61.// TODO Auto-generated catch block

62.e.printStackTrace();

63.}

64.}

65.}

66.@Override

67.public void surfaceDestroyed(SurfaceHolder holder) {

68.// TODO Auto-generated method stub

69.myCamera.stopPreview();//停止预览

70.myCamera.release();//释放相机资源

71.myCamera = null;

72.}

73.}
复制代码
        注意,这是必须添加在sd卡上写数据的权限
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

        (7)能够拍照了,这下子要考虑如何让图片更好看了,这显然是专业人士的强项,但是我们在程序上,也可以做一些处理,
        向上面的那些,因为我直接把surfaceView当做整体布局,就可能出现屏幕被拉开了,不是很好看,所以这时,就可以不要把surfaceView弄成整体布局,把他弄到到一个布局管理器,在设置相关的参数.这是需要注意的是有些参数不能随便乱设,

        如以下代码:

Java代码:

01.Camera.Parameters parames = myCamera.getParameters();//获得参数对象

02.parames.setPictureFormat(PixelFormat.JPEG);//设置图片格式

03.parames.setPreviewSize(640,480);//这里面的参数只能是几个特定的参数,否则会报错.(176*144,320*240,352*288,480*360,640*480)

04.myCamera.setParameters(parames);
复制代码      还有自动对焦,当然有些手机没有这个功能,自动对焦是通过autoFocus()这个方法调用一个自动对焦的接口,并在里面进行处理。
       注意,这个方法必须在startPreview()和stopPreview()中间。
       AutoFocusCallback是自动对焦的接口,实现它必须实现public void onAutoFocus(boolean success, Camera camera)这个方法,所以我们可以将拍照方法放在这里面,然后对焦后再进行拍摄。效果会好很多。
       注意自动对焦需要添加<uses-feature android:name="android.hardware.camera.autofocus" />下面我叫直接把上面的使用例子直接写出。

        CameraTest_4.java

Java代码:
01.import java.io.BufferedOutputStream;

02.import java.io.File;

03.import java.io.FileOutputStream;

04.import java.io.IOException;

05.import android.app.Activity;

06.import android.content.pm.ActivityInfo;

07.import android.graphics.Bitmap;

08.import android.graphics.BitmapFactory;

09.import android.graphics.PixelFormat;

10.import android.hardware.Camera;

11.import android.hardware.Camera.AutoFocusCallback;

12.import android.hardware.Camera.PictureCallback;

13.import android.os.Bundle;

14.import android.view.SurfaceHolder;

15.import android.view.SurfaceView;

16.import android.view.View;

17.import android.view.Window;

18.import android.view.SurfaceHolder.Callback;

19.import android.view.View.OnClickListener;

20.

21.

22.public class CameraTest_4 extends Activity implements

23.Callback, OnClickListener, AutoFocusCallback{

24.SurfaceView mySurfaceView;//surfaceView声明

25.SurfaceHolder holder;//surfaceHolder声明

26.Camera myCamera;//相机声明

27.String filePath="/sdcard/wjh.jpg";//照片保存路径

28.boolean isClicked = false;//是否点击标识

29.//创建jpeg图片回调数据对象

30.PictureCallback jpeg = new PictureCallback() {

31.@Override

32.public void onPictureTaken(byte[] data, Camera camera) {

33.// TODO Auto-generated method stub

34.try {// 获得图片

35.Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length);

36.File file = new File(filePath);

37.BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));

38.bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);//将图片压缩到流中

39.bos.flush();//输出

40.bos.close();//关闭

41.}catch(Exception e) {

42.e.printStackTrace();

43.}

44.}

45.};

46./** Called when the activity is first created. */

47.@Override

48.public void onCreate(Bundle savedInstanceState) {

49.super.onCreate(savedInstanceState);

50.requestWindowFeature(Window.FEATURE_NO_TITLE);//无标题

51.//设置拍摄方向

52.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

53.setContentView(R.layout.main);

54.//获得控件

55.mySurfaceView = (SurfaceView)findViewById(R.id.surfaceView1);

56.//获得句柄

57.holder = mySurfaceView.getHolder();

58.//添加回调

59.holder.addCallback(this);

60.//设置类型

61.holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

62.//设置监听

63.mySurfaceView.setOnClickListener(this);

64.}

65.@Override

66.public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

67.// TODO Auto-generated method stub

68.//设置参数并开始预览

69.Camera.Parameters params = myCamera.getParameters();

70.params.setPictureFormat(PixelFormat.JPEG);

71.params.setPreviewSize(640,480);

72.myCamera.setParameters(params);

73.myCamera.startPreview();

74.}

75.@Override

76.public void surfaceCreated(SurfaceHolder holder) {

77.// TODO Auto-generated method stub

78.//开启相机

79.if(myCamera == null) {

80.myCamera = Camera.open();

81.try {

82.myCamera.setPreviewDisplay(holder);

83.} catch (IOException e) {

84.// TODO Auto-generated catch block

85.e.printStackTrace();

86.}

87.}

88.}

89.@Override

90.public void surfaceDestroyed(SurfaceHolder holder) {

91.// TODO Auto-generated method stub

92.//关闭预览并释放资源

93.myCamera.stopPreview();

94.myCamera.release();

95.myCamera = null;

96.}

97.@Override

98.public void onClick(View v) {

99.// TODO Auto-generated method stub

100.if(!isClicked) {

101.myCamera.autoFocus(this);//自动对焦

102.isClicked = true;

103.}else {

104.myCamera.startPreview();//开启预览

105.isClicked = false;

106.}

107.}

108.@Override

109.public void onAutoFocus(boolean success, Camera camera) {

110.// TODO Auto-generated method stub

111.if(success) {

112.//设置参数,并拍照

113.Camera.Parameters params = myCamera.getParameters();

114.params.setPictureFormat(PixelFormat.JPEG);

115.params.setPreviewSize(640,480);

116.myCamera.setParameters(params);

117.myCamera.takePicture(null, null, jpeg);

118.}

119.}

120.

121.}
复制代码
       main.xml

Java代码:

01.<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"

02.androidrientation="vertical"

03.android:layout_width="fill_parent"

04.android:layout_height="fill_parent"

05.>

06.<surfaceview android:id="@+id/surfaceView1"

07.android:layout_width="640px"

08.android:layout_height="480px"

09.android:layout_gravity="center">
复制代码
       AndroidManifest.xml

Java代码:

01.<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"

02.package="com.wjh.camera"

03.android:versionCode="1"

04.android:versionName="1.0">

05.<uses-sdk android:minSdkVersion="7" />

06.<uses-permission android:name="android.permission.CAMERA"></uses-permission>

07.<uses-feature android:name="android.hardware.camera.autofocus" />

08.<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

09.<application android:icon="@drawable/icon" android:label="@string/app_name">

10.<activity android:name=".CameraTest_4" android:label="@string/app_name">

11.<intent-filter>

12.<action android:name="android.intent.action.MAIN" />

13.<category android:name="android.intent.category.LAUNCHER" />

14.</intent-filter>

15.</activity>

16.</application>

17.</manifest>
  相关解决方案