Android实现拍照及图片裁剪(6.0以上权限处理及7.0以上文件管理)

最近做项目中涉及到了图片相关功能 ,在使用安卓6.0手机及7.1手机拍照时,遇到了因权限及文件管理导致程序崩溃等问题。
 刚好把功能修改完,把代码简单地贴一下,方便以后使用。

—-主界面 代码 ——

public class MainActivity extends AppCompatActivity {
  //拍照按钮
  private Button take_photo;
  //显示裁剪后的图片
  private ImageView photo_iv;
  private static final int PERMISSIONS_FOR_TAKE_PHOTO = 10;
  //图片文件路径
  private String picPath;
  //图片对应Uri
  private Uri photoUri;
  //拍照对应RequestCode
  public static final int SELECT_PIC_BY_TACK_PHOTO = 1;
  //裁剪图片
  private static final int CROP_PICTURE = 3;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    take_photo = (Button) findViewById(R.id.take_photo);
    photo_iv = (ImageView) findViewById(R.id.photo_iv);
    take_photo.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
        //小于6.0版本直接操作
        if (Build.VERSION.SDK_INT < 23) {
          takePictures();
        } else {
          //6.0以后权限处理
          permissionForM();
        }
      }
    });
  }

  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == Activity.RESULT_OK) {
      if (requestCode == SELECT_PIC_BY_TACK_PHOTO) {
        String[] pojo = {MediaStore.Images.Media.DATA};
        Cursor cursor = managedQuery(photoUri, pojo, null, null, null);
        if (cursor != null) {
          int columnIndex = cursor.getColumnIndexOrThrow(pojo[0]);
          cursor.moveToFirst();
          picPath = cursor.getString(columnIndex);
          if (Build.VERSION.SDK_INT < 14) {
            cursor.close();
          }
        }
        if (picPath != null && (picPath.endsWith(".png") || picPath.endsWith(".PNG") || picPath.endsWith(".jpg") || picPath.endsWith(".JPG"))) {
          photoUri = Uri.fromFile(new File(picPath));
          if (Build.VERSION.SDK_INT > 23) {
            photoUri = FileProvider.getUriForFile(this, "com.innopro.bamboo.fileprovider", new File(picPath));
            cropForN(picPath, CROP_PICTURE);
          } else {
            startPhotoZoom(photoUri, CROP_PICTURE);
          }
        } else {
          //错误提示
        }
      }
      if (requestCode == CROP_PICTURE) {
        if (photoUri != null) {
          Bitmap bitmap = BitmapFactory.decodeFile(picPath);
          if (bitmap != null) {
            photo_iv.setImageBitmap(bitmap);
          }
        }
      }
    }
  }

  /**
   * 拍照获取图片
   */
  private void takePictures() {
    //执行拍照前,应该先判断SD卡是否存在
    String SDState = Environment.getExternalStorageState();
    if (SDState.equals(Environment.MEDIA_MOUNTED)) {
      Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
      ContentValues values = new ContentValues();
      photoUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
      intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
      startActivityForResult(intent, SELECT_PIC_BY_TACK_PHOTO);
    } else {
      Toast.makeText(this, "手机未插入内存卡", Toast.LENGTH_LONG).show();
    }
  }

  /**
   * 图片裁剪,参数根据自己需要设置
   *
   * @param uri
   * @param REQUE_CODE_CROP
   */
  private void startPhotoZoom(Uri uri,
                int REQUE_CODE_CROP) {
    int dp = 500;
    Intent intent = new Intent("com.android.camera.action.CROP");
    intent.setDataAndType(uri, "image/*");
    // 下面这个crop=true是设置在开启的Intent中设置显示的VIEW可裁剪
    intent.putExtra("crop", "true");
    intent.putExtra("scale", true);// 去黑边
    intent.putExtra("scaleUpIfNeeded", true);// 去黑边
    // aspectX aspectY 是宽高的比例
    intent.putExtra("aspectX", 4);//输出是X方向的比例
    intent.putExtra("aspectY", 3);
    intent.putExtra("outputX", 600);//输出X方向的像素
    intent.putExtra("outputY", 450);
    intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
    intent.putExtra("noFaceDetection", true);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
    intent.putExtra("return-data", false);//设置为不返回数据
    startActivityForResult(intent, REQUE_CODE_CROP);
  }

  /**
   * 7.0以上版本图片裁剪操作
   *
   * @param imagePath
   * @param REQUE_CODE_CROP
   */
  private void cropForN(String imagePath, int REQUE_CODE_CROP) {
    Uri cropUri = getImageContentUri(new File(imagePath));
    Intent intent = new Intent("com.android.camera.action.CROP");
    intent.setDataAndType(cropUri, "image/*");
    intent.putExtra("crop", "true");
    //输出是X方向的比例
    intent.putExtra("aspectX", 4);
    intent.putExtra("aspectY", 3);
    // outputX outputY 是裁剪图片宽高
    intent.putExtra("outputX", 600);
    intent.putExtra("outputY", 450);
    intent.putExtra("scale", true);
    intent.putExtra("return-data", false);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, cropUri);
    intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
    intent.putExtra("noFaceDetection", true);
    startActivityForResult(intent, REQUE_CODE_CROP);
  }

  private Uri getImageContentUri(File imageFile) {
    String filePath = imageFile.getAbsolutePath();
    Cursor cursor = getContentResolver().query(
        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
        new String[]{MediaStore.Images.Media._ID},
        MediaStore.Images.Media.DATA + "=? ",
        new String[]{filePath}, null);

    if (cursor != null && cursor.moveToFirst()) {
      int id = cursor.getInt(cursor
          .getColumnIndex(MediaStore.MediaColumns._ID));
      Uri baseUri = Uri.parse("content://media/external/images/media");
      return Uri.withAppendedPath(baseUri, "" + id);
    } else {
      if (imageFile.exists()) {
        ContentValues values = new ContentValues();
        values.put(MediaStore.Images.Media.DATA, filePath);
        return getContentResolver().insert(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
      } else {
        return null;
      }
    }
  }

  /**
   * 安卓6.0以上版本权限处理
   */
  private void permissionForM() {
    if (ContextCompat.checkSelfPermission(this,
        Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this,
        Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this,
        Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {

      ActivityCompat.requestPermissions(this,
          new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE},
          PERMISSIONS_FOR_TAKE_PHOTO);
    } else {
      takePictures();
    }
  }

  @Override
  public void onRequestPermissionsResult(int requestCode,
                      @NonNull String[] permissions, @NonNull int[] grantResults) {

    if (requestCode == PERMISSIONS_FOR_TAKE_PHOTO) {
      if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        takePictures();
      }
      return;
    }
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  }

}

–主界面布局——–

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context="com.innopro.improve.MainActivity">

  <Button
    android:id="@+id/take_photo"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="拍照"
    android:textSize="18sp"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

  <ImageView
    android:id="@+id/photo_iv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@mipmap/ic_launcher"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@id/take_photo" />

</android.support.constraint.ConstraintLayout>

–AndroidManifest.xml添加provider——–

   <provider
      android:name="android.support.v4.content.FileProvider"
      android:authorities="com.innopro.improve.fileprovider"
      android:exported="false"
      android:grantUriPermissions="true">
      <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
    </provider>

–资源文件下添加xml文件夹及file_paths文件——–

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <paths>
    <external-path
      name="camera_photos"
      path="" />
  </paths>
</resources>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

时间: 2017-10-18

Android拍照得到全尺寸图片并进行压缩

废话不多说了,直接给大家贴代码了,具体代码如下所示: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <

Android应用中拍照后获取照片路径并上传的实例分享

Activity 中的代码,我只贴出重要的事件部分代码 public void doPhoto(View view) { destoryBimap(); String state = Environment.getExternalStorageState(); if (state.equals(Environment.MEDIA_MOUNTED)) { Intent intent = new Intent("android.media.action.IMAGE_CAPTURE"); s

android 拍照和上传的实现代码

复制代码 代码如下: import java.io.ByteArrayOutputStream;   import java.io.File;   import android.app.Activity;   import android.content.Intent;   import android.graphics.Bitmap;   import android.net.Uri;   import android.os.Bundle;   import android.os.Enviro

Android拍照保存在系统相册不显示的问题解决方法

可能大家都知道我们保存相册到Android手机的时候,然后去打开系统图库找不到我们想要的那张图片,那是因为我们插入的图片还没有更新的缘故,先讲解下插入系统图库的方法吧,很简单,一句代码就能实现 复制代码 代码如下: MediaStore.Images.Media.insertImage(getContentResolver(), mBitmap, "", ""); 通过上面的那句代码就能插入到系统图库,这时候有一个问题,就是我们不能指定插入照片的名字,而是系统给了我

Android启动相机拍照并返回图片

具体实现过程请看下面代码: 简单的调用了一下系统的拍照功能 代码如下所示: //拍照的方法 private void openTakePhoto(){ /** * 在启动拍照之前最好先判断一下sdcard是否可用 */ String state = Environment.getExternalStorageState(); //拿到sdcard是否可用的状态码 if (state.equals(Environment.MEDIA_MOUNTED)){ //如果可用 Intent intent

Android仿微信发表说说实现拍照、多图上传功能

本文实例为大家分享了Android仿微信发表说说.心情功能,供大家参考,具体内容如下 既能实现拍照,选图库,多图案上传的案例,目前好多App都有类似微信朋友圈的功能,能过发表说说等附带图片上传.下面的就是实现该功能的过程:大家还没有看过Android Retrofit 2.0框架上传图片解决方案这篇文章,在看今天的就很容易,接在本项目中用到了一个library:photopicker,封装了图片的选择功能,是否选相机,还有选中图片后可以查看图片的功能.  一. 首先:将photopicker到工

android图像绘制(六)获取本地图片或拍照图片等图片资源

从SD卡中获取图片资源,或者拍一张新的图片. 先贴代码 获取图片: 注释:拍照获取的话,可以指定图片的保存地址,在此不说明. 复制代码 代码如下: CharSequence[] items = {"相册", "相机"}; new AlertDialog.Builder(this) .setTitle("选择图片来源") .setItems(items, new OnClickListener() { public void onClick(Dia

Android实现拍照、选择图片并裁剪图片功能

一. 实现拍照.选择图片并裁剪图片效果 按照之前博客的风格,首先看下实现效果. 二. uCrop项目应用 想起之前看到的Yalantis/uCrop效果比较绚,但是研究源码之后发现在定制界面方面还是有一点的限制,于是在它的基础上做了修改Android-Crop,把定制界面独立出来,让用户去自由设置.下图为使用Android-Crop实现的模仿微信选择图片并裁剪Demo. 三. 实现思路 比较简单的选择设备图片裁剪,并将裁剪后的图片保存到指定路径: 调用系统拍照,将拍照图片保存在SD卡,然后裁剪图

Android圆形头像拍照后“无法加载此图片”的问题解决方法(适配Android7.0)

Feature: 点击选择拍照或者打开相册,选取图片进行裁剪最后设置为圆形头像. Problem: 拍好照片,点击裁剪,弹Toast"无法加载此图片". Solution: 在裁剪的class里加两行代码 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 主要代码如下: public static final S

Android ListView滚动到底后自动加载数据

熟悉Android的朋友们都知道,不管是微博客户端还是新闻客户端,都离不开列表组件,可以说列表组件是Android数据展现方面最重要的组件,我们 今天就要讲一讲列表组件ListView加载数据的相关内容.通常来说,一个应用在展现大量数据时,不会将全部的可用数据都呈现给用户,因为这不管对于服 务端还是客户端来说都是不小的压力,因此,很多应用都是采用分批次加载的形式来获取用户所需的数据.比如:微博客户端可能会在用户滑动至列表底端时自动加 载下一页数据,也可能在底部放置一个"加载更多"按钮,

Android实现疯狂连连看游戏之加载界面图片和实现游戏Activity(四)

正如在<我的Android进阶之旅------>Android疯狂连连看游戏的实现之状态数据模型(三)>一文中看到的,在AbstractBoard的代码中,当程序需要创建N个Piece对象时,程序会直接调用ImageUtil的getPlayImages()方法去获取图片,该方法会随机从res/drawable目录中取得N张图片. 下面是res/drawable目录视图: 为了让getPlayImages()方法能随机从res/drawable目录中取得N张图片,具体实现分为以下几步: 通

Android插件化之资源动态加载

Android插件化之资源动态加载 一.概述 Android插件化的一个重要问题就是插件资源访问问题,先列出会面对的问题 1.如何加载插件资源 2.如何处理插件资源与宿主资源的处突:插件化资源问题要做到的效果是,如果我们要获取的资源在插件中找得到,则加载优先加载插件的,如果找不到,则到宿主资源中找.这样能做到动态更新的效果. 3.如何确保插件和宿主使用到的是被修改过的资源. 二.原理分析 在做一件事之前必须先弄清楚原理,所以,这里先要弄清楚Android的资源体系原理. 1.资源链 Contex

Android自定义view实现阻尼效果的加载动画

效果: 需要知识: 1. 二次贝塞尔曲线 2. 动画知识 3. 基础自定义view知识 先来解释下什么叫阻尼运动 阻尼振动是指,由于振动系统受到摩擦和介质阻力或其他能耗而使振幅随时间逐渐衰减的振动,又称减幅振动.衰减振动.[1] 不论是弹簧振子还是单摆由于外界的摩擦和介质阻力总是存在,在振动过程中要不断克服外界阻力做功,消耗能量,振幅就会逐渐减小,经过一段时间,振动就会完全停下来.这种振幅随时间减小的振动称为阻尼振动.因为振幅与振动的能量有关,阻尼振动也就是能量不断减少的振动.阻尼振动是非简谐运

Android使用PullToRefresh实现上拉加载和下拉刷新效果的代码

在没给大家介绍正文之前,先给大家介绍展示下运行图,如果大家感觉还不错,请继续往下阅读: 相关阅读:分享Android中pullToRefresh的使用心得 项目已同步至:https://github.com/nanchen2251/pullToRefreshDemo 简单使用详情: 1)studio可以直接在app的module设置中直接进行搜索,但是有-的必须添上,而不能用空格代替,为了更加了解这个东西,我还是推荐大家去这里看看,奉上网址: https://github.com/chrisba

Android使用原生组件WebView加载网页和数据的方法

在Api中关于这个类的介绍大致就是这是一个可以显示网页的视图,如: webView.loadUrl(http://www.baidu.com/); 显示结果: 还可以加载一些html的字符串,如: String str = "<html><body>You scored <b>192</b> points.</body></html>"; webView.loadData(str, "text/html&

Android下拉刷新上拉加载控件(适用于所有View)

前面写过一篇关于下拉刷新控件的文章下拉刷新控件终结者:PullToRefreshLayout,后来看到好多人还有上拉加载更多的需求,于是就在前面下拉刷新控件的基础上进行了改进,加了上拉加载的功能.不仅如此,我已经把它改成了对所有View都通用!可以随心所欲使用这两个功能~~ 我做了一个大集合的demo,实现了ListView.GridView.ExpandableListView.ScrollView.WebView.ImageView.TextView的下拉刷新和上拉加载.后面会提供demo的

Android 实现加载大图片的方法

项目简介: 该项目为加载大图片 详细介绍: 对于超大的图片,如果不缩放的话,容易导致内存溢出.而经过处理后,无论多大的图片,都能够在手机屏幕上加载出来,不会导致内存溢出.当然,脸黑的除外 该应用涉及到的知识有: - 1.Bitmap的使用 - 2.Android手机中加载图片的原理 有的时候,我们加载一张不足1M的图片,尽管手机的堆内存有16M,仍然会导致内存溢出,why? 这就更计算机加载图片的原理有关了: 1).手机会解析图片的所有像素信息,把每个像素信息都存入到内存中 2).Android

Android 使用 Path 实现搜索动态加载动画效果

今天实现一个搜索动态加载数据的动画效果,还是先看效果吧,用文字描述干巴巴的,看图说话什么都明白了, 实现这个就是使用Path中的getSegment()不断的去改变它截取片段的start和stop,再结合动画,今天就分步骤实现它,看完以后你也会觉的不是很难,只是没想到这么实现而已,所以要多见识,所谓眼界决定你的高度,还是延续我写博客的习惯,一步步分析,第一步就是绘制如下图: 如果单纯的绘制这个图很简单很简单的,绘制一个圆,然后再绘制一根线就搞定,但是要考虑这里的效果,就不能这么干了,如果你看了上