欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android第三方库TakePhoto应用场景及实现教程

程序员文章站 2022-03-31 10:36:39
应用场景 但凡一个最终会上线的App,基本都会有上传用户头像的模块。这里便会涉及到从相册中选取用户头像、通过拍照获取头像、裁剪、压缩等功能。网上有许多博客都写到了这一功能的代码实...

应用场景

但凡一个最终会上线的App,基本都会有上传用户头像的模块。这里便会涉及到从相册中选取用户头像、通过拍照获取头像、裁剪、压缩等功能。网上有许多博客都写到了这一功能的代码实现,有些的确有效,有些却无法正确返回结果。   自己实现这一模块主要由以下难点:   ①. 返回的照片过大容易造成 OOM。   ②. 安卓4.4系统作为分水岭,4.4以上的系统返回的图片Uri是封装过的,并不是图片真实的Uri,例如:

Android4.4以前获取的uri的字符串是“content://media/external/image/media”格式的,而4.4以后变成"file:///sdcard/mysong.mp3"格式

③. Android系统的碎片化

由于Android系统的开放性带来的碎片化问题几乎是从始至终会贯穿于开发过程的,而且一直没有很好的解决方案。尤其是国内的手机厂商对于ROM的深度定制更是给程序员带来了噩梦般的苦恼。经常是在一部手机上完全没有问题的代码,换一部手机,即使是Android版本相同,手机厂商不同也可能导致代码的崩溃,唉,说多了都是泪啊, -_-|||

④. ...

我也是在开发的过程中饱尝了“碎片化”、OOM等的心酸后,才尝试了三方库,不得不说,Github上优秀的三方库大都能够很好的处理碎片化问题,毕竟只是针对某一个功能点进行适配性维护的代价还是可以承受的。

TakePhoto简介

TakePhoto是一款用于在Android设备上获取照片(拍照或从相册、文件中选择)、裁剪图片、压缩图片的开源工具库,目前最新版本4.0.3。支持通过相机拍照获取图片

支持从相册选择图片

支持从文件选择图片

支持批量图片选取

支持图片压缩以及批量图片压缩

支持图片裁切以及批量图片裁切

支持照片旋转角度自动纠正

支持自动权限管理(无需关心SD卡及摄像头权限等问题)

支持对裁剪及压缩参数个性化配置

提供自带裁剪工具(可选)

支持智能选取及裁剪异常处理

支持因拍照Activity被回收后的自动恢复

支持Android7.0

+支持多种压缩工具

+支持多种图片选择工具

哈哈,功能还是很强大的,而且,更重要的是,使用也很简单,真是Android程序狗的福音!话不多说,基础用法先来一遍。

TakePhoto的使用

引入三方库依赖(安装)

相信有许多像我一样刚刚上手Android程序开发编程菜鸟并不是不想用三方库,而是苦于在没有人指导的情况下对于如何使用一个三方库不知所云。下面我就根据我走过的弯路介绍下引入三方库依赖的方法,老司机发车咯,新手刷卡上车,其他老司机自动跳过即可,滴滴滴——

以AndroidStudio为例,安装三方库一般有三种方案:

build.gradle文件中添加一行或者几行说明,一般是在dependencies{...}中添加。这种方案最为常见,也最为方便,如下图所示

compile 'com.jph.takephoto:takephoto_library:4.0.3'即为TakePhoto的安装。之后只需要重新更新下build.gradle文件,等待工程下载相关依赖即可大功告成了!

更新方式有两个:

①:点击图中红圈圈中按钮

②:一旦build.gradle文件发生改动后,AS都会主动提示更新,点击sync now 即可

这里要注意,一个Android工程里会有两个build.gradle文件,查看方式:右上角切换项目结构组织方式,从Android切换为Project

切换后

使用Android Studio新建一个工程后,默认会生成两个build.gralde文件,一个位于工程根目录,一个位于app目录下。一般的三方库只需要添加到app目录下即可(即图中选中的文件),少数三方库也需要改动工程根目录下的build.gradle。

下载三方库的.jar文件,添加到Android工程的libs目录中,然后刷新build.gradle文件,如上图所示,gson-02.2.2.jar还有Volley.jar都是这样安装的Maven:咳咳,不做介绍...(什么鬼,菜菜的我不知所云 (°ー°〃))

2.** 使用说明(建议参照Github应用实例,注解详细哦)**

(1) 获取TakePhoto实例

TakePhoto在作用上类似于FragmentManager,无论是拍照、裁剪、从相册中选取、压缩都需要调用TakePhoto的方法,例如:takePhoto.onPickFromGallery();。所以,获取TakePhoto是第一步,有两种方式,一般来说,第一种方式更加简洁,如果通过继承的方式无法满足实际项目的使用,可以通过方式二。。

 方式一:通过继承的方式(参照MainActivity.java)

继承TakePhotoActivity、TakePhotoFragmentActivity、TakePhotoFragment

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

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

方式二:通过组装的方式(参照AnotherActivity)

可参照:TakePhotoActivity,以下为主要步骤:

实现TakePhoto.TakeResultListener,InvokeListener接口。

public class AnotherActivity extends AppCompatActivity implements 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);
    }

4.重写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;
    }

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

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

(2) 调用TakePhoto相关方法,并通过以下方法获取结果

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

举个栗子:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ···
        takeFromCameraBtn = (Button) findViewById(R.id.take_from_camera);
        takeFromCameraBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                imageUri = getImageCropUri();
                //拍照并裁剪
                takePhoto.onPickFromCaptureWithCrop(imageUri, cropOptions);
                //仅仅拍照不裁剪
                //takePhoto.onPickFromCapture(imageUri);
            }
        });
        ···
    }
        ···

    @Override
    public void takeSuccess(TResult result) {
        super.takeSuccess(result);
        String iconPath = result.getImage().getOriginalPath();
        //Toast显示图片路径
        Toast.makeText(this, "imagePath:" + iconPath, Toast.LENGTH_SHORT).show();
        //Google Glide库 用于加载图片资源
        Glide.with(this).load(iconPath).into(imageView);
    }

    @Override
    public void takeFail(TResult result, String msg) {
        super.takeFail(result, msg);
        Toast.makeText(MainActivity.this, "Error:" + msg, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void takeCancel() {
        super.takeCancel();
    }

TakePhoto主要包含以下几个方法

获取图片(调用示例: takephoto.onPickFromDocuments();)

/**
 * 从文件中获取图片(不裁剪)
 */
void onPickFromDocuments();
/**
 * 从相册中获取图片(不裁剪)
 */
void onPickFromGallery();
/**
 * 从相机获取图片(不裁剪)
 * @param outPutUri 图片保存的路径
 */
void onPickFromCapture(Uri outPutUri);
/**
 * 图片多选
 * @param limit 最多选择图片张数的限制
 **/
void onPickMultiple(int limit);

裁剪图片(调用示例: takephoto.onPickFromCaptureWithCrop(imageUri, cropOptions );)

/**
 * 从相机获取图片并裁剪
 * @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);

对指定图片进行裁剪(调用示例: takephoto.onCrop(imageUri, outPutUri, cropOptions);)

/**
 * 裁剪图片
 * @param imageUri 要裁剪的图片
 * @param outPutUri 图片裁剪之后保存的路径
 * @param options 裁剪配置
 */
void onCrop(Uri imageUri, Uri outPutUri, CropOptions options)throws TException;
/**
 * 裁剪多张图片
 * @param multipleCrop 要裁切的图片的路径以及输出路径
 * @param options 裁剪配置
 */
void onCrop(MultipleCrop multipleCrop, CropOptions options)throws TException;

压缩图片

 /**
  * 启用图片压缩
  * @param config 压缩图片配置
  * @param showCompressDialog 压缩时是否显示进度对话框
  * @return
  */
 void onEnableCompress(CompressConfig config,boolean showCompressDialog);
 /**
  * 对指定图片进行压缩
  */
new CompressImageImpl(compressConfig,result.getImages(), new CompressImage.CompressListener() {
    @Override
    public void onCompressSuccess(ArrayList images) {
        //图片压缩成功
    }
    @Override
    public void onCompressFailed(ArrayList images, String msg) {
        //图片压缩失败
    }
}).compress();

(3) TakePhoto支持裁剪、压缩,支持设置裁剪压缩参数

裁剪

图片的裁剪比例setAspectX(1); setAspectY(1)

是否使用TakePhoto自带的裁剪工具进行裁剪setWithOwnCrop(false)压缩

图片最大尺寸setMaxSize(50*1024)

最大输出大小setMaxPixel(800)还是举个栗子

    private CropOptions cropOptions;  //裁剪参数
    private CompressConfig compressConfig;  //压缩参数
       ···
//设置裁剪参数
 cropOptions = new CropOptions.Builder().setAspectX(1).setAspectY(1).setWithOwnCrop(false).create();
//设置压缩参数
 compressConfig=new CompressConfig.Builder().setMaxSize(50*1024).setMaxPixel(800).create();
 takePhoto.onEnableCompress(compressConfig,true);  //设置为需要压缩
      ...

(4)TakePhoto支持自定义UI,参照Github [README.md](https://github.com/crazycodeboy/TakePhoto)