在android系统上,调用相机是很简单也很有意思的事情。有两种方法,一种是直接调用摄像头,捕获图像然后自己处理;一种是调用系统或者第三方相机,然后使用返回的数据。这里说的就是第二种。

本文需要内存卡写权限和相机权限。

android 确实很伟大,调用相机很简单。

核心代码如下:启动activity,并在onactivity回调中 获取这个图片,很容易吧。下面的代码是把图片显示在一个imageView上。

//  启动系统相机
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (intent.resolveActivity(getPackageManager()) != null) {
            startActivityForResult(intent, 100);
        }
    protected  void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == 100 && resultCode == RESULT_OK) {
"data");
im.setImageBitmap(thumbnail);
// Do other work with full size photo saved in mLocationForPhotos
        }
    }

android 拍照调用 android调用系统拍照功能_缩放



上述代码看起来不错,但是图片怎么这么小呢?查阅文档发现,此时data返回的是缩略图。且这个图片并没有存储,也就是说,关闭程序,就再也找不到这张图片,当然我们可以自己把这个缩略图存储起来。但问题是,我们拍照的原图去哪里了,或者该怎么获取?

查阅android官方文档,可以在启动相机的时候,设置存储路径,这样就可以获得原图了。代码如下

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//其中tempFile 在oncreate中,如下:
//   tempFile =  new File(Environment.getExternalStorageDirectory(),
// System.currentTimeMillis()+".jpg");
        intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(tempFile));
        if (intent.resolveActivity(getPackageManager()) != null) {
            startActivityForResult(intent, 100);
        }
 
protected  void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == 100 && resultCode == RESULT_OK) {
//设置照片存储路径后,有的机型返回的intent 就为null,这时不能从里面取数据了,
// 需要从自己定义的路径取数据
//            Bitmap thumbnail = data.getParcelableExtra("data");
          
        Bitmap Opic = null;
           try {
//读取文件。
                  Opic = BitmapFactory.decodeStream(new FileInputStream(tempFile));
           } catch (FileNotFoundException e) {
// TODO Auto-generated catch block
              e.printStackTrace();
           }
im.setImageBitmap(Opic);
// Do other work with full size photo saved in mLocationForPhotos
        }
    }

以上代码主要是在启动相机的时候,传入了照片存储路径的额外参数,MediaStore.EXTRA_OUTPUT. 并在回调中从传入的路径中读取图片。从显示的结果来看,显示的是拍照的图片。

android 拍照调用 android调用系统拍照功能_System_02

至此,好像一切万事大吉。拍照不过如此。但是细细研究发现,还有两点瑕疵:

1.     直接使用原图,如果图片很大,在一些手机上可能会内存溢出;

2.     我们存储的照片路径在系统媒体库中没有。

对于第一点,如果有很多图片,只是显示其缩略图,只有具体点击的时候才显示大图,或者本身我们不需要太大的图片,因而需要对图片做一些处理。

增加方法,缩放图片。代码如下

/*
     * 
     * 此方法并没有正在的改变原文件图片的大小。
     * width、height 为参考的   宽和高,实际返回的大小由option.inSampleSize  确定
     */
    public Bitmap reSizePic(String path ,int width,int heith){
       BitmapFactory.Options option =  new BitmapFactory.Options();
//设置inJustDecodeBounds 为true之后,BitmapFactory.decodeFile 不返回bitmap,只是
//在option中返回图片的大小
inJustDecodeBounds = true;
       BitmapFactory.decodeFile(path,option);
       
       int oWidth = option.outWidth;
       int oHeihth = option.outHeight;
       System.out.println("-------------------- the originai size wihth and heigth "+oWidth+" , "+ oHeihth);
       System.out.println("-------------------- the request size wihth and heigth "+width+" , "+ heith);
 
       
// 计算缩放量,这里只是简单的计算。
        int scaleFactor = Math.min(oWidth/width, oHeihth/heith);
        
//重新设置为false,返回图片
inJustDecodeBounds = false;
//设置获得的图片的所放量,当为2时,返回的图片大小为原来的1/2
inSampleSize
        Bitmap res = BitmapFactory.decodeFile(path,option);
       System.out.println("-------------------- the resize real size wihth and heigth "+res.getWidth()+" , "+ res.getHeight());
 
        return res;
    }

注释已经写的很清楚了。另外onactivityResult回调稍微改一下,调用这个方法。

protected  void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == 100 && resultCode == RESULT_OK) {
//设置照片存储路径后,有的机型返回的intent 就为null,这时不能从里面取数据了,
// 需要从自己定义的路径取数据
//            Bitmap thumbnail = data.getParcelableExtra("data");
          
        Bitmap Opic = null;
//         try {
//            //读取文件。
//            Opic = BitmapFactory.decodeStream(new FileInputStream(tempFile));
//         } catch (FileNotFoundException e) {
//            // TODO Auto-generated catch block
//            e.printStackTrace();
//         }
//缩放
tempFile.getAbsolutePath(), 480, 640);
im.setImageBitmap(Opic);
// Do other work with full size photo saved in mLocationForPhotos
        }
    }

效果如下图,右边为打印的日志。

 

android 拍照调用 android调用系统拍照功能_媒体库_03

android 拍照调用 android调用系统拍照功能_媒体库_04

以上图片进行缩放后并没有存储,如果要进行存储,可以在适当时候调用以下方法。如果要覆盖原文件,只需要传入路径的时候传入原文件的路径就行。

/**   
    * 把bitmap 保存未指定位置的文件,默认类型为JPG格式
    */
    public  boolean saveBitMap(Bitmap bp,String desPath) {
       FileOutputStream out = null;
       boolean res = false;
       try {
           out = new FileOutputStream(desPath);
           bp.compress(CompressFormat.JPEG, 100, out);
           out.flush();
           res = true;
       } catch (IOException e) {
// TODO Auto-generated catch block
           e.printStackTrace();
       } finally {
           try {
              if (out != null)
                  out.close();
           } catch (IOException e) {
// TODO Auto-generated catch block
              e.printStackTrace();
           }
 
       }
       return res;
    }

至此图片缩放的工作完成。剩下更新多媒体库的问题。当我们采用类似以下代码来选择一张图片并返回的时候,我们发现,可选择的图片中,并没有我们之前调用相机拍照的图片(当然在文件管理的相应目录下可以看到)。

/**
     * 添加图片.
     */
    public  void addPhoto(int requetCode) {
// 选择图片 requestCode 返回的标
       Intent innerIntent = new Intent(Intent.ACTION_GET_CONTENT);
       innerIntent.addCategory(Intent.CATEGORY_OPENABLE);
"image/*"); // 查看类型
       Intent wrapperIntent = Intent.createChooser(innerIntent, "Add Photo");
 
       startActivityForResult(wrapperIntent, requetCode);
    }

为什么看不到我们刚才拍照的图片呢?这是android机制决定的。Android的媒体库信息实际上是以contentProvider提供的,媒体库在系统启动的时候扫描整个系统,把获得的媒体系统存储在内部db中,我们访问的实际上是db。所以当系统启动后,新增一张图片,在媒体库中是不可见。Android当然有更新媒体库的办法。方法调用如下,我们可以在拍完照返回的时候调用以下方法:

private  void galleryAddPic(String path1) {
       Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
       Uri contentUri = Uri.fromFile(new File(path1));
       mediaScanIntent.setData(contentUri);
       this.sendBroadcast(mediaScanIntent);
    }

上面的方法调用结果就不再贴图。至此问题基本解决完毕。