android之系统相机拍照

在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) {

            Bitmap thumbnail = data.getParcelableExtra("data");

            im.setImageBitmap(thumbnail);

            // Do other work with full size photo saved in mLocationForPhotos

        }

    }


上述代码看起来不错,但是图片怎么这么小呢?查阅文档发现,此时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. 并在回调中从传入的路径中读取图片。从显示的结果来看,显示的是拍照的图片。


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

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

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

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

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

/*

     *

     * 此方法并没有正在的改变原文件图片的大小。

     * widthheight 为参考的  宽和高,实际返回的大小option.inSampleSize  确定

     */

    public Bitmap reSizePic(String path ,int width,int heith){

       BitmapFactory.Options option =  new BitmapFactory.Options();

       //设置inJustDecodeBounds true之后,BitmapFactory.decodeFile 不返回bitmap,只是

       //option中返回图片的大小

       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,返回图片

        option.inJustDecodeBounds = false;

        //设置获得的图片的所放量,当为2时,返回的图片大小为原来的1/2

        option.inSampleSize = scaleFactor;

        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();

//         }

        //缩放

           Opic = reSizePic(tempFile.getAbsolutePath(), 480, 640);

            im.setImageBitmap(Opic);

            // Do other work with full size photo saved in mLocationForPhotos

        }

    }

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

 

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

/**  

    * 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);

       innerIntent.setType("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);

    }

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

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值