《Android三方库--TakePhoto》

写在前面

  刚开始写安卓的时候,总是希望自己能够亲自实现某个功能,认为只有都是自己写出来的才会学到东西。虽然
有学长跟自己说要多利用Github,但是我却完全没有Get到学长的意思,以为Github只是用来看别人的代码,学习
某个解决方案的。其实不然,Github很重要的一个用处就是上面有许多很优美的封装过的三方库,只需要简单的几
行代码就可以实现很好的效果。一开始的时候也完全没必要纠结于自己是不是完全能看懂某个三方库的代码,大家
都是从会用开始,然后到看懂,再到自己“造轮子”的。
  经过了接近一年的学习,也不可避免的接触了许多优秀的三方库,以后将逐步分享给大家,今天要跟大家分享
是TakePhoto.

正菜

名称:TakePhoto
TakePhoto Github地址:https://github.com/crazycodeboy/TakePhoto
应用实例 Github地址:https://github.com/ZhangRui111/BlogLibsTakePhoto

应用场景

但凡一个最终会上线的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的使用

  1. 引入三方库依赖(安装)

相信有许多像我一样刚刚上手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)

  • 继承TakePhotoActivityTakePhotoFragmentActivityTakePhotoFragment
    三者之一。
  • 通过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<TImage> images) {
        //图片压缩成功
    }
    @Override
    public void onCompressFailed(ArrayList<TImage> 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)

实现效果截图




原创文章,转载请注明出处:http://www.jianshu.com/p/9528a0d29f29

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容