android调用手机摄像头拍照

来源:互联网 发布:unix环境高级编程 源码 编辑:程序博客网 时间:2024/04/28 19:19

网上调用android手机摄像头拍照的代码也挺多,总的来说都能使.但是对于刚开始接触的人用处不大,都是转来转去,看着都烦

下面我就来写一个,用代码来详细解释android手机拍照的过程

首先是使用camera需要用到的权限。

 
文件写入    
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />      <!-- 摄像头拍照 -->    <uses-permission android:name="android.permission.CAMERA" />    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />    <uses-feature android:name="android.hardware.camera"/>

 

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;

import net.cartravel.app.AppContext;
import net.cartravel.app.AppException;
import net.cartravel.app.AppManager;
import net.cartravel.app.R;
import net.cartravel.app.api.RequestData;
import net.cartravel.app.api.RequestResult;
import net.cartravel.app.bean.CarParkingRecord;
import net.cartravel.app.bean.URLs;
import net.cartravel.app.common.UIHelper;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.LinearLayout.LayoutParams;

 

 

public class CameraActivity extends Activity {


 private Camera camera;  //  定义 Camera对象,调用系统的摄像头 
 private Preview preview;  // 声明Preview ,自定义类
 private ImageView ivFocus;  // 声明相机焦点
 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); // 时间转换
 private String randomImage = "car.jpg";  // 文件名
 byte[] image;
 int k = 0;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  // TODO Auto-generated method stub
  super.onCreate(savedInstanceState);
  requestWindowFeature(Window.FEATURE_NO_TITLE); // 无标题
  preview = new Preview(this);   // 创建Preview对象,传入当前Activity.
  setContentView(preview); // 设置preview为显示界面
  ivFocus = new ImageView(this); // 创建ImageView组件
 }
 
 @Override
 public boolean onTouchEvent(MotionEvent event) {
  // TODO Auto-generated method stub
  if (event.getAction() == KeyEvent.ACTION_DOWN) { // 按下事件
   openOptionsMenu(); // 打开菜单栏
  }
  return super.onTouchEvent(event);
 }
 
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
        // TODO Auto-generated method stub
       menu.add(0, Menu.FIRST, 0, "拍照")
                .setIcon(R.drawable.camera);
        menu.add(0, Menu.FIRST + 1, 0, "取消")
          .setIcon(R.drawable.close);
       return super.onCreateOptionsMenu(menu);
 }
 
  @Override
 public boolean onOptionsItemSelected(MenuItem item) {
  
  switch (item.getItemId()) {
         case Menu.FIRST:
          if (k == 0) {
           camera.autoFocus(new AutoFocusCallback() { // 自动对焦
         public void onAutoFocus(boolean success, Camera camera) {
          if (success) {           
           // success为true表示对焦成功,改变对焦状态图像(一个绿色的png图像)
              preview.takePicture(); // 进行拍照
              k = 1;
              ivFocus.setImageResource(R.drawable.white); // white为图片
          }
         }
        }); 
          }
    break;
         case Menu.FIRST + 1:
             camera.startPreview(); // 开始亮灯,重新获取拍摄界面
             ivFocus.setImageResource(R.drawable.focus1); // focus1为图片 
             k = 0;
             break;
         }
     return super.onOptionsItemSelected(item);
 }

    /*

     * 使用接口的原因:因为使用SurfaceView 有一个原则,所有的绘图工作必须得在Surface 被创建之后才能开始(Surface—表面,这个概念在 图形编程中常常被提到。基本上我们可以把它当作显存的一个映射,写入到Surface 的内容
                      可以被直接复制到显存从而显示出来,这使得显示速度会非常快),而在Surface 被销毁之前必须结束。所以Callback 中的surfaceCreated 和surfaceDestroyed 就成了绘图处理代码的边界
     */
  class Preview extends SurfaceView implements SurfaceHolder.Callback {
   
  // 定义 SurfaceHolder对象
  private SurfaceHolder holder;
  // 创建一个PictureCallback对象,并实现其中的onPictureTaken方法
  private PictureCallback pictureCallback = new PictureCallback() {
   // 该方法用于处理拍摄后的照片数据
   public void onPictureTaken(byte[] data, Camera camera) {
    // data参数值就是照片数据,将这些数据以key-value形式保存,以便其他调用该Activity的程序可
    // 以获得照片数据  
    Bitmap cameraBitmap;
//    // 文件名
    cameraBitmap = BitmapFactory.decodeByteArray(data, 0,
      data.length);
    if (getWindowManager().getDefaultDisplay().getOrientation() == 0)
    {
     Matrix matrix = new Matrix();
     matrix.setRotate(90);
     cameraBitmap = Bitmap.createBitmap(cameraBitmap, 0, 0,
       cameraBitmap.getWidth(), cameraBitmap.getHeight(),
       matrix, true); // 生成图片数据
    }
    File myCaptureFile = new File("/sdcard/DCIM/Camera/" + randomImage);
    try {
     BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(myCaptureFile));
     cameraBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos); //压缩图片像素,将图片数据写入
     bos.flush();
     bos.close();
     cameraBitmap.recycle(); // 回收Bitmap的空间 
     camera.reconnect(); // 重新连接摄像机
    } catch(Exception e) {
     e.printStackTrace();
    }
   }
  };

  // Preview类的构造方法
  public Preview(Context context)
  {
   super(context);
  holder = getHolder(); // 显示一个surface的抽象接口,使你可以控制surface的大小和格式, 以及在surface上编辑像素,和监视surface的改变。  
   holder.addCallback(this); // 指定用于捕捉拍照事件的SurfaceHolder.Callback对象
   // 设置SurfaceHolder对象的类型
   holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // 表明该Surface不包含原生数据,Surface用到的数据由其他对象提供,在Camera图像预览中就使用该类型的Surface,有Camera负责提供给预览Surface数据,这样图像预览会比较流畅。
  }

  // 开始拍照时调用该方法
  public void surfaceCreated(SurfaceHolder holder) {
   // 获得Camera对象
   camera = Camera.open();
   try {    
    // 设置用于控制surface对象
    camera.setPreviewDisplay(holder);
    
   }
   catch (IOException exception) {
    // 释放手机摄像头
    camera.release();
   }
  }

  // 停止拍照时调用该方法
  public void surfaceDestroyed(SurfaceHolder holder) {
   // 释放手机摄像头
   camera.release();
  }

  // 拍照状态变化时调用该方法
  public void surfaceChanged(final SurfaceHolder holder, int format,
    int w, int h) {   
   
   try {   
    Camera.Parameters parameters = camera.getParameters();
    // 设置照片格式
    parameters.setPictureFormat(PixelFormat.JPEG);    
    camera.setDisplayOrientation(90);    
  
    // 设置拍摄照片的实际分辨率,在本例中的分辨率是1024*768
    parameters.setPictureSize(1024, 768);
    // 设置保存的图像大小
    camera.setParameters(parameters);
    // 开始拍照
    camera.startPreview();
    // 准备用于表示对焦状态的图像
    ivFocus.setImageResource(R.drawable.focus1);
    // 设置摄像图片布局
    LayoutParams layoutParams = new LayoutParams(
      LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
    ivFocus.setScaleType(ScaleType.CENTER);
    addContentView(ivFocus, layoutParams);
    ivFocus.setVisibility(VISIBLE);               
   }
   catch (Exception e) {
    // 释放手机摄像头
    camera.release();
   }
  }
  
  // 停止拍照,并将拍摄的照片传入PictureCallback接口的onPictureTaken方法
  public void takePicture() {
   if (camera != null) {  
    camera.takePicture(null, null, pictureCallback);
   }
  }  
 }

 @Override
 protected void onPause() {
  // TODO Auto-generated method stub
  super.onPause(); 
  finish();
 }

 @Override
 protected void onRestart() {
  // TODO Auto-generated method stub
  super.onRestart();
 }
}

由于时间问题,我不会把每一个类,每一个配置文件都写出来,我只写一些核心代码.

亲测了下,没问题.图片你们自己准备把,就是小图标

就写到这吧,不懂的QQ 468903507具体问我,应该注释得很详细了.下篇写写百度地图api的使用,以及如何在地图上进行一些画图、标注等操作.