Android获取照片、裁剪图片、压缩图片

前言

在做上一个项目时深深受到了图片上传的苦恼。图片上传主要分为两个部分,首先要获取图片,而获取图片可以分为从文件获取或者拍照获取。第二个部分才是上传图片,两个部分都是走了不少弯路。由于Android系统的碎片化比较严重,我们可能出现在第一台机子上能获取图片,但是换一个机子就不能获取图片的问题,并且在Android6.0,7.0之后也要做一定的适配,这样对于开发者来说,无疑很蛋疼。由于也是初学者,很多东西没有考虑到,适配起来也是有点难度的。

这几天也是从github上找到了一个库(地址在这TakePhoto),经过简单的学习之后,发现用起来还是蛮简单的,并且在不同机型之间都能达到同样的效果。更重要的是可以根据不同配置达到不同的效果

接下来看下用法

获取图片

1) 获取TakePhoto对象

一) 通过继承的方式

继承TakePhotoActivity、TakePhotoFragmentActivity、TakePhotoFragment三者之一。
通过getTakePhoto()获取TakePhoto实例进行相关操作。
重写以下方法获取结果

 void takeSuccess(TResult result);
 void takeFail(TResult result,String msg);
 void takeCancel();

这种方法使用起来虽然简单,但是感觉定制性不高,必须继承指定的Activity,而 有时我们已经封装好了BaseActivity,不想再改了。有时候通过继承无法满足实际项目的需求。

二) 通过组装的方式去使用

实现TakePhoto.TakeResultListener,InvokeListener接口。
在 onCreate,onActivityResult,onSaveInstanceState方法中调用TakePhoto对用的方法。
重写onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults),添加如下代码。

 @Override
  public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    //以下代码为处理Android6.0、7.0动态权限所需
    TPermissionType type=PermissionManager.onRequestPermissionsResult(requestCode,permissions,grantResults);
    PermissionManager.handlePermissionsResult(this,type,invokeParam,this);
  }

重写TPermissionType invoke(InvokeParam invokeParam)方法,添加如下代码:

 @Override
  public TPermissionType invoke(InvokeParam invokeParam) {
    TPermissionType type=PermissionManager.checkPermission(TContextWrap.of(this),invokeParam.getMethod());
    if(TPermissionType.WAIT.equals(type)){
      this.invokeParam=invokeParam;
    }
    return type;
  }

添加如下代码获取TakePhoto实例:

  /**
   * 获取TakePhoto实例
   * @return
   */
  public TakePhoto getTakePhoto(){
    if (takePhoto==null){
      takePhoto= (TakePhoto) TakePhotoInvocationHandler.of(this).bind(new TakePhotoImpl(this,this));
    }
    return takePhoto;
  }

2)自定义UI

不仅可以对于参数自定义,也可以对于UI的自定义,比如自定义相册,自定义Toolbar, 自定义状态栏,自定义提示文字,自定义裁切工具(需要使用自带的TakePhoto裁剪才行)。

3)通过TakePhoto对象获取图片

支持从相册获取,也支持拍照,相关Api

 * 从相机获取图片并裁剪
 * @param outPutUri 图片裁剪之后保存的路径
 * @param options 裁剪配置
 */
void onPickFromCaptureWithCrop(Uri outPutUri, CropOptions options);
/**
 * 从相册中获取图片并裁剪
 * @param outPutUri 图片裁剪之后保存的路径
 * @param options 裁剪配置
 */
void onPickFromGalleryWithCrop(Uri outPutUri, CropOptions options);
/**
 * 从文件中获取图片并裁剪
 * @param outPutUri 图片裁剪之后保存的路径
 * @param options 裁剪配置
 */
void onPickFromDocumentsWithCrop(Uri outPutUri, CropOptions options);
/**
 * 图片多选,并裁切
 * @param limit 最多选择图片张数的限制
 * @param options 裁剪配置
 * */
void onPickMultipleWithCrop(int limit, CropOptions options);

4)裁剪配置

CropOptions 用于裁剪的配置类,可以对图片的裁剪比例,最大输出大小,以及是否使用TakePhoto自带的裁剪工具进行裁剪等,进行个性化配置。

压缩图片 onEnableCompress(CompressConfig config,boolean showCompressDialog)

指定压缩工具 takePhoto里面自带压缩算法,也可以通过第三方的Luban进行压缩

对于TakePhoto的二次封装

封装是对第二种方法的封装,主要参考了第一种的思想封装的。
关于TakePhoto的库代码全部封装到一个TakePhotoUtil工具类中,看代码:

public class TakePhotoUtil implements TakePhoto.TakeResultListener, InvokeListener {

  private static final String TAG = TakePhotoUtil.class.getName();
  private TakePhoto takePhoto;
  private InvokeParam invokeParam;
  private Activity activity;
  private Fragment fragment;

  public TakePhotoUtil(Activity activity){
    this.activity = activity;
  }

  public TakePhotoUtil(Fragment fragment){
    this.fragment = fragment;
  }

  /**
   * 获取TakePhoto实例
   * @return
   */
  public TakePhoto getTakePhoto(){
    if (takePhoto==null){
      takePhoto= (TakePhoto) TakePhotoInvocationHandler.of(this).bind(new TakePhotoImpl(activity,this));
    }
    return takePhoto;
  }

  public void onCreate(Bundle savedInstanceState){
    getTakePhoto().onCreate(savedInstanceState);
  }

  public void onSaveInstanceState(Bundle outState){
    getTakePhoto().onSaveInstanceState(outState);
  }

  public void onActivityResult(int requestCode, int resultCode, Intent data){
    getTakePhoto().onActivityResult(requestCode, resultCode, data);
  }

  public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    PermissionManager.TPermissionType type=PermissionManager.onRequestPermissionsResult(requestCode,permissions,grantResults);
    PermissionManager.handlePermissionsResult(activity,type,invokeParam,this);
  }

  /**
   *
   * @param result
   */
  @Override
  public void takeSuccess(TResult result) {
    if(listener != null){
      listener.takeSuccess(result);
    }
//    deleteCachePic();
  }

  @Override
  public void takeFail(TResult result, String msg) {
    if(listener != null){
      listener.takeFail(result, msg);
    }
//    deleteCachePic();
  }

  @Override
  public void takeCancel() {
    if(listener != null){
      listener.takeCancel();
    }
  }

  public void deleteCachePic(){
    File file=new File(Environment.getExternalStorageDirectory(), "/takephoto/");
    if(!file.exists()) return;

    File[] files = file.listFiles();
    for (File f: files) {
      f.delete();
    }
  }

  public interface TakePhotoListener{
    void takeSuccess(TResult result);
    void takeFail(TResult result, String msg);
    void takeCancel();
  }

  public TakePhotoListener listener;

  public void setTakePhotoListener(SimpleTakePhotoListener listener){
    this.listener = listener;
  }

  public static class SimpleTakePhotoListener implements TakePhotoListener{

    @Override
    public void takeSuccess(TResult result) {

    }

    @Override
    public void takeFail(TResult result, String msg) {

    }

    @Override
    public void takeCancel() {

    }
  }

  @Override
  public PermissionManager.TPermissionType invoke(InvokeParam invokeParam) {
    PermissionManager.TPermissionType type=PermissionManager.checkPermission(TContextWrap.of(activity),invokeParam.getMethod());
    if(PermissionManager.TPermissionType.WAIT.equals(type)){
      this.invokeParam=invokeParam;
    }
    return type;
  }

  /**
   *
   * @param select_type
   */
  public void takePhoto(Select_type select_type, SimpleTakePhotoListener listener){
    takePhoto(select_type, null, listener);
  }

  public void takePhoto(Select_type select_type, PhotoConfigOptions cropOptions, SimpleTakePhotoListener listener){
    if (takePhoto == null){
      Toast.makeText(activity, "请先开启照片功能", Toast.LENGTH_SHORT).show();
      return;
    }

    setTakePhotoListener(listener);

    if(cropOptions == null){
      cropOptions = new PhotoConfigOptions();
    }

    cropOptions.configCompress();  //压缩配置
    cropOptions.configTakePhoto(); //拍照配置

    File file=new File(Environment.getExternalStorageDirectory(), "/takephoto/"+System.currentTimeMillis() + ".jpg");
    if (!file.getParentFile().exists())file.getParentFile().mkdirs();
    Uri imageUri = Uri.fromFile(file);

    switch (select_type){
      case PICK_BY_SELECT: //从相册获取
        if(cropOptions.limit > 1){
          if(cropOptions.crop == true){
            takePhoto.onPickMultipleWithCrop(cropOptions.limit, cropOptions.getCropOptions());
          }else {
            takePhoto.onPickMultiple(cropOptions.limit);
          }
        }
        if(cropOptions.chooseFromFile){
          if(cropOptions.crop == true){
            takePhoto.onPickFromDocumentsWithCrop(imageUri, cropOptions.getCropOptions());
          }else {
            takePhoto.onPickFromDocuments();
          }
        }else {
          if(cropOptions.crop == true){
            takePhoto.onPickFromGalleryWithCrop(imageUri, cropOptions.getCropOptions());
          }else {
            takePhoto.onPickFromGallery();
          }
        }
        break;
      case PICK_BY_TAKE: //拍照获取
        if(cropOptions.crop == true){
          takePhoto.onPickFromCaptureWithCrop(imageUri, cropOptions.getCropOptions());
        }else {
          takePhoto.onPickFromCapture(imageUri);
        }
        break;
      default:
        break;
    }
  }

  /**
   * 图片的裁剪配置选项内部类
   */
  public class PhotoConfigOptions{
    //裁剪配置
    private boolean crop = true; //是否裁剪
    private boolean withWonCrop = true; //是否采用自带的裁剪工具,默认选取第三方的裁剪工具
    private boolean cropSize = true; //尺寸还是比例

    //压缩配置
    private boolean useOwnCompressTool = true; //使用自带的压缩工具
    private boolean isCompress = true; //是否压缩
    private boolean showProgressBar = true; //显示压缩进度条
//    private
    private int maxSize = 102400;

    //选择图片配置
    private boolean useOwnGallery = true; //选择使用自带的相册
    private boolean chooseFromFile = false; //从文件获取图片
    private int limit = 1; //选择最多图片的配置,选择多张图片会自动切换到TakePhoto自带相册

    //其它配置
    private boolean savePic = true; //选择完之后是否保存图片
    private boolean correctTool = false; //纠正拍照的照片旋转角度

    private int height = 800;
    private int width = 800;

    /**
     * 裁剪相关配置
     * @return
     */
    public CropOptions getCropOptions(){
      if(crop == false) return null;

      CropOptions.Builder builder = new CropOptions.Builder();
      if(cropSize){
        builder.setOutputX(width).setOutputY(height);
      }else {
        builder.setAspectX(width).setAspectY(height);
      }
      builder.setWithOwnCrop(withWonCrop); //默认采用第三方配置
      return builder.create();
    }

    /**
     * 图片压缩相关配置
     */
    public void configCompress(){
      if(isCompress == false) {
        takePhoto.onEnableCompress(null, false);
        return;
      }

      CompressConfig config;
      if(useOwnCompressTool){
        config = new CompressConfig.Builder()
            .setMaxSize(maxSize)
            .setMaxPixel(width>height?width:height)
            .enableReserveRaw(savePic)
            .create();
      }else {
        LubanOptions options = new LubanOptions.Builder()
            .setMaxHeight(height)
            .setMaxWidth(maxSize)
            .create();
        config = CompressConfig.ofLuban(options);
        config.enableReserveRaw(savePic);
      }
      takePhoto.onEnableCompress(config, showProgressBar);
    }

    public void configTakePhoto(){
      TakePhotoOptions.Builder builder = new TakePhotoOptions.Builder();
      if(useOwnGallery){
        builder.setWithOwnGallery(true);
      }
      if(correctTool){
        builder.setCorrectImage(true);
      }
      takePhoto.setTakePhotoOptions(builder.create());
    }

    public void setCrop(boolean crop) {
      this.crop = crop;
    }

    public void setWithWonCrop(boolean withWonCrop) {
      this.withWonCrop = withWonCrop;
    }

    public void setCropSize(boolean cropSize) {
      this.cropSize = cropSize;
    }

    public void setUseOwnCompressTool(boolean useOwnCompressTool) {
      this.useOwnCompressTool = useOwnCompressTool;
    }

    public void setCompress(boolean compress) {
      isCompress = compress;
    }

    public void setShowProgressBar(boolean showProgressBar) {
      this.showProgressBar = showProgressBar;
    }

    public void setMaxSize(int maxSize) {
      this.maxSize = maxSize;
    }

    public void setUseOwnGallery(boolean useOwnGallery) {
      this.useOwnGallery = useOwnGallery;
    }

    public void setChooseFromFile(boolean chooseFromFile) {
      this.chooseFromFile = chooseFromFile;
    }

    public void setLimit(int limit) {
      this.limit = limit;
    }

    public void setSavePic(boolean savePic) {
      this.savePic = savePic;
    }

    public void setCorrectTool(boolean correctTool) {
      this.correctTool = correctTool;
    }

    public void setHeight(int height) {
      this.height = height;
    }

    public void setWidth(int width) {
      this.width = width;
    }
  }

  /**
   * 照片获取方式, 从相册获取或拍照处理
   */
  public enum Select_type{
    PICK_BY_SELECT, PICK_BY_TAKE
  }
}

封装了一个BaseTakePhotoActivity,里面的代码如下:

 protected TakePhotoUtil takePhotoUtil;

  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    takePhotoUtil = new TakePhotoUtil(this);
    if(useTakePhoto()){
      takePhotoUtil.onCreate(savedInstanceState);
    }
    super.onCreate(savedInstanceState);
  }

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    if(useTakePhoto()){
      takePhotoUtil.onSaveInstanceState(outState);
    }
    super.onSaveInstanceState(outState);
  }

  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if(useTakePhoto()){
      takePhotoUtil.onActivityResult(requestCode, resultCode, data);
    }
    super.onActivityResult(requestCode, resultCode, data);
  }

  @Override
  public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    if(useTakePhoto()){
      takePhotoUtil.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  }

  protected boolean useTakePhoto(){
    return false;
  }

其他对于业务的封装,可以再封装一个BaseActivity,继承自BaseTakePhotoActivity,这样就可以不影响BaseActivity的使用,如果我们在主Activity中使用获取图片的功能需要两步

1)开启TakePhoto功能

@Override
  protected boolean useTakePhoto() {
    return true;
  }

2 ) 获取图片

takePhotoUtil.takePhoto(TakePhotoUtil.Select_type.PICK_BY_TAKE, new TakePhotoUtil.SimpleTakePhotoListener(){
      @Override
      public void takeSuccess(TResult result) {
        String s = result.getImage().getCompressPath();
        Bitmap bitmap = BitmapFactory.decodeFile(s);
        iv.setImageBitmap(bitmap);
      }
    });

takePhoto()的第一个参数是一个枚举类型的参数,分别为从相册获取和拍照获取,第二个参数为获取成功失败监听,有三个回调,由于有些回调不是必须的,所以对Listener做了一个适配,只需要回调想要的方法即可,获取成功之后就可以通过TResult封装的参数获取想要的图片以及图片地址。对于获取到的图片地址就可以做一些上传处理。

图片上传

可以借助okhttp3实现上传功能

MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);

 RequestBody requestBody = RequestBody.create(MediaType.parse(MULTIPART_FORM_DATA), file);

 MultipartBody.Part part = MultipartBody.Part.createFormData("dir", file.getName(), requestBody);

 builder.addPart(part);

 Request.Builder builder1 = new Request.Builder().url(url).post(builder.build());

 Request request = builder1.build();

 HttpUtils.client.newCall(request).enqueue(new Callback() {
   @Override
   public void onFailure(Call call, IOException e) {

   }

   @Override
   public void onResponse(Call call, Response response) throws IOException {
     if(response.isSuccessful()){
       final String s = response.body().string();
       ((Activity)context).runOnUiThread(new Runnable() {
         @Override
         public void run() {

         }
       });
     }
   }
 });

大致代码如上

最后

由于当时没有找到这个库,于是跑去问公司另一个做Android的,看了下他封装的代码,确实也是值得学习的,他的代码也是适配到了Android7.0,贴下它的代码,方便以后学习:

public class CameraUtil {
  private static final int REQUEST_CAPTURE_CAMERA = 1221;
  private static final int REQUEST_CROP = 1222;
  private static final int REQUEST_OPEN_ALBUM = 1223;
  private static final String TAG = "Camera";
  private static Uri mCacheUri;

  private CameraUtil() {
  }

  @RequiresPermission(allOf = {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA})
  public static void getImageFromCamera(Activity activity) {
    if (checkExternalStorageState(activity)) {
      activity.startActivityForResult(getImageFromCamera(activity.getApplicationContext()), REQUEST_CAPTURE_CAMERA);
    }
  }

  @RequiresPermission(allOf = {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA})
  @Deprecated
  public static void getImageFromCamera(Fragment fragment) {
    if (checkExternalStorageState(fragment.getContext())) {
      fragment.startActivityForResult(getImageFromCamera(fragment.getContext()), REQUEST_CAPTURE_CAMERA);
    }
  }

  private static Intent getImageFromCamera(Context context) {
    Intent getImageByCamera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    mCacheUri = getCachePhotoUri(context.getApplicationContext());
    getImageByCamera.putExtra(MediaStore.EXTRA_OUTPUT, mCacheUri);
    getImageByCamera.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
    grantUriPermission(context, getImageByCamera, mCacheUri);
    return getImageByCamera;
  }

  private static boolean checkExternalStorageState(Context context) {
    if (TextUtils.equals(Environment.getExternalStorageState(), Environment.MEDIA_MOUNTED)) {
      return true;
    }
    Toast.makeText(context.getApplicationContext(), "请确认已经插入SD卡", Toast.LENGTH_LONG).show();
    return false;
  }

  @SuppressWarnings("ResultOfMethodCallIgnored")
  public static File getCachePhotoFile() {
    File file = new File(Environment.getExternalStorageDirectory(), "/lenso/cache/CameraTakePhoto" + System.currentTimeMillis() + ".jpg");
    if (!file.getParentFile().exists()) file.getParentFile().mkdirs();
    return file;
  }

  private static Uri getCachePhotoUri(Context context) {
    return FileProvider.getUriForFile(context, getAuthority(context), getCachePhotoFile());
  }

  private static Uri getCachePhotoUri(Context context, File file) {
    return FileProvider.getUriForFile(context, getAuthority(context), file);
  }

  public static void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data, OnActivityResultListener listener) {
    onActivityResult(activity, null, requestCode, resultCode, data, listener);
  }

  /**
   * getCachePhotoFile().getParentFile().getAbsolutePath()
   * @param dir
   * @return
   */
  public static boolean deleteDir(File dir) {
    if (dir != null && dir.isDirectory()) {
      String[] children = dir.list();
      for (int i = 0; i < children.length; i++) {
        boolean success = deleteDir(new File(dir, children[i]));
        if (!success) {
          return false;
        }
      }
    }
    return dir.delete();
  }

  public static File saveBitmap(Bitmap bitmap) {
    File file = getCachePhotoFile();
    if (bitmap == null || bitmap.isRecycled()) return file;
    FileOutputStream outputStream = null;
    try {
      outputStream = new FileOutputStream(file);
      bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } finally {
      if (outputStream != null)
        try {
          outputStream.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      bitmap.recycle();
    }
    return file;
  }

  public static void copy(File file, File point) {
    if (!file.exists()) return;
    if (!point.getParentFile().exists()) point.getParentFile().mkdirs();
    BufferedInputStream inputStream = null;
    BufferedOutputStream outputStream = null;
    try {
      inputStream = new BufferedInputStream(new FileInputStream(file));
      outputStream = new BufferedOutputStream(new FileOutputStream(point));
      byte[] buff = new byte[1024 * 1024 * 2];
      int len;
      while ((len = inputStream.read(buff)) != -1) {
        outputStream.write(buff, 0, len);
        outputStream.flush();
      }
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      closeStream(inputStream);
      closeStream(outputStream);
    }
  }

  private static void closeStream(Closeable closeable) {
    if (closeable != null) try {
      closeable.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  public static void onActivityResult(Activity activity, CropOption crop, int requestCode, int resultCode, Intent data, OnActivityResultListener listener) {

    if (resultCode == Activity.RESULT_CANCELED) return;
    Uri uri;
    switch (requestCode) {
      case REQUEST_OPEN_ALBUM:
        uri = data.getData();
        if (uri != null) {
          mCacheUri = getCachePhotoUri(activity);
          copy(new File(getRealFilePath(activity, uri)), new File(getRealFilePath(activity, mCacheUri)));
        } else {
          Bitmap bitmap = data.getParcelableExtra("data");
          File file = saveBitmap(bitmap);
          mCacheUri = getCachePhotoUri(activity, file);
        }
      case REQUEST_CAPTURE_CAMERA:
        uri = mCacheUri;
        if (listener != null) {
          listener.requestCaptureCamera(getRealFilePath(activity, uri), null);
        }
        if (crop == null) return;
        crop.setSource(uri);
        Intent intent = crop.create();
        grantUriPermission(activity, intent, crop.getOutput());
        activity.startActivityForResult(intent, REQUEST_CROP);
        break;
      case REQUEST_CROP:
        if (listener != null && data != null)
        {
          listener.requestCrop(getRealFilePath(activity, mCacheUri), (Bitmap) data.getParcelableExtra("data"));
        }
        break;
    }
  }

  @RequiresPermission(allOf = {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE})
  public static void getImageFromAlbum(Activity activity) {
    Intent intent = new Intent(Intent.ACTION_PICK);
    intent.setType("image/*");//相片类型
    activity.startActivityForResult(intent, REQUEST_OPEN_ALBUM);
  }

  @RequiresPermission(allOf = {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE})
  @Deprecated
  public static void getImageFromAlbum(Fragment fragment) {
    Intent intent = new Intent(Intent.ACTION_PICK);
    intent.setType("image/*");//相片类型
    fragment.startActivityForResult(intent, REQUEST_OPEN_ALBUM);
  }

  public interface OnActivityResultListener {
    void requestCaptureCamera(String path, Bitmap bitmap);

    void requestCrop(String path, Bitmap bitmap);
  }

  /**
   * Try to return the absolute file path from the given Uri
   *
   * @param context context
   * @param uri   uri
   * @return the file path or null
   */
  public static String getRealFilePath(final Context context, final Uri uri) {
    if (null == uri) return null;
    String path = uri.toString();
    if (path.startsWith("content://" + getAuthority(context) + "/rc_external_path")) {
      return path.replace("content://" + getAuthority(context) + "/rc_external_path", Environment.getExternalStorageDirectory().getAbsolutePath());
    }
    final String scheme = uri.getScheme();
    String data = null;
    if (scheme == null)
      data = uri.getPath();
    else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
      data = uri.getPath();
    } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
      Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);
      if (null != cursor) {
        if (cursor.moveToFirst()) {
          int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
          if (index > -1) {
            data = cursor.getString(index);
          }
        }
        cursor.close();
      }
    }
    return data;
  }

  private static String getAuthority(Context context) {
    return context.getPackageName() + ".FileProvider";
  }

  public static class CropOption {
    private int aspectX=1;//x比例
    private int aspectY=1;//y比例
    private boolean returnData = false;//是返回bitmap,否返回uri
    private String outputFormat;//输出流保存格式JPG PNG ...
    private int outputX=200;//返回的bitmap宽
    private int outputY=200;//返回的bitmap高
    private Uri output;//输出流保存路径
    private Uri source;//需要截图的图片uri
    private boolean noFaceDetection = true;//是否关闭人脸识别功能
// get和set方法省略

    private Intent create() {
      if (source == null)
        throw new NullPointerException("没有设置图片uri");
      Intent intent = new Intent("com.android.camera.action.CROP");
      intent.setDataAndType(source, "image/*");
      intent.putExtra("crop", "true");
      if (aspectX > 0)
        intent.putExtra("aspectX", aspectX);
      if (aspectY > 0)
        intent.putExtra("aspectY", aspectY);
      if (outputX > 0)
        intent.putExtra("outputX", outputX);
      if (outputY > 0)
        intent.putExtra("outputY", outputY);
      intent.putExtra("return-data", returnData);
      if (!returnData) {
        output = output == null ? source : output;
        outputFormat = outputFormat == null ? Bitmap.CompressFormat.JPEG.toString() : outputFormat;
        intent.putExtra(MediaStore.EXTRA_OUTPUT, output);
        intent.putExtra("outputFormat", outputFormat);
        intent.setType("image/*");
        intent.putExtra("noFaceDetection", noFaceDetection);
      }
      return intent;
    }
  }

  private static void grantUriPermission(Context context, Intent intent, Uri uri) {
    List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
    for (ResolveInfo resolveInfo : resInfoList) {
      String packageName = resolveInfo.activityInfo.packageName;
      context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }
  }
}

//xml文件部分
<?xml version="1.0" encoding="utf-8"?>
<resources >
  <paths>
    <external-path path="" name="rc_external_path" />
  </paths>
</resources>
//清单文件注册部分
<provider
  android:name="android.support.v4.content.FileProvider"
  android:authorities="com.lenso.FileProvider"
  android:exported="false"
  android:grantUriPermissions="true">
  <meta-data
    android:name="android.support.FILE_PROVIDER_PATHS"
    android:resource="@xml/file_path" />
</provider>

也封装了从本地获取,以及拍照获取的相关功能,可以值得学习,毕竟不少坑。

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

时间: 2017-05-16

android bitmap compress(图片压缩)代码

android的照相功能随着手机硬件的发展,变得越来越强大,能够找出很高分辨率的图片.有些场景中,需要照相并且上传到服务,但是由于图片的大小太大,那么就上传就会很慢(在有些网络情况下),而且很耗流量,要想速度快,那么就需要减小图片的大小.减少图片的大小有两种方法,1. 照小图片: 2. 压缩大图片. 照相时获取小图片一般不太符合要求,因为,图片的清晰度会很差,但是这种情况有个好处就是应用速度会快些: 压缩图片,就是把大图片压缩小,降低图片的质量,在一定范围内,降低图片的大小,并且满足需求(图片仍

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

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

Android裁剪图片为圆形图片的实现原理与代码

以前在eoe论坛中找过裁剪图片为圆形图片的方法,但是效果都不是很理想,这几天因为公司业务的要求,需要对头像进行裁剪以圆形的方式显示,这个方法是根据传入的图片的高度(height)和宽度(width)决定的,如果是 width <= height时,则会裁剪高度,裁剪的区域是宽度不变高度从顶部到宽度width的长度:如果 width > height,则会裁剪宽度,裁剪的区域是高度不变,宽度是取的图片宽度的中心区域,不过不同的业务需求,对裁剪图片要求不一样,可以根据业务的需求来调整裁剪的区域.

Android 调用系统相机拍摄获取照片的两种方法实现实例

Android 调用系统相机拍摄获取照片的两种方法实现实例 在我们Android开发中经常需要做这个一个功能,调用系统相机拍照,然后获取拍摄的照片.下面是我总结的两种方法获取拍摄之后的照片,一种是通过Bundle来获取压缩过的照片,一种是通过SD卡获取的原图. 下面是演示代码: 布局文件: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http:

android图片压缩的3种方法实例

android 图片压缩方法: 第一:质量压缩法: 复制代码 代码如下: private Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos = new ByteArrayOutputStream();        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中        int op

解决Android从相册中获取图片出错图片却无法裁剪问题的方法

在学习获取相册中图片进行裁剪的时候遇到了比较大的问题,在纠结了近半天才真的解决,下面分享一下学习经验. 问题: 选择了相册中的图片之后要进入图片裁剪的时候出错,(华为)手机提示"此图片无法获取",经百度后,明白是版本不同导致的URI的问题的问题,原文如下: 4.3或以下,选了图片之后,根据Uri来做处理,很多帖子都有了,我就不详细说了.主要是4.4,如果使用上面pick的原生方法来选图,返回的uri还是正常的,但如果用ACTION_GET_CONTENT的方法,返回的uri跟4.3是完

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使用phonegap从相册里面获取照片(代码分享)

话不多说,请看代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Take a Photo</title> <script type="text/javascript" charset="UTF-8" src="cordova.js"></script> &

Android实现从本地图库/相机拍照后裁剪图片并设置头像

玩qq或者是微信的盆友都知道,这些聊天工具里都要设置头像,一般情况下大家的解决办法是从本地图库选择图片或是从相机拍照,然后根据自己的喜爱截取图片.上述过程已经实现好了,最后一步我加上了把截取好的图片在保存到本地的操作,来保存头像.为了大家需要,下面我们小编把完整的代码贴出来供大家参考. 先给大家展示效果图: 代码部分: 布局代码(其实就是两个按钮和一个ImageView来显示头像) <LinearLayout xmlns:android="http://schemas.android.co

android获取照片的快照 思路及实现方法

当我们在做相册.上传相关的应用的时候需要获取图片的快照,这时候就需要获取图片的快照. android中专门有一个BitmapFactory类可以来处理这类需求. 实现的步骤如下: 1.首先解析出图片文件(注意在这里为了节约内存将inJustDecodeBounds设为true,这样的话解析的图片的话只有图片的尺寸大小信息) 复制代码 代码如下: BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();bmpFac

Android获取手机系统版本等信息的方法

本文实例讲述了Android获取手机系统版本等信息的方法.分享给大家供大家参考.具体如下: String phoneInfo = "Product: " + android.os.Build.PRODUCT; phoneInfo += ", CPU_ABI: " + android.os.Build.CPU_ABI; phoneInfo += ", TAGS: " + android.os.Build.TAGS; phoneInfo += &qu

Android获取本机各种类型文件的方法

介绍 本篇介绍Android获取本机各种类型文件的方法,已经封装成工具类,末尾有源码下载地址. 提示 获取音乐.视频.图片.文档等文件是需要有读取SD卡的权限的,如果是6.0以下的系统,则直接在清单文件中声明SD卡读取权限即可:如果是6.0或以上,则需要动态申请权限. FileManager的使用 FileManager是封装好的用于获取本机各类文件的工具类,使用方式如:FileManager.getInstance(Context context).getMusics(),使用的是单例模式创建

android获取监听SD Card状态的方法

本文实例讲述了android获取监听SD Card状态的方法.分享给大家供大家参考.具体分析如下: 1. 注册StorageEventListener来监听SD卡状态即onStorageStateChanged()方法,当sd卡状态改变时,调用该方法. 复制代码 代码如下: public void onStorageStateChanged(String path,String oldState,String newState){ if (newState.equals(Environment.

实现Android 获取cache缓存的目录路径的方法

实现Android 获取cache缓存的目录路径的方法 Android开发中,有时需要知道cache缓存的路径.我写了一个静态类,供大家能参考 public class CommonUtil { /** * 获取cache路径 * * @param context * @return */ public static String getDiskCachePath(Context context) { if (Environment.MEDIA_MOUNTED.equals(Environmen

Android获取手机本机号码的实现方法

Android获取手机本机号码的实现方法 反射TelephoneManager 获取本机号码,注意一下提供的接口有的SIM卡没写是获取不到的,该接口只适配Android5.0以上版本 public String getMsisdn(int slotId) { return getLine1NumberForSubscriber(getSubIdForSlotId(slotId)); } 权限 <uses-permission android:name="android.permission

Android获取栈顶的应用包名方法

有时候我们需要判断栈顶的应用是否是我们的应用,于是获取栈顶的应用包名的需求就出现了. 在android5.0之前,系统提供了一套API可以实现这个功能. ActivityManager manager = (ActivityManager) getApplicationContext().getSystemService(ACTIVITY_SERVICE); String currentClassName = manager.getRunningTasks(1).get(0).topActivi

Android获取系统储存以及内存信息的方法(二)

Android获取储存信息以及内存信息可以用adb命令查看. adb查看系统内存信息以及储存信息: 命令:adb shell cat /proc/meminfo 代码: private static final String FILENAME_PROC_MEMINFO = "/proc/meminfo"; /** * 获取手机内存总大小 * @return */ public static String getTotalMemorySize() { try { FileReader f

Android 获取内外SD卡路径几种方法总结

Android 获取SD卡路径: 外置sd卡路径,也许很多同学在平时的工作中并不会用到,因为现在很多机型都不支持外置sd卡(这也是Google目标),所以并不用考虑外置sd卡的路径问题.除了开发文件管理类的应用之外,其他应用使用 Enviroment 这个类中的一些静态方法就能满足需要.但也有一些特殊需求需要用到外置sd卡路径,那怎么才能准确获得外置sd卡的路径呢? 方法一 //内置sd卡路径 String sdcardPath = System.getenv("EXTERNAL_STORAGE

android 获取视频第一帧作为缩略图的方法

今天,简单讲讲android里如何获取一个视频文件的第一帧作为缩略图显示在界面上. 之前,我说个最近需要从服务器下载视频文件,但是下载后肯定需要显示视频的缩略图在界面上给用户看,于是想到显示视频的第一帧作为缩略图.但是我不知道具体怎么写,于是在网上查找资料,最终是解决了问题.这里记录一下. 一.使用MediaMetadataRetriever获取视频的第一帧作为缩略图 /** * 获取视频文件截图 * * @param path 视频文件的路径 * @return Bitmap 返回获取的Bit