在android中应用相机功能,一般有两种:一种是直接调用系统相机,一种自己写的相机。
  我将分别演示两种方式的使用:
  第一种:是使用Intent跳转到系统相机,action为:android.media.action.STILL_IMAGE_CAMERA
  关键代码:
  java代码

1.  Intent intent = new Intent(); //调用照相机
2.  
3.    intent.setAction("android.media.action.STILL_IMAGE_CAMERA");
4.    startActivity(intent);


复制代码

  例子:


  java代码

1.  import android.app.Activity;
2.  
3.    import android.content.Intent;
4.    import android.os.Bundle;
5.    public class CameraTest_2 extends Activity {
6.    /** Called when the activity is first created. */
7.    @Override
8.    public void onCreate(Bundle savedInstanceState) {
9.    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.    }


复制代码

  想要测试的,可以直接新建一个项目,并且把主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)


 

  (4)

SurfaceHolder.Callback,这是个holder用来显示surfaceView 数据的接口,他分别必须实现3个方法 

  surfaceCreated()这个方法是surface 被创建后调用的 

  surfaceChanged()这个方法是当surfaceView发生改变后调用的 

  surfaceDestroyed()这个是当surfaceView销毁时调用的. 

  surfaceHolde通过addCallBack()方法将响应的接口绑定到他身上. 

  surfaceHolder还必须设定一个setType()方法,查看api的时候,发现这个方法已经过时,但是不写,又会报错


  我用以上知识写了一个MySurfaceView类,他继承于SurfaceView,并在里面实现了照相机的预览功能.这个我觉得最简单的照相机预览代码:


  MySurfaceView.java:


  java代码


    1.  import java.io.IOException;
    2.  
    3.    import android.content.Context;
    4.    import android.graphics.PixelFormat;
    5.    import android.hardware.Camera;
    6.    import android.util.Log;
    7.    import android.view.SurfaceHolder;
    8.    import android.view.SurfaceView;
    9.    public class MySurfaceView extends SurfaceView implements 
    10.  SurfaceHolder.Callback{
    11.    SurfaceHolder holder;
    12.    Camera myCamera;
    13.    public MySurfaceView(Context context)
    14.    {
    15.    super(context);
    16.    holder = getHolder();//获得surfaceHolder引用
    17.    holder.addCallback(this);
    18.    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//设置类型
    19.    }
    20.    @Override
    21.    public void surfaceCreated(SurfaceHolder holder) {
    22.    // TODO Auto-generated method stub
    23.    if(myCamera == null)
    24.    {
    25.    myCamera = Camera.open();//开启相机,不能放在构造函数中,不然不会显示画面.
    26.    try {
    27.    myCamera.setPreviewDisplay(holder);
    28.    } catch (IOException e) {
    29.    // TODO Auto-generated catch block
    30.    e.printStackTrace();
    31.    }
    32.    }
    33.    }
    34.    @Override
    35.    public void surfaceChanged(SurfaceHolder holder, int format, int width,
    36.    int height) {
    37.    myCamera.startPreview();
    38.    }
    39.    @Override
    40.    public void surfaceDestroyed(SurfaceHolder holder) {
    41.    // TODO Auto-generated method stub
    42.    myCamera.stopPreview();//停止预览
    43.    myCamera.release();//释放相机资源
    44.    myCamera = null;
    45.    Log.d("ddd", "4");
    46.    }
    47.    }


    复制代码

      主activity代码:


      java代码


      1.  import android.app.Activity;
      2.  
      3.    import android.os.Bundle;
      4.    import android.view.View;
      5.    import android.view.View.OnClickListener;
      6.    public class CameraTest_3 extends Activity {
      7.    /** Called when the activity is first created. */
      8.    MySurfaceView mySurface;
      9.    @Override
      10.    public void onCreate(Bundle savedInstanceState) {
      11.    super.onCreate(savedInstanceState);
      12.    mySurface = new MySurfaceView(this);
      13.    setContentView(mySurface);
      14.    }
      15.    }


      复制代码

        (5)能够预览了,接下来就是拍照了,拍照用到了一个camera.tackPiture()这个方法,这个方法,有三个参数分别是


       

      ShutterCallBack shutter,PictureCallBack raw,PictureCallBack jpeg.



        下面是对他们的实现


        java代码


        1.  private ShutterCallback shutter = new ShutterCallback() {
        2.  
        3.    @Override
        4.    public void onShutter() {
        5.    // TODO Auto-generated method stub
        6.    Log.d("ddd", "shutter");
        7.    }
        8.    };
        9.    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.    private PictureCallback jpeg = new PictureCallback() {
        17.    @Override
        18.    public void onPictureTaken(byte[] data, Camera camera) {
        19.    // TODO Auto-generated method stub
        20.    Log.d("ddd","jpeg");
        21.    }
        22.    };


        复制代码

          当开始拍照时,会依次调用shutter的onShutter()方法,raw的onPictureTaken方法,jpeg的onPictureTaken方法.


          三个参数的作用是shutter--拍照瞬间调用,raw--获得没有压缩过的图片数据,jpeg---返回jpeg的图片数据


          当你不需要对照片进行处理,可以直接用null代替.


          注意,当调用camera.takePiture方法后,camera关闭了预览,这时需要调用startPreview()来重新开启预览。


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


          MySurfaceView.java:


          java代码


          1.  package jason.camera;
          2.  
          3.    import java.io.IOException;
          4.    import android.content.Context;
          5.    import android.graphics.PixelFormat;
          6.    import android.hardware.Camera;
          7.    import android.hardware.Camera.PictureCallback;
          8.    import android.hardware.Camera.ShutterCallback;
          9.    import android.util.Log;
          10.    import android.view.SurfaceHolder;
          11.    import android.view.SurfaceView;
          12.    public class MySurfaceView extends SurfaceView implements 
          13.  SurfaceHolder.Callback{
          14.    SurfaceHolder holder;
          15.    Camera myCamera;
          16.    private ShutterCallback shutter = new ShutterCallback() {
          17.    @Override
          18.    public void onShutter() {
          19.    // TODO Auto-generated method stub
          20.    Log.d("ddd", "shutter");
          21.    }
          22.    };
          23.    private PictureCallback raw = new PictureCallback() {
          24.    @Override
          25.    public void onPictureTaken(byte[] data, Camera camera) {
          26.    // TODO Auto-generated method stub
          27.    Log.d("ddd", "raw");
          28.    }
          29.    };
          30.    private PictureCallback jpeg = new PictureCallback() {
          31.    @Override
          32.    public void onPictureTaken(byte[] data, Camera camera) {
          33.    // TODO Auto-generated method stub
          34.    Log.d("ddd","jpeg");
          35.    }
          36.    };
          37.    public MySurfaceView(Context context)
          38.    {
          39.    super(context);
          40.    holder = getHolder();//获得surfaceHolder引用
          41.    holder.addCallback(this);
          42.    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//设置类型
          43.    }
          44.    public void tackPicture()
          45.    {
          46.    myCamera.takePicture(null,null,null);
          47.    }
          48.    public void voerTack()
          49.    {
          50.    myCamera.startPreview();
          51.    }
          52.    @Override
          53.    public void surfaceChanged(SurfaceHolder holder, int format, int width,
          54.    int height) {
          55.    myCamera.startPreview();
          56.    }
          57.    @Override
          58.    public void surfaceCreated(SurfaceHolder holder) {
          59.    // TODO Auto-generated method stub
          60.    if(myCamera == null)
          61.    {
          62.    myCamera = Camera.open();//开启相机,不能放在构造函数中,不然不会显示画面.
          63.    try {
          64.    myCamera.setPreviewDisplay(holder);
          65.    } catch (IOException e) {
          66.    // TODO Auto-generated catch block
          67.    e.printStackTrace();
          68.    }
          69.    }
          70.    }
          71.    @Override
          72.    public void surfaceDestroyed(SurfaceHolder holder) {
          73.    // TODO Auto-generated method stub
          74.    myCamera.stopPreview();//停止预览
          75.    myCamera.release();//释放相机资源
          76.    myCamera = null;
          77.    }
          78.    }


          复制代码

            主activity:


            java代码


            1.  import android.app.Activity;
            2.  
            3.    import android.os.Bundle;
            4.    import android.view.View;
            5.    import android.view.View.OnClickListener;
            6.    public class CameraTest_3 extends Activity implements OnClickListener {
            7.    /** Called when the activity is first created. */
            8.    MySurfaceView mySurface;
            9.    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.    @Override
            18.    public void onClick(View v) {
            19.    // TODO Auto-generated method stub
            20.    if(!isClicked)
            21.    {
            22.    mySurface.tackPicture();
            23.    isClicked = true;
            24.    }else
            25.    {
            26.    mySurface.voerTack();
            27.    isClicked = false;
            28.    }
            29.    }


            复制代码

              这样就是实现了拍照的功能,那么怎样要图片保存呢?那么这是就需要在那个参数中的jpeg的


              方法里面进行处理了,那个方法的data参数,就是相片的数据。


              我们通过BitmapFactory.decodeByteArray(data, 0, data.length)来获得图片并通过io处理,将图片保存到想要保存的位置


              下面这段代码,是将照片保存到/sdcard/wjh.jpg;并把一些没有用到的代码全部删掉,剩下一些必须的代码


              java代码


              1.  package java.camera;
              2.  
              3.    import java.io.BufferedInputStream;
              4.    import java.io.BufferedOutputStream;
              5.    import java.io.File;
              6.    import java.io.FileOutputStream;
              7.    import java.io.IOException;
              8.    import java.io.OutputStream;
              9.    import android.content.Context;
              10.    import android.graphics.Bitmap;
              11.    import android.graphics.BitmapFactory;
              12.    import android.graphics.PixelFormat;
              13.    import android.hardware.Camera;
              14.    import android.hardware.Camera.PictureCallback;
              15.    import android.hardware.Camera.ShutterCallback;
              16.    import android.util.Log;
              17.    import android.view.SurfaceHolder;
              18.    import android.view.SurfaceView;
              19.    public class MySurfaceView extends SurfaceView implements 
              20.  SurfaceHolder.Callback{
              21.    SurfaceHolder holder;
              22.    Camera myCamera;
              23.    private PictureCallback jpeg = new PictureCallback() {
              24.    @Override
              25.    public void onPictureTaken(byte[] data, Camera camera) {
              26.    // TODO Auto-generated method stub
              27.    try
              28.    {
              29.    Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length);
              30.    File file = new File("/sdcard/wjh.jpg");
              31.    BufferedOutputStream bos
              32.    = new BufferedOutputStream(new FileOutputStream(file));
              33.    bm.compress(Bitmap.CompressFormat.JPEG,100,bos);
              34.    bos.flush();
              35.    bos.close();
              36.    }catch(Exception e)
              37.    {
              38.    e.printStackTrace();
              39.    }
              40.    }
              41.    };
              42.    public MySurfaceView(Context context)
              43.    {
              44.    super(context);
              45.    holder = getHolder();//获得surfaceHolder引用
              46.    holder.addCallback(this);
              47.    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//设置类型
              48.    }
              49.    public void tackPicture()
              50.    {
              51.    myCamera.takePicture(null,null,jpeg);
              52.    }
              53.    public void voerTack()
              54.    {
              55.    myCamera.startPreview();
              56.    }
              57.    @Override
              58.    public void surfaceChanged(SurfaceHolder holder, int format, int width,
              59.    int height) {
              60.    myCamera.startPreview();
              61.    }
              62.    @Override
              63.    public void surfaceCreated(SurfaceHolder holder) {
              64.    // TODO Auto-generated method stub
              65.    if(myCamera == null)
              66.    {
              67.    myCamera = Camera.open();//开启相机,不能放在构造函数中,不然不会显示画面.
              68.    try {
              69.    myCamera.setPreviewDisplay(holder);
              70.    } catch (IOException e) {
              71.    // TODO Auto-generated catch block
              72.    e.printStackTrace();
              73.    }
              74.    }
              75.    }
              76.    @Override
              77.    public void surfaceDestroyed(SurfaceHolder holder) {
              78.    // TODO Auto-generated method stub
              79.    myCamera.stopPreview();//停止预览
              80.    myCamera.release();//释放相机资源
              81.    myCamera = null;
              82.    }
              83.    }


              复制代码

                注意,这是必须添加在sd卡上写数据的权限



                (7)能够拍照了,这下子要考虑如何让图片更好看了,这显然是专业人士的强项,但是我们在程序上,也可以做一些处理,

                向上面的那些,因为我直接把surfaceView当做整体布局,就可能出现屏幕被拉开了,不是很好看,所以这时,就可以不要把

                surfaceView弄成整体布局,把他弄到一个布局管理器,再设置相关的参数.

                这时需要注意的是有些参数不能随便乱设

                如以下代码:

                java代码

              1.  Camera.Parameters parames = myCamera.getParameters();//获得参数对象
              2.  
              3.    parames.setPictureFormat(PixelFormat.JPEG);//设置图片格式
              4.    parames.setPreviewSize(640,480);//这里面的参数只能是几个特定的参数,否则会报错.(176*144,320*240,352*288,480*360,640*480)
              5.    myCamera.setParameters(parames);


              复制代码   还有自动对焦,当然有些手机没有这个功能,自动对焦是通过autoFocus()这个方法调用一个自动对焦的接口,并在里面进行处理。


                注意,这个方法必须在startPreview()和stopPreview()中间。


                AutoFocusCallback是自动对焦的接口,实现它必须实现public void onAutoFocus(boolean success, Camera camera)这个方法,


                所以我们可以将拍照方法放在这里面,然后对焦后再进行拍摄。。效果会好很多。


                注意自动对焦需要添加



                下面是主要代码,直接贴出来了


                java代码

              1.  import java.io.BufferedOutputStream;
              2.  
              3.    import java.io.File;
              4.    import java.io.FileOutputStream;
              5.    import java.io.IOException;
              6.    import android.app.Activity;
              7.    import android.content.pm.ActivityInfo;
              8.    import android.graphics.Bitmap;
              9.    import android.graphics.BitmapFactory;
              10.    import android.graphics.PixelFormat;
              11.    import android.hardware.Camera;
              12.    import android.hardware.Camera.AutoFocusCallback;
              13.    import android.hardware.Camera.PictureCallback;
              14.    import android.os.Bundle;
              15.    import android.view.SurfaceHolder;
              16.    import android.view.SurfaceView;
              17.    import android.view.View;
              18.    import android.view.Window;
              19.    import android.view.SurfaceHolder.Callback;
              20.    import android.view.View.OnClickListener;
              21.    public class CameraTest_4 extends Activity implements
              22.    Callback, OnClickListener, AutoFocusCallback{
              23.    SurfaceView mySurfaceView;//surfaceView声明
              24.    SurfaceHolder holder;//surfaceHolder声明
              25.    Camera myCamera;//相机声明
              26.    String filePath="/sdcard/wjh.jpg";//照片保存路径
              27.    boolean isClicked = false;//是否点击标识
              28.    //创建jpeg图片回调数据对象
              29.    PictureCallback jpeg = new PictureCallback() {
              30.    @Override
              31.    public void onPictureTaken(byte[] data, Camera camera) {
              32.    // TODO Auto-generated method stub
              33.    try
              34.    {// 获得图片
              35.    Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length);
              36.    File file = new File(filePath);
              37.    BufferedOutputStream bos =
              38.    new BufferedOutputStream(new FileOutputStream(file));
              39.    bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);//将图片压缩到流中
              40.    bos.flush();//输出
              41.    bos.close();//关闭
              42.    }catch(Exception e)
              43.    {
              44.    e.printStackTrace();
              45.    }
              46.    }
              47.    };
              48.    /** Called when the activity is first created. */
              49.    @Override
              50.    public void onCreate(Bundle savedInstanceState) {
              51.    super.onCreate(savedInstanceState);
              52.    requestWindowFeature(Window.FEATURE_NO_TITLE);//无标题
              53.    //设置拍摄方向
              54.    this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
              55.    setContentView(R.layout.main);
              56.    //获得控件
              57.    mySurfaceView = (SurfaceView)findViewById(R.id.surfaceView1);
              58.    //获得句柄
              59.    holder = mySurfaceView.getHolder();
              60.    //添加回调
              61.    holder.addCallback(this);
              62.    //设置类型
              63.    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
              64.    //设置监听
              65.    mySurfaceView.setOnClickListener(this);
              66.    }
              67.    @Override
              68.    public void surfaceChanged(SurfaceHolder holder, int format, int width,
              69.    int height) {
              70.    // TODO Auto-generated method stub
              71.    //设置参数并开始预览
              72.    Camera.Parameters params = myCamera.getParameters();
              73.    params.setPictureFormat(PixelFormat.JPEG);
              74.    params.setPreviewSize(640,480);
              75.    myCamera.setParameters(params);
              76.    myCamera.startPreview();
              77.    }
              78.    @Override
              79.    public void surfaceCreated(SurfaceHolder holder) {
              80.    // TODO Auto-generated method stub
              81.    //开启相机
              82.    if(myCamera == null)
              83.    {
              84.    myCamera = Camera.open();
              85.    try {
              86.    myCamera.setPreviewDisplay(holder);
              87.    } catch (IOException e) {
              88.    // TODO Auto-generated catch block
              89.    e.printStackTrace();
              90.    }
              91.    }
              92.    }
              93.    @Override
              94.    public void surfaceDestroyed(SurfaceHolder holder) {
              95.    // TODO Auto-generated method stub
              96.    //关闭预览并释放资源
              97.    myCamera.stopPreview();
              98.    myCamera.release();
              99.    myCamera = null;
              100.    }
              101.    @Override
              102.    public void onClick(View v) {
              103.    // TODO Auto-generated method stub
              104.    if(!isClicked)
              105.    {
              106.    myCamera.autoFocus(this);//自动对焦
              107.    isClicked = true;
              108.    }else
              109.    {
              110.    myCamera.startPreview();//开启预览
              111.    isClicked = false;
              112.    }
              113.    }
              114.    @Override
              115.    public void onAutoFocus(boolean success, Camera camera) {
              116.    // TODO Auto-generated method stub
              117.    if(success)
              118.    {
              119.    //设置参数,并拍照
              120.    Camera.Parameters params = myCamera.getParameters();
              121.    params.setPictureFormat(PixelFormat.JPEG);
              122.    params.setPreviewSize(640,480);
              123.    myCamera.setParameters(params);
              124.    myCamera.takePicture(null, null, jpeg);
              125.    }
              126.    }
              127.    }


              复制代码   main.xml:


                html代码


              1.   androidrientation="vertical"
              2.    android:layout_width="fill_parent"
              3.    android:layout_height="fill_parent"
              4.    >  android:layout_width="640px"
              5.    android:layout_height="480px"
              6.    android:layout_gravity="center">
              7.    AndroidManifest.xml:

              复制代码