安卓 调用系统相机并裁剪

做程序猿已有一段时间,东西也做了挺多,今天刚开通了博客,把我之前做过的东西记录下来,今天先写安卓系统下调用系统照相机并裁剪

之前做调用系统相机的时候遇到过很多问题,现在贴代码,在代码中一点点提出

btn.setOnClickListener(new OnClickListener() {

  @Override
  public void onClick(View v) {
    Intent intent;
    String fileName = System.currentTimeMillis() + ".png";
    logoTempPath = LOGO_BASE_PATH + fileName;
    intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(LOGO_BASE_PATH, fileName)));
    startActivityForResult(intent, PHOTO_CAMERA);
  }
});

以上是点击某个按钮调用系统相机,在这里注意一点:

String fileName = System.currentTimeMillis() + ".png";拍出来的图片名称之所以这样来命名,是因为之前遇到过一个问题,即在拍完照之后裁剪时显示的图片是上一次拍的图片,现在更改临时文件名称随时产生。

----------------------------------------------------------------------------

if(requestCode == PHOTO_CAMERA) {//拍照获取
  int angle = readPictureDegree(logoTempPath);//有些手机拍完照片之后会有旋转,此处是获取照片旋转的角度,具体方法内容在后面贴出
  if(angle != 0)
    rotatePhoto(angle);//获取旋转角度之后,将图片旋转回来
  File file = new File(logoTempPath);
  startPhotoZoom(Uri.fromFile(file));//裁剪图片,代码后面贴出

}

上面是拍照之后onActivityResult方法中获取数据并调用裁剪,上面再调用拍照的时候已经将照片储存在固定位置,所以此处直接从那个位置(logoTempPath)读取数据,不用从intent中获取

之所以这样做是因为有些手机拍照之后返回的数据会为空

----------------------------------------------------------------------------

public void startPhotoZoom(Uri uri) {
  Intent intent = new Intent("com.android.camera.action.CROP");
  intent.setDataAndType(uri, "image/*");
  intent.putExtra("crop", "true");

  //这里的aspectX,aspectY是宽高的比例
  intent.putExtra("aspectX", 1);
  intent.putExtra("aspectY", 1);
  //outputX,outputY 网上查说是裁剪的宽高,其实个人感觉不是,具体是什么我也不清楚
  intent.putExtra("outputX", 200);
  intent.putExtra("outputY", 200);
  intent.putExtra("return-data", false);

  intent.putExtra("outputFormat", Bitmap.CompressFormat.PNG.toString());
  intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(LOGO_ZOOM_FILE_PATH)));

  startActivityForResult(intent, PHOTO_RESULT);
}

以上是裁剪的方法,这里注意一点intent.putExtra("return-data", false);这里没有设置为true,所以在裁剪之后也不能从intent中获取数据,

之前有做过设置为true,但是有些手机拍完照之后图片占内存很大,在调用裁剪的话会报OOM,这里修改为不返回数据,而是直接将数据保存在自己设置的位置上

这样改之后就不会有oom的问题

----------------------------------------------------------------------------

if(requestCode == PHOTO_RESULT) {//裁剪之后
  Bitmap bitmap  = BitmapFactory.decodeFile(LOGO_ZOOM_FILE_PATH);
获取裁剪之后的图片。

-----------------------------------------------------------------------------

public int readPictureDegree(String path) {
  int degree = 0;
  try {
    ExifInterface exifInterface = new ExifInterface(path);
    int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
    switch (orientation) {
      case ExifInterface.ORIENTATION_ROTATE_90:
        degree = 90;
      break;
      case ExifInterface.ORIENTATION_ROTATE_180:
        degree = 180;
      break;
      case ExifInterface.ORIENTATION_ROTATE_270:
        degree = 270;
      break;
    }
  } catch (IOException e) {
    e.printStackTrace();
  }
  return degree;
}

获取拍照之后图片旋转的角度

----------------------------------------------------------------------------

public void rotatePhoto(int angle) {

  WindowManager wm = getWindowManager();
  int windowWidth = wm.getDefaultDisplay().getWidth();
  int windowHeight = wm.getDefaultDisplay().getHeight();

  BitmapFactory.Options opts = new BitmapFactory.Options();
  opts.inJustDecodeBounds = true;
  BitmapFactory.decodeFile(logoTempPath, opts);
  opts.inPreferredConfig = Bitmap.Config.RGB_565;
  int bitmapHeight = opts.outHeight;
  int bitmapWidth = opts.outWidth;
  if (bitmapHeight > windowHeight || bitmapWidth > windowWidth) {
    int scaleX = bitmapWidth / windowWidth;
    int scaleY = bitmapHeight / windowHeight;
    if(scaleX > scaleY)//按照水平方向的比例缩放
      opts.inSampleSize = scaleX;
    else //按照竖直方向的比例缩放
      opts.inSampleSize = scaleY;
  } else {//图片比手机屏幕小 不缩放
    opts.inSampleSize = 1;
  }
  opts.inJustDecodeBounds = false;
  Matrix m = new Matrix();
  m.postRotate(angle);
  Bitmap bitmap = null;
  try {
    bitmap = BitmapFactory.decodeFile(logoTempPath, opts);
    if(bitmap == null)
      return;
    bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, true);// 重新生成图片
    saveToFile(bitmap);//将新生成的图片保存的指定位置,以供后面裁剪时调用,具体代码就不贴出了
   } catch (OutOfMemoryError e) {
    System.gc();
   } finally {
    if(bitmap != null)
      bitmap.recycle();
   }
}

以上是讲旋转的图片再转回去生成新的图片,保存到指定位置

----------------------------------------------------------------------------

最后再讲一个我最近遇到的问题,问题描述如下:

调用相机之后按home键退出程序,在手机上打开照相机拍几张照片,退出照相机重新进入程序,这时点击拍照确认键,跳转到裁剪界面时界面是黑的,没有任何照片显示。

经过一个下午的排查,最终找到原因,操作这个步骤之后,之前调用裁剪时保存的图片位置及名称已经不存在了即logoTempPath 在返回程序时已经为空了,而且本程序的这个activity重新走了onCreate方法,

所以在程序中logoTempPath为空,解决方法:

@Override
protected void onSaveInstanceState(Bundle outState) {
  super.onSaveInstanceState(outState);
  outState.putString("logoTempPath", logoTempPath);
}

将之前设置的信息保存,在下次进入本程序的onCreate方法时重新获取。

----------------------------------------------------------------------------

以上就是本次的所有内容了,第一次写博客没有经验,不足之处还望指正^_^

时间: 2024-10-18 06:43:53

安卓 调用系统相机并裁剪的相关文章

安卓 调用系统相册并裁剪

上一篇写了关于调用系统相机并裁剪,这一片写关于调用系统相册裁剪照片 btn_album.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent; logoTempPath = LOGO_BASE_PATH + System.currentTimeMillis() + ".png"; intent = new Intent(Intent.ACTION_

安卓调用系统相机三步走

第一步: <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> 第二步: Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTU

调用系统相机,相册功能

一开始的思路是这一块的功能单独出去;这样处理又会碰见很多问题. 还是集成在Activity中可能效果更好些, 而且三星的手机调用系统相机会导致调用的Activity会重启生命周期,如果是在fragment中调用的,会碰见更多的问题,做外包的伤不起,想深入下这个问题都没时间,暂时记录下在Activity中解决问题的方法,方便后面使用时直接拿来用. 比如在Activity中点击某个按钮,弹出一个对话框,选择拍照还是选择图片 mButton.setOnClickListener(new OnClick

Android7.0调用系统相机拍照、读取系统相册照片+CropImageView剪裁照片

Android手机拍照.剪裁,并非那么简单 简书地址:[我的简书–T9的第三个三角] 前言 项目中,基本都有用户自定义头像或自定义背景的功能,实现方法一般都是调用系统相机–拍照,或者系统相册–选择照片,然后进行剪裁,最终设为头像或背景. 而在Android6.0之后,需要动态获取权限,而且Android7.0之后,无法直接根据拍照返回的URI拿到图片,这是因为从安卓7.0开始,直接使用本地真实路径被认为是不安全的,会抛出FileUriExposedExCeption异常,本文就是基于这个功能去针

Android调用系统相机拍照保存照片很小解决方案

保存图片小的一般操作步骤: 1. 调用系统相机 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(intent, 1); 2. 保存照片 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {  // TODO Auto-generated method s

Android调用系统相机、自定义相机、处理大图片

Android调用系统相机和自定义相机实例 本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显示出来,该例子也会涉及到Android加载大图片时候的处理(避免OOM),还有简要提一下有些人SurfaceView出现黑屏的原因. Android应用拍照的两种方式,下面为两种形式的Demo展示出来的效果.    知识点: 一.调用系统自带的相机应用 二.自定义我们自己的拍照界面 三.关于计算机解析图片原理(如何正确加载图片到Android应用中) 所需

Android6.0机型上调用系统相机拍照返回的resultCode值始终等于0的问题

版权声明:本文为博主原创文章,未经博主允许不得转载. 正常情况下调用系统相机拍照: 如果拍照后点击的是“确定”图标,返回的resultCode = -1(Activity.RESULT_OK): 如果点击的是底部的“返回”键,返回的resultCode = 0(Activity.RESULT_CANCELED). 简单的调用系统相机的写法: //调用系统拍照 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); String p

Android 调用系统相机拍照保存以及调用系统相册的方法

系统已经有的东西,如果我们没有新的需求的话,直接调用是最直接的.下面讲讲调用系统相机拍照并保存图片和如何调用系统相册的方法. 首先看看调用系统相机的核心方法: Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(camera, CAMERA); 相机返回的数据通过下面的回调方法取得,并处理: public static final int CAMERA  = 0x01; @Over

Android简单的调用系统相机和相册

  public void reasonAdd(View v)     {        final String [] strs=new String[]{"拍照","相册"};         AlertDialog.Builder builder=new AlertDialog.Builder(this);         builder.setTitle("照片");         builder.setItems(strs, new