Full Code of crazycodeboy/TakePhoto for AI

master 31a222705b52 cached
74 files
195.3 KB
50.8k tokens
339 symbols
1 requests
Download .txt
Showing preview only (216K chars total). Download the full file or copy to clipboard to get everything.
Repository: crazycodeboy/TakePhoto
Branch: master
Commit: 31a222705b52
Files: 74
Total size: 195.3 KB

Directory structure:
gitextract_b4074lig/

├── .gitignore
├── LICENSE
├── README -V1.0+.md
├── README.2+.md
├── README.md
├── build.gradle
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
├── simple/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── org/
│       │           └── devio/
│       │               └── simple/
│       │                   └── ApplicationTest.java
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── org/
│           │       └── devio/
│           │           └── simple/
│           │               ├── CustomHelper.java
│           │               ├── MainActivity.java
│           │               ├── ResultActivity.java
│           │               ├── SimpleActivity.java
│           │               ├── SimpleFragment.java
│           │               └── SimpleFragmentActivity.java
│           └── res/
│               ├── layout/
│               │   ├── activity_main_layout.xml
│               │   ├── activity_result_layout.xml
│               │   ├── common_layout.xml
│               │   ├── image_show.xml
│               │   └── simple_fragment_layout.xml
│               ├── menu/
│               │   └── menu_main.xml
│               ├── values/
│               │   ├── dimens.xml
│               │   ├── strings.xml
│               │   └── styles.xml
│               └── values-w820dp/
│                   └── dimens.xml
└── takephoto_library/
    ├── .gitignore
    ├── build.gradle
    ├── proguard-rules.pro
    └── src/
        ├── androidTest/
        │   └── java/
        │       └── org/
        │           └── devio/
        │               └── takephoto/
        │                   └── ApplicationTest.java
        └── main/
            ├── AndroidManifest.xml
            ├── java/
            │   └── org/
            │       └── devio/
            │           └── takephoto/
            │               ├── app/
            │               │   ├── TakePhoto.java
            │               │   ├── TakePhotoActivity.java
            │               │   ├── TakePhotoFragment.java
            │               │   ├── TakePhotoFragmentActivity.java
            │               │   └── TakePhotoImpl.java
            │               ├── compress/
            │               │   ├── CompressConfig.java
            │               │   ├── CompressImage.java
            │               │   ├── CompressImageImpl.java
            │               │   ├── CompressImageUtil.java
            │               │   └── CompressWithLuBan.java
            │               ├── model/
            │               │   ├── CropOptions.java
            │               │   ├── InvokeParam.java
            │               │   ├── LubanOptions.java
            │               │   ├── MultipleCrop.java
            │               │   ├── TContextWrap.java
            │               │   ├── TException.java
            │               │   ├── TExceptionType.java
            │               │   ├── TImage.java
            │               │   ├── TIntentWap.java
            │               │   ├── TResult.java
            │               │   └── TakePhotoOptions.java
            │               ├── permission/
            │               │   ├── InvokeListener.java
            │               │   ├── PermissionManager.java
            │               │   └── TakePhotoInvocationHandler.java
            │               └── uitl/
            │                   ├── ImageRotateUtil.java
            │                   ├── IntentUtils.java
            │                   ├── TConstant.java
            │                   ├── TFileUtils.java
            │                   ├── TImageFiles.java
            │                   ├── TUriParse.java
            │                   └── TUtils.java
            └── res/
                ├── values/
                │   ├── dimens.xml
                │   └── strings.xml
                ├── values-en/
                │   └── strings.xml
                ├── values-w820dp/
                │   └── dimens.xml
                └── xml/
                    └── file_paths.xml

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Created by .ignore support plugin (hsz.mobi)
### Android template
# Built application files
#*.apk
*.ap_

# Files for the Dalvik VM
*.dex

# Java class files
*.class

# Generated files
bin/
gen/

# Gradle files
.gradle/
build/
/*/build/

# Local configuration file (sdk path, etc)
local.properties

# Proguard folder generated by Eclipse
proguard/

# Log Files
*.log


### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion

*.iml

## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:

# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries

# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml

# Gradle:
# .idea/gradle.xml
# .idea/libraries

# Mongo Explorer plugin:
# .idea/mongoSettings.xml

## File-based project format:
*.ipr
*.iws

## Plugin-specific files:

# IntelliJ
/out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties


### Gradle template
.gradle

# Ignore Gradle GUI config
gradle-app.setting

# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar

###
android-crop




================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "{}"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright {yyyy} {name of copyright owner}

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.



================================================
FILE: README -V1.0+.md
================================================
## [TakePhoto](https://github.com/crazycodeboy/TakePhoto) 简介    
`TakePhoto`是一款用于Android设备获取照片(拍照或从相册、文件中选择)、裁剪图片、压缩图片的开源工具库,目前最新版本**[2.0.0已发布,请使用最新版](https://github.com/crazycodeboy/TakePhoto)**。   

**V1.0+**  

- 支持以拍照的方式获取照片 
- 支持从相册选择照片  
- 支持对照片进行裁切
- 支持对照片进行压缩
- 支持对裁切及压缩参数自定义  
- 支持因拍照Activity被回收后的自动恢复   

GitHub地址: [https://github.com/crazycodeboy/TakePhoto](https://github.com/crazycodeboy/TakePhoto)
## 如何使用   
### 使用TakePhoto有以下两种方式:
**方式一:通过继承的方式**  
1. 继承TakePhotoActivity、TakePhotoFragmentActivity、TakePhotoFragment三者之一。  
2. 通过`getTakePhoto()`获取TakePhoto实例进行相关操作。  
3. 重写以下方法获取结果        
```java
void takeSuccess(String imagePath);  
void takeFail(String msg);
void takeCancel();
```  
此方式使用简单,满足的大部分的使用需求,具体使用详见simple。如果通过继承的方式无法满足实际项目的使用,可以通过下面介绍的方式。  

**方式二:通过组装的方式**  
1. 获取TakePhoto实例`TakePhoto takePhoto=new TakePhotoImpl(getActivity(),this);`  
2. 在 `onCreate`,`onActivityResult`,`onSaveInstanceState`方法中调用TakePhoto对用的方法。  
3. 调用TakePhoto实例进行相关操作。  
4. 在`TakeResultListener`相关方法中获取结果。      
### 关于压缩照片 
你可以选择是否对照片进行压缩处理。  
```java
 /**
  * 启用照片压缩
  * @param config 压缩照片配置
  * @param showCompressDialog 压缩时是否显示进度对话框
  * @return 
  */
 TakePhoto onEnableCompress(CompressConfig config,boolean showCompressDialog);
```
eg:  
`getTakePhoto().onEnableCompress(new CompressConfig.Builder().setMaxSize(50*1024).setMaxPixel(800).create(),true).onPicSelectCrop(imageUri);`  
如果你启用了照片压缩,TakePhoto会使用`CompressImage`对照片进行压缩处理,CompressImage目前支持对照片的尺寸以及照片的质量进行压缩。默认情况下,CompressImage开启了尺寸与质量双重压缩,
你可以通过CompressConfig.Builder对照片压缩后的尺寸以及质量进行相关设置。如果你想改变压缩的方式可以通过CompressConfig.Builder进行相关设置。  
## 关于兼容性问题  
TakePhoto是基于Android官方标准API编写的,适配了目前市场上主流的Rom。如果你在使用过程中发现了适配问题,可以提交Issues。   
1. 为适配部分手机拍照时会回收Activity,TakePhoto在`onSaveInstanceState`与 `onCreate`做了相应的恢复处理。  
2. 为适配部分手机拍照或从相册选择照片时屏幕方向会发生转变,从而导致拍照失败的问题,可以在AndroidManifest.xml中对使用了TakePhoto的Activity添加android:configChanges="orientation|keyboardHidden|screenSize"配置。  
eg:  
```
<activity
    android:name=".MainActivity"
    android:screenOrientation="portrait"
    android:configChanges="orientation|keyboardHidden|screenSize"
    android:label="@string/app_name" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
```

## 在项目中使用    
为方便大家使用,现已将TakePhoto发布到JCenter(如果你对如何将项目发布到JCenter感兴趣可以参考:《[教你轻松将Android library 发布到JCenter](http://blog.csdn.net/fengyuzhengfan/article/details/51407009))》  
Gradle:  
```groovy 
    compile 'com.jph.takephoto:takephoto_library:1.0.1'
```

Maven:  
```groovy 
<dependency>
  <groupId>com.jph.takephoto</groupId>
  <artifactId>takephoto_library</artifactId>
  <version>1.0.1</version>
  <type>pom</type>
</dependency>
```  
## 最后  
如果你对[TakePhoto](https://github.com/crazycodeboy/TakePhoto)有更好的建议或想改造它,欢迎大家Fork and Pull requests。  


================================================
FILE: README.2+.md
================================================
## [TakePhoto](https://github.com/crazycodeboy/TakePhoto) 简介  
`TakePhoto`是一款用于在Android设备上获取照片(拍照或从相册、文件中选择)、裁剪图片、压缩图片的开源工具库,目前最新版本[2.0.4](https://github.com/crazycodeboy/TakePhoto/)。  
2.0以下版本及API说明,详见[TakePhoto1.0+](https://github.com/crazycodeboy/TakePhoto/blob/master/README%20-V1.0+.md)。  

**V2.0**    

- 支持通过相机拍照获取图片
- 支持从相册选择图片
- 支持从文件选择图片  
- 支持对图片进行压缩
- 支持对图片进行裁剪
- 支持对裁剪及压缩参数个性化配置  
- 提供自带裁剪工具(可选)  
- 支持智能选取及裁剪异常处理
- 支持因拍照Activity被回收后的自动恢复   

GitHub地址: [https://github.com/crazycodeboy/TakePhoto](https://github.com/crazycodeboy/TakePhoto)

## 预览图  

运行效果图:    

![运行效果图](https://raw.githubusercontent.com/crazycodeboy/TakePhoto/master/Screenshots/%E9%A2%84%E8%A7%88%E5%9B%BE.jpg)


## 如何使用   

### 使用TakePhoto有以下两种方式:
**方式一:通过继承的方式**  
1. 继承`TakePhotoActivity`、`TakePhotoFragmentActivity`、`TakePhotoFragment`三者之一。  
2. 通过`getTakePhoto()`获取`TakePhoto`实例进行相关操作。  
3. 重写以下方法获取结果        

```java
void takeSuccess(String imagePath);  
void takeFail(String msg);
void takeCancel();
```  
此方式使用简单,满足的大部分的使用需求,具体使用详见simple。如果通过继承的方式无法满足实际项目的使用,可以通过下面介绍的方式。  

**方式二:通过组装的方式**  
1. 获取TakePhoto实例`TakePhoto takePhoto=new TakePhotoImpl(getActivity(),this);`  
2. 在 `onCreate`,`onActivityResult`,`onSaveInstanceState`方法中调用TakePhoto对用的方法。  
3. 调用TakePhoto实例进行相关操作。  
4. 在`TakeResultListener`相关方法中获取结果。      

### 获取图片
TakePhoto提供拍照,从相册选择,从文件中选择三种方式获取图片。    

#### API:

```java
/**
 * 从文件中获取图片(不裁剪)
 */
void onPickFromDocuments();
/**
 * 从相册中获取图片(不裁剪)
 */
void onPickFromGallery();
/**
 * 从相机获取图片(不裁剪)
 * @param outPutUri 图片保存的路径
 */
void onPickFromCapture(Uri outPutUri);
```
以上三种方式均提供对应的裁剪API,详见:[裁剪图片](https://github.com/crazycodeboy/TakePhoto#裁剪图片)。    
**注:**  
由于不同Android Rom厂商对系统有不同程度的定制,有可能导致某种选择图片的方式不支持,所以为了提高`TakePhoto`的兼容性,当某种选的图片的方式不支持时,`TakePhoto`会自动切换成使用另一种选择图片的方式进行图片选择。      

### 裁剪图片  

#### API  
`TakePhoto`支持对图片进行裁剪,无论是拍照的照片,还是从相册、文件中选择的图片。你只需要调用`TakePhoto`的相应方法即可:  

```java
/**
 * 从相机获取图片并裁剪
 * @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);
```   
#### 对指定图片进行裁剪     
另外,TakePhoto也支持你对指定图片进行裁剪:     

```java
/**
 * 裁剪图片
 * @param imageUri 要裁剪的图片
 * @param outPutUri 图片裁剪之后保存的路径
 * @param options 裁剪配置
 */
void onCrop(Uri imageUri, Uri outPutUri, CropOptions options)throws TException;
```

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

**Usage:**  

```java
 CropOptions cropOptions=new CropOptions.Builder().setAspectX(1).setAspectY(1).setWithOwnCrop(true).create();  
 getTakePhoto().onPickFromDocumentsWithCrop(imageUri,cropOptions);  
 //或  
 getTakePhoto().onCrop(imageUri,outPutUri,cropOptions);  

```

**注:**  
由于不同Android Rom厂商对系统有不同程度的定制,有可能系统中没有自带或第三方的裁剪工具,所以为了提高`TakePhoto`的兼容性,当系统中没有自带或第三方裁剪工具时,`TakePhoto`会自动切换到使用`TakePhoto`自带的裁剪工具进行裁剪。  


### 压缩图片
你可以选择是否对图片进行压缩处理,你只需要告诉它你是否要启用压缩功能以及`CompressConfig`即可。  

#### API
```java
 /**
  * 启用图片压缩
  * @param config 压缩图片配置
  * @param showCompressDialog 压缩时是否显示进度对话框
  * @return
  */
 TakePhoto onEnableCompress(CompressConfig config,boolean showCompressDialog);
```

**Usage:**  

```java
getTakePhoto().onEnableCompress(compressConfig,true).onPickFromGalleryWithCrop(imageUri,cropOptions);
```  
如果你启用了图片压缩,`TakePhoto`会使用`CompressImage`对图片进行压缩处理,`CompressImage`目前支持对图片的尺寸以及图片的质量进行压缩。默认情况下,`CompressImage`开启了尺寸与质量双重压缩。  

#### 对指定图片进行压缩  
另外,你也可以对指定图片进行压缩:    
**Usage:**  

```java
new CompressImageImpl(compressConfig).compress(picturePath, new CompressImage.CompressListener() {
    @Override
    public void onCompressSuccess(String imgPath) {//图片压缩成功

    }
    @Override
    public void onCompressFailed(String imagePath,String msg) {//图片压缩失败

    }
});
```

#### CompressConfig  
`CompressConfig`是用于图片压缩的配置类,你可以通过`CompressConfig.Builder`对图片压缩后的尺寸以及质量进行相关设置。如果你想改变压缩的方式可以通过`CompressConfig.Builder`进行相关设置。     
**Usage:**   

```java
CompressConfig compressConfig=new CompressConfig.Builder().setMaxSize(50*1024).setMaxPixel(800).create();
getTakePhoto().onEnableCompress(compressConfig,true).onPickFromGallery();
```


## 兼容性

### TakePhoto在深度兼容性方面的测试    
![兼容性测试报告](https://raw.githubusercontent.com/crazycodeboy/TakePhoto/master/Screenshots/%E5%85%BC%E5%AE%B9%E6%80%A7%E6%B5%8B%E8%AF%95.jpg)

### 获取更高的兼容性    
`TakePhot`o是基于Android官方标准API编写的,适配了目前市场上主流的Rom。如果你在使用过程中发现了适配问题,可以[提交Issues](https://github.com/crazycodeboy/TakePhoto/issues)。   
1. 为适配部分手机拍照时会回收`Activity`,`TakePhoto`在`onSaveInstanceState`与 `onCreate`做了相应的恢复处理。  
2. 为适配部分手机拍照或从相册选择图片时屏幕方向会发生转变,从而导致拍照失败的问题,可以在AndroidManifest.xml中对使用了`TakePhoto`的`Activity`添加android:configChanges="orientation|keyboardHidden|screenSize"配置。  
eg:  

```
<activity
    android:name=".MainActivity"
    android:screenOrientation="portrait"
    android:configChanges="orientation|keyboardHidden|screenSize"
    android:label="@string/app_name" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
```

## 在项目中使用    
为方便大家使用,现已将TakePhoto V2.0.4发布到JCenter(如果你对如何将项目发布到JCenter感兴趣可以参考:《[教你轻松将Android library 发布到JCenter](http://blog.csdn.net/fengyuzhengfan/article/details/51407009))》  
Gradle:  

```groovy
    compile 'com.jph.takephoto:takephoto_library:2.0.4'
```

Maven:  

```groovy
<dependency>
  <groupId>com.jph.takephoto</groupId>
  <artifactId>takephoto_library</artifactId>
  <version>2.0.4</version>
  <type>pom</type>
</dependency>
```  

## 最后  
如果你对[TakePhoto](https://github.com/crazycodeboy/TakePhoto)有更好的建议或想改造它,欢迎大家[Fork and Pull requests](https://github.com/crazycodeboy/TakePhoto)。  


================================================
FILE: README.md
================================================
## [TakePhoto](https://github.com/crazycodeboy/TakePhoto) 简介

[![PRs Welcome](https://img.shields.io/badge/PRs-Welcome-brightgreen.svg)](https://github.com/crazycodeboy/TakePhoto/pulls)
[![Download](https://api.bintray.com/packages/crazycodeboy/maven/TakePhoto/images/download.svg) ](https://bintray.com/crazycodeboy/maven/TakePhoto/_latestVersion)
[![GitHub release](https://img.shields.io/github/release/crazycodeboy/TakePhoto.svg?maxAge=2592000?style=flat-square)](https://github.com/crazycodeboy/TakePhoto/releases)
[![License Apache2.0](http://img.shields.io/badge/license-Apache2.0-brightgreen.svg?style=flat)](https://raw.githubusercontent.com/crazycodeboy/TakePhoto/master/LICENSE)



`TakePhoto`是一款用于在Android设备上获取照片(拍照或从相册、文件中选择)、裁剪图片、压缩图片的开源工具库,目前最新版本[4.1.0](https://github.com/crazycodeboy/TakePhoto/)。
3.0以下版本及API说明,详见[TakePhoto2.0+](https://github.com/crazycodeboy/TakePhoto/blob/master/README.2+.md)。  

>TakePhoto交流平台:QQ群:556387607(群1,未满)

**V4.0**

- 支持通过相机拍照获取图片
- 支持从相册选择图片
- 支持从文件选择图片  
- 支持批量图片选取
- 支持图片压缩以及批量图片压缩
- 支持图片裁切以及批量图片裁切
- 支持照片旋转角度自动纠正
- 支持自动权限管理(无需关心SD卡及摄像头权限等问题)
- 支持对裁剪及压缩参数个性化配置  
- 提供自带裁剪工具(可选)  
- 支持智能选取及裁剪异常处理
- 支持因拍照Activity被回收后的自动恢复   
- 支持Android8.1
- +支持多种压缩工具
- +支持多种图片选择工具

GitHub地址: [https://github.com/crazycodeboy/TakePhoto](https://github.com/crazycodeboy/TakePhoto)
## 目录

- [安装说明](#安装说明)
- [演示](#演示)
- [使用说明](#使用说明)
- [自定义UI](#自定义ui)
- [API](#api)
- [兼容性](#兼容性)
- [贡献](#贡献)
- [更新说明](#更新说明)
- [最后](#混淆)

## 安装说明  
**Gradle:**  

```groovy
    compile 'com.jph.takephoto:takephoto_library:4.1.0'
```

**Maven:**  

```groovy
<dependency>
  <groupId>com.jph.takephoto</groupId>
  <artifactId>takephoto_library</artifactId>
  <version>4.1.0</version>
  <type>pom</type>
</dependency>
```  


## 演示 

运行效果图:    
![预览图](https://raw.githubusercontent.com/crazycodeboy/TakePhoto/master/Screenshots/takephoto_preview.png)
![运行效果图](https://raw.githubusercontent.com/crazycodeboy/TakePhoto/master/Screenshots/%E9%A2%84%E8%A7%88%E5%9B%BE.jpg)


## 使用说明   

### 使用TakePhoto有以下两种方式:
**方式一:通过继承的方式**  
1. 继承`TakePhotoActivity`、`TakePhotoFragmentActivity`、`TakePhotoFragment`三者之一。  
2. 通过`getTakePhoto()`获取`TakePhoto`实例进行相关操作。  
3. 重写以下方法获取结果        

```java
 void takeSuccess(TResult result);
 void takeFail(TResult result,String msg);
 void takeCancel();
```  
此方式使用简单,满足的大部分的使用需求,具体使用详见[simple](https://github.com/crazycodeboy/TakePhoto/blob/master/simple/src/main/java/com/jph/simple/SimpleActivity.java)。如果通过继承的方式无法满足实际项目的使用,可以通过下面介绍的方式。  

**方式二:通过组装的方式**  

可参照:[TakePhotoActivity](https://github.com/crazycodeboy/TakePhoto/blob/master/takephoto_library/src/main/java/com/jph/takephoto/app/TakePhotoActivity.java),以下为主要步骤:  

1.实现`TakePhoto.TakeResultListener,InvokeListener`接口。

2.在 `onCreate`,`onActivityResult`,`onSaveInstanceState`方法中调用TakePhoto对用的方法。  

3.重写`onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)`,添加如下代码。

```java
  @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)`方法,添加如下代码:  

```java
 @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实例:  

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

## 自定义UI

TakePhoto不仅支持对相关参数的自定义,也支持对UI的自定义,下面就像大家介绍如何自定义TakePhoto的相册与裁剪工具的UI。

### 自定义相册
如果TakePhoto自带相册的UI不符合你应用的主题的话,你可以对它进行自定义。方法如下:   

#### 自定义Toolbar 

在“res/layout”目录中创建一个名为“toolbar.xml”的布局文件,内容如下:   

```xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    app:theme="@style/CustomToolbarTheme"
    android:background="#ffa352">
</android.support.v7.widget.Toolbar>
```

在“toolbar.xml”文件中你可以指定TakePhoto自带相册的主题以及Toolbar的背景色。

#### 自定义状态栏

在“res/values”目录中创建一个名为“colors.xml”的资源文件,内容如下: 

```xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="multiple_image_select_primaryDark">#212121</color>
</resources>
```

通过上述方式便可以自定义状态栏的颜色。

#### 自定义提示文字

在“res/values”目录的“string.xml”文件冲添加如下代码:

```xml
<resources>    
    <string name="album_view">选择图片</string>
    <string name="image_view">单击选择</string>
    <string name="add">确定</string>
    <string name="selected">已选</string>
    <string name="limit_exceeded">最多能选 %d 张</string>
</resources>
```

重写上述代码,便可以自定义TakePhoto自带相册的提示文字。

### 自定义裁切工具

在“res/layout”目录中创建一个名为“crop__activity_crop.xml”与“crop__layout_done_cancel.xml”的布局文件,内容如下:  

**crop__activity_crop.xml**  

```xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.soundcloud.android.crop.CropImageView
        android:id="@+id/crop_image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentTop="true"
        android:background="@drawable/crop__texture"
        android:layout_above="@+id/done_cancel_bar" />
    <include
        android:id="@+id/done_cancel_bar"
        android:layout_alignParentBottom="true"
        layout="@layout/crop__layout_done_cancel"
        android:layout_height="50dp"
        android:layout_width="match_parent" />
</RelativeLayout>
```

**crop__layout_done_cancel.xml**  

```xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    style="@style/Crop.DoneCancelBar">
    <FrameLayout
        android:id="@+id/btn_cancel"
        style="@style/Crop.ActionButton">
        <TextView style="@style/Crop.ActionButtonText.Cancel" />
    </FrameLayout>
    <FrameLayout
        android:id="@+id/btn_done"
        style="@style/Crop.ActionButton">
        <TextView style="@style/Crop.ActionButtonText.Done" />
    </FrameLayout>
</LinearLayout>
```

重写上述代码,便可以自定义TakePhoto裁切工具的UI。

## API

### 获取图片
TakePhoto提供拍照,从相册选择,从文件中选择三种方式获取图片。    

#### API:

```java
/**
 * 从文件中获取图片(不裁剪)
 */
void onPickFromDocuments();
/**
 * 从相册中获取图片(不裁剪)
 */
void onPickFromGallery();
/**
 * 从相机获取图片(不裁剪)
 * @param outPutUri 图片保存的路径
 */
void onPickFromCapture(Uri outPutUri);
/**
 * 图片多选
 * @param limit 最多选择图片张数的限制
 **/
void onPickMultiple(int limit);
```
以上三种方式均提供对应的裁剪API,详见:[裁剪图片](https://github.com/crazycodeboy/TakePhoto#裁剪图片)。    
**注:**  
由于不同Android Rom厂商对系统有不同程度的定制,有可能导致某种选择图片的方式不支持,所以为了提高`TakePhoto`的兼容性,当某种选的图片的方式不支持时,`TakePhoto`会自动切换成使用另一种选择图片的方式进行图片选择。      

### 裁剪图片  

#### API  
`TakePhoto`支持对图片进行裁剪,无论是拍照的照片,还是从相册、文件中选择的图片。你只需要调用`TakePhoto`的相应方法即可:  

```java
/**
 * 从相机获取图片并裁剪
 * @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也支持你对指定图片进行裁剪:     

```java
/**
 * 裁剪图片
 * @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;
```

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

**Usage:**  

```java
 CropOptions cropOptions=new CropOptions.Builder().setAspectX(1).setAspectY(1).setWithOwnCrop(true).create();  
 getTakePhoto().onPickFromDocumentsWithCrop(imageUri,cropOptions);  
 //或  
 getTakePhoto().onCrop(imageUri,outPutUri,cropOptions);  

```

**注:**  
由于不同Android Rom厂商对系统有不同程度的定制,有可能系统中没有自带或第三方的裁剪工具,所以为了提高`TakePhoto`的兼容性,当系统中没有自带或第三方裁剪工具时,`TakePhoto`会自动切换到使用`TakePhoto`自带的裁剪工具进行裁剪。  

>另外TakePhoto4.0+支持指定使用TakePhoto自带相册,如:`takePhoto.setTakePhotoOptions(new TakePhotoOptions.Builder().setWithOwnGallery(true).create());`
详情可参考:[Demo](https://github.com/crazycodeboy/TakePhoto/blob/master/simple/src/main/java/com/jph/simple/CustomHelper.java)

### 压缩图片
你可以选择是否对图片进行压缩处理,你只需要告诉它你是否要启用压缩功能以及`CompressConfig`即可。  

#### API
```java
 /**
  * 启用图片压缩
  * @param config 压缩图片配置
  * @param showCompressDialog 压缩时是否显示进度对话框
  * @return
  */
 void onEnableCompress(CompressConfig config,boolean showCompressDialog);
```

**Usage:**  

```java
TakePhoto takePhoto=getTakePhoto();
takePhoto.onEnableCompress(compressConfig,true);
takePhoto.onPickFromGallery();
```  
如果你启用了图片压缩,`TakePhoto`会使用`CompressImage`对图片进行压缩处理,`CompressImage`目前支持对图片的尺寸以及图片的质量进行压缩。默认情况下,`CompressImage`开启了尺寸与质量双重压缩。  

#### 对指定图片进行压缩  
另外,你也可以对指定图片进行压缩:    
**Usage:**  

```java
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();
```

#### CompressConfig  
`CompressConfig`是用于图片压缩的配置类,你可以通过`CompressConfig.Builder`对图片压缩后的尺寸以及质量进行相关设置。如果你想改变压缩的方式可以通过`CompressConfig.Builder`进行相关设置。     
**Usage:**   

```java
CompressConfig compressConfig=new CompressConfig.Builder().setMaxSize(50*1024).setMaxPixel(800).create();
```
#### 指定压缩工具

#### 使用TakePhoto压缩工具进行压缩: 

```
CompressConfig config=new CompressConfig.Builder()
                    .setMaxSize(maxSize)
                    .setMaxPixel(width>=height? width:height)
                    .create();
takePhoto.onEnableCompress(config,showProgressBar);
```

#### 使用Luban进行压缩: 
```
LubanOptions option=new LubanOptions.Builder()
                    .setGear(Luban.CUSTOM_GEAR)
                    .setMaxHeight(height)
                    .setMaxWidth(width)
                    .setMaxSize(maxSize)
                    .create();
CompressConfig config=CompressConfig.ofLuban(option);
takePhoto.onEnableCompress(config,showProgressBar);
```

>详情可参考Demo:[CustomHelper.java](https://github.com/crazycodeboy/TakePhoto/blob/master/simple/src/main/java/com/jph/simple/CustomHelper.java)


## 兼容性

### Android6.0
由于Android6.0新增了"运行时权限控制(Runtime Permissions)",为了应对这一改变,TakePhoto加入和自动权限管理,当TakePhoto检测到需要权限时,TakePhoto会自动申请权限,所以小伙伴们不用担心权限的使用问题。

### Android7.0  

在Android N中,Android 框架执行了 StrictMode,应用间共享文件和以前也有所区别。为了适配Android7.0的改变,同时也为了方便大家使用TakePhoto,TakePhoto会自动根据手机的Android版本自行适配,小伙伴们依旧可以向TakePhoto传递`Uri imageUri = Uri.fromFile(file);`类型的Uri而不用担心兼容性问题。

### TakePhoto在深度兼容性方面的测试    
![兼容性测试报告](https://raw.githubusercontent.com/crazycodeboy/TakePhoto/master/Screenshots/%E5%85%BC%E5%AE%B9%E6%80%A7%E6%B5%8B%E8%AF%95.jpg)

### 获取更高的兼容性    
`TakePhot`o是基于Android官方标准API编写的,适配了目前市场上主流的Rom。如果你在使用过程中发现了适配问题,可以[提交Issues](https://github.com/crazycodeboy/TakePhoto/issues)。   
1. 为适配部分手机拍照时会回收`Activity`,`TakePhoto`在`onSaveInstanceState`与 `onCreate`做了相应的恢复处理。  
2. 为适配部分手机拍照或从相册选择图片时屏幕方向会发生转变,从而导致拍照失败的问题,可以在AndroidManifest.xml中对使用了`TakePhoto`的`Activity`添加android:configChanges="orientation|keyboardHidden|screenSize"配置。  
eg:  

```
<activity
    android:name=".MainActivity"
    android:screenOrientation="portrait"
    android:configChanges="orientation|keyboardHidden|screenSize"
    android:label="@string/app_name" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
```

## 贡献  
如果你在使用TakePhoto中遇到任何问题可以提[Issues](https://github.com/crazycodeboy/TakePhoto/issues)出来。另外欢迎大家为TakePhoto贡献智慧,欢迎大家[Fork and Pull requests](https://github.com/crazycodeboy/TakePhoto)。     

## 更新说明

v4.1.0(2018/4/2)
-----------------

1. Upgrade glide to 4.6.1;
2. Upgrade  buildToolsVersion & targetSdkVersion ;
3. rename package name ;

v4.0.3(2017/1/18)
-----------------
**Bugfixes**

1. Fixed bug and add new features([`62a6725`](https://github.com/crazycodeboy/TakePhoto/commit/62a6725a99118ec0ce0f4cf1cd76b2ba70e21745))-@[Yanqilong](https://github.com/Yanqilong)
2. fix 鲁班压缩出现路径重复([`a0a64a59`](https://github.com/crazycodeboy/TakePhoto/commit/a0a64a59762fa8554eb46b6ec544f70a5d46f551))-@[namezhouyu](https://github.com/namezhouyu)


v4.0.2(2016/11/28)
------------------
1. 压缩成功后返回原图路径(originalPath), 以便用户可以自行处理原图。
2. 压缩成功后压缩路径path改为compressPath。
3. 压缩成功后返回图片来源类型,现在分CAMERA, OTHER两种。
4. 用户可以配置CompressConfig.enableReserveRaw(boolean)方法,ture保留原图,false删除原图,当且仅当类型为CAMERA此配置才有效
5. 纠正拍照旋转角度功能改为可选

## 最后

### 关于代码混淆
如果你的项目中启用了代码混淆,可在混淆规则文件(如:proguard-rules.pro)中添加如下代码:   

```
-keep class com.jph.takephoto.** { *; }
-dontwarn com.jph.takephoto.**

-keep class com.darsh.multipleimageselect.** { *; }
-dontwarn com.darsh.multipleimageselect.**

-keep class com.soundcloud.android.crop.** { *; }
-dontwarn com.soundcloud.android.crop.**

```


================================================
FILE: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
        google()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.0'
//        classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
//        classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
        google()
    }
}


================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Mon Apr 02 19:53:50 CST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip


================================================
FILE: gradle.properties
================================================
# Project-wide Gradle settings.

# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.

# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html

# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

================================================
FILE: gradlew
================================================
#!/usr/bin/env bash

##############################################################################
##
##  Gradle start up script for UN*X
##
##############################################################################

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""

APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

warn ( ) {
    echo "$*"
}

die ( ) {
    echo
    echo "$*"
    echo
    exit 1
}

# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
  CYGWIN* )
    cygwin=true
    ;;
  Darwin* )
    darwin=true
    ;;
  MINGW* )
    msys=true
    ;;
esac

# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
    [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi

# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
    ls=`ls -ld "$PRG"`
    link=`expr "$ls" : '.*-> \(.*\)$'`
    if expr "$link" : '/.*' > /dev/null; then
        PRG="$link"
    else
        PRG=`dirname "$PRG"`"/$link"
    fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar

# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
        # IBM's JDK on AIX uses strange locations for the executables
        JAVACMD="$JAVA_HOME/jre/sh/java"
    else
        JAVACMD="$JAVA_HOME/bin/java"
    fi
    if [ ! -x "$JAVACMD" ] ; then
        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
    fi
else
    JAVACMD="java"
    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi

# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
    MAX_FD_LIMIT=`ulimit -H -n`
    if [ $? -eq 0 ] ; then
        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
            MAX_FD="$MAX_FD_LIMIT"
        fi
        ulimit -n $MAX_FD
        if [ $? -ne 0 ] ; then
            warn "Could not set maximum file descriptor limit: $MAX_FD"
        fi
    else
        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
    fi
fi

# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi

# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`

    # We build the pattern for arguments to be converted via cygpath
    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
    SEP=""
    for dir in $ROOTDIRSRAW ; do
        ROOTDIRS="$ROOTDIRS$SEP$dir"
        SEP="|"
    done
    OURCYGPATTERN="(^($ROOTDIRS))"
    # Add a user-defined pattern to the cygpath arguments
    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
    fi
    # Now convert the arguments - kludge to limit ourselves to /bin/sh
    i=0
    for arg in "$@" ; do
        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option

        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
        else
            eval `echo args$i`="\"$arg\""
        fi
        i=$((i+1))
    done
    case $i in
        (0) set -- ;;
        (1) set -- "$args0" ;;
        (2) set -- "$args0" "$args1" ;;
        (3) set -- "$args0" "$args1" "$args2" ;;
        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
    esac
fi

# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
    JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"

exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"


================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem  Gradle startup script for Windows
@rem
@rem ##########################################################################

@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto init

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:init
@rem Get command-line arguments, handling Windowz variants

if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args

:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2

:win9xME_args_slurp
if "x%~1" == "x" goto execute

set CMD_LINE_ARGS=%*
goto execute

:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1

:mainEnd
if "%OS%"=="Windows_NT" endlocal

:omega


================================================
FILE: settings.gradle
================================================
include ':takephoto_library', ':simple'


================================================
FILE: simple/.gitignore
================================================
# Created by .ignore support plugin (hsz.mobi)
### Android template
# Built application files
*.apk
*.ap_

# Files for the Dalvik VM
*.dex

# Java class files
*.class

# Generated files
bin/
gen/

# Gradle files
.gradle/
build/
/*/build/

# Local configuration file (sdk path, etc)
local.properties

# Proguard folder generated by Eclipse
proguard/

# Log Files
*.log


### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion

*.iml

## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:

# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries

# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml

# Gradle:
# .idea/gradle.xml
# .idea/libraries

# Mongo Explorer plugin:
# .idea/mongoSettings.xml

## File-based project format:
*.ipr
*.iws

## Plugin-specific files:

# IntelliJ
/out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties


### Gradle template
.gradle

# Ignore Gradle GUI config
gradle-app.setting

# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar




================================================
FILE: simple/build.gradle
================================================
apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    buildToolsVersion '26.0.3'

    defaultConfig {
        applicationId "org.devio.simple"
        minSdkVersion 14
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile project(':takephoto_library')
}


================================================
FILE: simple/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in D:\Program Files\adt-bundle-windows-x86_64-20140702\sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}

-dontwarn android.support.**
-keep class android.support.** { *; }


-keepattributes InnerClasses
-dontoptimize

================================================
FILE: simple/src/androidTest/java/org/devio/simple/ApplicationTest.java
================================================
package org.devio.simple;

import android.app.Application;
import android.test.ApplicationTestCase;

/**
 * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
 */
public class ApplicationTest extends ApplicationTestCase<Application> {
    public ApplicationTest() {
        super(Application.class);
    }
}

================================================
FILE: simple/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.devio.simple" >
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:screenOrientation="portrait"
            android:configChanges="orientation|keyboardHidden|screenSize"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".SimpleActivity"
            android:screenOrientation="portrait"
            android:configChanges="orientation|keyboardHidden|screenSize"></activity>
        <activity android:name=".SimpleFragmentActivity"
            android:screenOrientation="portrait"
            android:configChanges="orientation|keyboardHidden|screenSize"></activity>
        <activity android:name=".ResultActivity"></activity>
    </application>

</manifest>


================================================
FILE: simple/src/main/java/org/devio/simple/CustomHelper.java
================================================
package org.devio.simple;

import android.net.Uri;
import android.os.Environment;
import android.view.View;
import android.widget.EditText;
import android.widget.RadioGroup;

import org.devio.takephoto.app.TakePhoto;
import org.devio.takephoto.compress.CompressConfig;
import org.devio.takephoto.model.CropOptions;
import org.devio.takephoto.model.LubanOptions;
import org.devio.takephoto.model.TakePhotoOptions;

import java.io.File;


/**
 * - 支持通过相机拍照获取图片
 * - 支持从相册选择图片
 * - 支持从文件选择图片
 * - 支持多图选择
 * - 支持批量图片裁切
 * - 支持批量图片压缩
 * - 支持对图片进行压缩
 * - 支持对图片进行裁剪
 * - 支持对裁剪及压缩参数自定义
 * - 提供自带裁剪工具(可选)
 * - 支持智能选取及裁剪异常处理
 * - 支持因拍照Activity被回收后的自动恢复
 * Author: crazycodeboy
 * Date: 2016/9/21 0007 20:10
 * Version:4.0.0
 * 技术博文:http://www.devio.org
 * GitHub:https://github.com/crazycodeboy
 * Email:crazycodeboy@gmail.com
 */
public class CustomHelper {
    private View rootView;
    private RadioGroup rgCrop, rgCompress, rgFrom, rgCropSize, rgCropTool, rgShowProgressBar, rgPickTool, rgCompressTool, rgCorrectTool,
        rgRawFile;
    private EditText etCropHeight, etCropWidth, etLimit, etSize, etHeightPx, etWidthPx;

    public static CustomHelper of(View rootView) {
        return new CustomHelper(rootView);
    }

    private CustomHelper(View rootView) {
        this.rootView = rootView;
        init();
    }

    private void init() {
        rgCrop = (RadioGroup) rootView.findViewById(R.id.rgCrop);
        rgCompress = (RadioGroup) rootView.findViewById(R.id.rgCompress);
        rgCompressTool = (RadioGroup) rootView.findViewById(R.id.rgCompressTool);
        rgCropSize = (RadioGroup) rootView.findViewById(R.id.rgCropSize);
        rgFrom = (RadioGroup) rootView.findViewById(R.id.rgFrom);
        rgPickTool = (RadioGroup) rootView.findViewById(R.id.rgPickTool);
        rgRawFile = (RadioGroup) rootView.findViewById(R.id.rgRawFile);
        rgCorrectTool = (RadioGroup) rootView.findViewById(R.id.rgCorrectTool);
        rgShowProgressBar = (RadioGroup) rootView.findViewById(R.id.rgShowProgressBar);
        rgCropTool = (RadioGroup) rootView.findViewById(R.id.rgCropTool);
        etCropHeight = (EditText) rootView.findViewById(R.id.etCropHeight);
        etCropWidth = (EditText) rootView.findViewById(R.id.etCropWidth);
        etLimit = (EditText) rootView.findViewById(R.id.etLimit);
        etSize = (EditText) rootView.findViewById(R.id.etSize);
        etHeightPx = (EditText) rootView.findViewById(R.id.etHeightPx);
        etWidthPx = (EditText) rootView.findViewById(R.id.etWidthPx);



    }

    public void onClick(View view, TakePhoto takePhoto) {
        File file = new File(Environment.getExternalStorageDirectory(), "/temp/" + System.currentTimeMillis() + ".jpg");
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        Uri imageUri = Uri.fromFile(file);

        configCompress(takePhoto);
        configTakePhotoOption(takePhoto);
        switch (view.getId()) {
            case R.id.btnPickBySelect:
                int limit = Integer.parseInt(etLimit.getText().toString());
                if (limit > 1) {
                    if (rgCrop.getCheckedRadioButtonId() == R.id.rbCropYes) {
                        takePhoto.onPickMultipleWithCrop(limit, getCropOptions());
                    } else {
                        takePhoto.onPickMultiple(limit);
                    }
                    return;
                }
                if (rgFrom.getCheckedRadioButtonId() == R.id.rbFile) {
                    if (rgCrop.getCheckedRadioButtonId() == R.id.rbCropYes) {
                        takePhoto.onPickFromDocumentsWithCrop(imageUri, getCropOptions());
                    } else {
                        takePhoto.onPickFromDocuments();
                    }
                    return;
                } else {
                    if (rgCrop.getCheckedRadioButtonId() == R.id.rbCropYes) {
                        takePhoto.onPickFromGalleryWithCrop(imageUri, getCropOptions());
                    } else {
                        takePhoto.onPickFromGallery();
                    }
                }
                break;
            case R.id.btnPickByTake:
                if (rgCrop.getCheckedRadioButtonId() == R.id.rbCropYes) {
                    takePhoto.onPickFromCaptureWithCrop(imageUri, getCropOptions());
                } else {
                    takePhoto.onPickFromCapture(imageUri);
                }
                break;
            default:
                break;
        }
    }

    private void configTakePhotoOption(TakePhoto takePhoto) {
        TakePhotoOptions.Builder builder = new TakePhotoOptions.Builder();
        if (rgPickTool.getCheckedRadioButtonId() == R.id.rbPickWithOwn) {
            builder.setWithOwnGallery(true);
        }
        if (rgCorrectTool.getCheckedRadioButtonId() == R.id.rbCorrectYes) {
            builder.setCorrectImage(true);
        }
        takePhoto.setTakePhotoOptions(builder.create());

    }

    private void configCompress(TakePhoto takePhoto) {
        if (rgCompress.getCheckedRadioButtonId() != R.id.rbCompressYes) {
            takePhoto.onEnableCompress(null, false);
            return;
        }
        int maxSize = Integer.parseInt(etSize.getText().toString());
        int width = Integer.parseInt(etCropWidth.getText().toString());
        int height = Integer.parseInt(etHeightPx.getText().toString());
        boolean showProgressBar = rgShowProgressBar.getCheckedRadioButtonId() == R.id.rbShowYes ? true : false;
        boolean enableRawFile = rgRawFile.getCheckedRadioButtonId() == R.id.rbRawYes ? true : false;
        CompressConfig config;
        if (rgCompressTool.getCheckedRadioButtonId() == R.id.rbCompressWithOwn) {
            config = new CompressConfig.Builder().setMaxSize(maxSize)
                .setMaxPixel(width >= height ? width : height)
                .enableReserveRaw(enableRawFile)
                .create();
        } else {
            LubanOptions option = new LubanOptions.Builder().setMaxHeight(height).setMaxWidth(width).setMaxSize(maxSize).create();
            config = CompressConfig.ofLuban(option);
            config.enableReserveRaw(enableRawFile);
        }
        takePhoto.onEnableCompress(config, showProgressBar);


    }

    private CropOptions getCropOptions() {
        if (rgCrop.getCheckedRadioButtonId() != R.id.rbCropYes) {
            return null;
        }
        int height = Integer.parseInt(etCropHeight.getText().toString());
        int width = Integer.parseInt(etCropWidth.getText().toString());
        boolean withWonCrop = rgCropTool.getCheckedRadioButtonId() == R.id.rbCropOwn ? true : false;

        CropOptions.Builder builder = new CropOptions.Builder();

        if (rgCropSize.getCheckedRadioButtonId() == R.id.rbAspect) {
            builder.setAspectX(width).setAspectY(height);
        } else {
            builder.setOutputX(width).setOutputY(height);
        }
        builder.setWithOwnCrop(withWonCrop);
        return builder.create();
    }

}


================================================
FILE: simple/src/main/java/org/devio/simple/MainActivity.java
================================================
package org.devio.simple;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;


/**
 * - 支持通过相机拍照获取图片
 * - 支持从相册选择图片
 * - 支持从文件选择图片
 * - 支持多图选择
 * - 支持批量图片裁切
 * - 支持批量图片压缩
 * - 支持对图片进行压缩
 * - 支持对图片进行裁剪
 * - 支持对裁剪及压缩参数自定义
 * - 提供自带裁剪工具(可选)
 * - 支持智能选取及裁剪异常处理
 * - 支持因拍照Activity被回收后的自动恢复
 * Author: crazycodeboy
 * Date: 2016/9/21 0007 20:10
 * Version:4.0.0
 * 技术博文:http://www.devio.org
 * GitHub:https://github.com/crazycodeboy
 * Email:crazycodeboy@gmail.com
 */
public class MainActivity extends Activity implements View.OnClickListener {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_layout);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btnTakePhotoActivity:
                startActivity(new Intent(this, SimpleActivity.class));
                break;
            case R.id.btnTakePhotoFragment:
                startActivity(new Intent(this, SimpleFragmentActivity.class));
                break;
            default:
        }
    }
}


================================================
FILE: simple/src/main/java/org/devio/simple/ResultActivity.java
================================================
package org.devio.simple;

import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;

import com.bumptech.glide.Glide;

import org.devio.takephoto.model.TImage;

import java.io.File;
import java.util.ArrayList;


/**
 * - 支持通过相机拍照获取图片
 * - 支持从相册选择图片
 * - 支持从文件选择图片
 * - 支持多图选择
 * - 支持批量图片裁切
 * - 支持批量图片压缩
 * - 支持对图片进行压缩
 * - 支持对图片进行裁剪
 * - 支持对裁剪及压缩参数自定义
 * - 提供自带裁剪工具(可选)
 * - 支持智能选取及裁剪异常处理
 * - 支持因拍照Activity被回收后的自动恢复
 * Author: crazycodeboy
 * Date: 2016/9/21 0007 20:10
 * Version:4.0.0
 * 技术博文:http://www.devio.org
 * GitHub:https://github.com/crazycodeboy
 * Email:crazycodeboy@gmail.com
 */
public class ResultActivity extends Activity {
    ArrayList<TImage> images;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_result_layout);
        images = (ArrayList<TImage>) getIntent().getSerializableExtra("images");
        showImg();
    }

    private void showImg() {
        LinearLayout linearLayout = (LinearLayout) findViewById(R.id.llImages);
        for (int i = 0, j = images.size(); i < j - 1; i += 2) {
            View view = LayoutInflater.from(this).inflate(R.layout.image_show, null);
            ImageView imageView1 = (ImageView) view.findViewById(R.id.imgShow1);
            ImageView imageView2 = (ImageView) view.findViewById(R.id.imgShow2);
            Glide.with(this).load(new File(images.get(i).getCompressPath())).into(imageView1);
            Glide.with(this).load(new File(images.get(i + 1).getCompressPath())).into(imageView2);
            linearLayout.addView(view);
        }
        if (images.size() % 2 == 1) {
            View view = LayoutInflater.from(this).inflate(R.layout.image_show, null);
            ImageView imageView1 = (ImageView) view.findViewById(R.id.imgShow1);
            Glide.with(this).load(new File(images.get(images.size() - 1).getCompressPath())).into(imageView1);
            linearLayout.addView(view);
        }

    }
}


================================================
FILE: simple/src/main/java/org/devio/simple/SimpleActivity.java
================================================
package org.devio.simple;

import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;

import org.devio.takephoto.app.TakePhotoActivity;
import org.devio.takephoto.model.TImage;
import org.devio.takephoto.model.TResult;

import java.util.ArrayList;


/**
 * - 支持通过相机拍照获取图片
 * - 支持从相册选择图片
 * - 支持从文件选择图片
 * - 支持多图选择
 * - 支持批量图片裁切
 * - 支持批量图片压缩
 * - 支持对图片进行压缩
 * - 支持对图片进行裁剪
 * - 支持对裁剪及压缩参数自定义
 * - 提供自带裁剪工具(可选)
 * - 支持智能选取及裁剪异常处理
 * - 支持因拍照Activity被回收后的自动恢复
 * Author: crazycodeboy
 * Date: 2016/9/21 0007 20:10
 * Version:4.0.0
 * 技术博文:http://www.devio.org
 * GitHub:https://github.com/crazycodeboy
 * Email:crazycodeboy@gmail.com
 */
public class SimpleActivity extends TakePhotoActivity {
    private CustomHelper customHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        View contentView = LayoutInflater.from(this).inflate(R.layout.common_layout, null);
        setContentView(contentView);
        customHelper = CustomHelper.of(contentView);
    }

    public void onClick(View view) {
        customHelper.onClick(view, getTakePhoto());
    }

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

    @Override
    public void takeFail(TResult result, String msg) {
        super.takeFail(result, msg);
    }

    @Override
    public void takeSuccess(TResult result) {
        super.takeSuccess(result);
        showImg(result.getImages());
    }

    private void showImg(ArrayList<TImage> images) {
        Intent intent = new Intent(this, ResultActivity.class);
        intent.putExtra("images", images);
        startActivity(intent);
    }
}


================================================
FILE: simple/src/main/java/org/devio/simple/SimpleFragment.java
================================================
package org.devio.simple;

import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import org.devio.takephoto.app.TakePhotoFragment;
import org.devio.takephoto.model.TImage;
import org.devio.takephoto.model.TResult;

import java.util.ArrayList;


/**
 * - 支持通过相机拍照获取图片
 * - 支持从相册选择图片
 * - 支持从文件选择图片
 * - 支持多图选择
 * - 支持批量图片裁切
 * - 支持批量图片压缩
 * - 支持对图片进行压缩
 * - 支持对图片进行裁剪
 * - 支持对裁剪及压缩参数自定义
 * - 提供自带裁剪工具(可选)
 * - 支持智能选取及裁剪异常处理
 * - 支持因拍照Activity被回收后的自动恢复
 * Author: crazycodeboy
 * Date: 2016/9/21 0007 20:10
 * Version:4.0.0
 * 技术博文:http://www.devio.org
 * GitHub:https://github.com/crazycodeboy
 * Email:crazycodeboy@gmail.com
 */
public class SimpleFragment extends TakePhotoFragment {
    private CustomHelper customHelper;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.common_layout, null);
        customHelper = CustomHelper.of(view);
        return view;
    }

    public void onClick(View view) {
        customHelper.onClick(view, getTakePhoto());
    }

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

    @Override
    public void takeFail(TResult result, String msg) {
        super.takeFail(result, msg);
    }

    @Override
    public void takeSuccess(TResult result) {
        super.takeSuccess(result);
        showImg(result.getImages());
    }

    private void showImg(ArrayList<TImage> images) {
        Intent intent = new Intent(getContext(), ResultActivity.class);
        intent.putExtra("images", images);
        startActivity(intent);
    }
}


================================================
FILE: simple/src/main/java/org/devio/simple/SimpleFragmentActivity.java
================================================
package org.devio.simple;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.view.View;


/**
 * - 支持通过相机拍照获取图片
 * - 支持从相册选择图片
 * - 支持从文件选择图片
 * - 支持多图选择
 * - 支持批量图片裁切
 * - 支持批量图片压缩
 * - 支持对图片进行压缩
 * - 支持对图片进行裁剪
 * - 支持对裁剪及压缩参数自定义
 * - 提供自带裁剪工具(可选)
 * - 支持智能选取及裁剪异常处理
 * - 支持因拍照Activity被回收后的自动恢复
 * Author: crazycodeboy
 * Date: 2016/9/21 0007 20:10
 * Version:4.0.0
 * 技术博文:http://www.devio.org
 * GitHub:https://github.com/crazycodeboy
 * Email:crazycodeboy@gmail.com
 */
public class SimpleFragmentActivity extends FragmentActivity {
    SimpleFragment fragment;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.simple_fragment_layout);
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.add(R.id.fragment1, fragment = new SimpleFragment(), "test");
        transaction.commit();
    }

    public void onClick(View v) {
        fragment.onClick(v);
    }
}


================================================
FILE: simple/src/main/res/layout/activity_main_layout.xml
================================================
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:id="@+id/btnTakePhotoActivity"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onClick"
            android:layout_margin="5dp"
            android:text="在Activity中使用" />
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btnTakePhotoFragment"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onClick"
            android:layout_margin="5dp"
            android:text="在Fragment中使用" />
    </LinearLayout>

</LinearLayout>


================================================
FILE: simple/src/main/res/layout/activity_result_layout.xml
================================================
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <LinearLayout
            android:id="@+id/llImages"
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </ScrollView>
</LinearLayout>

================================================
FILE: simple/src/main/res/layout/common_layout.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="10dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:orientation="vertical">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="裁切配置:"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1px"
                android:background="@android:color/darker_gray" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_vertical"
                android:orientation="horizontal">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="是否裁切:" />

                <RadioGroup
                    android:id="@+id/rgCrop"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal">

                    <RadioButton
                        android:id="@+id/rbCropYes"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_horizontal"
                        android:checked="true"
                        android:text="是" />

                    <RadioButton
                        android:id="@+id/rbCropNo"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="否" />
                </RadioGroup>
            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_vertical"
                android:orientation="horizontal">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="裁切工具:" />

                <RadioGroup
                    android:id="@+id/rgCropTool"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal">

                    <RadioButton
                        android:id="@+id/rbCropByOther"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_horizontal"
                        android:checked="true"
                        android:text="第三方" />

                    <RadioButton
                        android:id="@+id/rbCropOwn"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="TakePhoto自带" />
                </RadioGroup>
            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_vertical"
                android:orientation="horizontal">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="尺寸/比例:" />

                <RadioGroup
                    android:id="@+id/rgCropSize"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal">

                    <RadioButton
                        android:id="@+id/rbOutPut"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_horizontal"
                        android:checked="true"
                        android:text="宽x高" />

                    <RadioButton
                        android:id="@+id/rbAspect"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="宽/高" />
                </RadioGroup>

                <EditText
                    android:id="@+id/etCropWidth"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="10dp"
                    android:inputType="number"
                    android:minWidth="42dp"
                    android:text="800" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="x" />

                <EditText
                    android:id="@+id/etCropHeight"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:minWidth="42dp"
                    android:text="800" />
            </LinearLayout>

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:gravity="center_vertical"
            android:orientation="vertical">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="压缩配置:"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1px"
                android:background="@android:color/darker_gray" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_vertical"
                android:orientation="horizontal">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="压缩工具:" />

                <RadioGroup
                    android:id="@+id/rgCompressTool"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal">

                    <RadioButton
                        android:id="@+id/rbCompressWithOwn"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_horizontal"
                        android:checked="true"
                        android:text="自带" />

                    <RadioButton
                        android:id="@+id/rbCompressWithLuban"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Luban" />
                </RadioGroup>
            </LinearLayout>

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center_vertical"
                android:orientation="horizontal">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="是否压缩:" />

                <RadioGroup
                    android:id="@+id/rgCompress"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal">

                    <RadioButton
                        android:id="@+id/rbCompressYes"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_horizontal"
                        android:checked="true"
                        android:text="是" />

                    <RadioButton
                        android:id="@+id/rbCompressNo"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="否" />
                </RadioGroup>
            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_vertical"
                android:orientation="horizontal">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="显示压缩进度条:" />

                <RadioGroup
                    android:id="@+id/rgShowProgressBar"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal">

                    <RadioButton
                        android:id="@+id/rbShowYes"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_horizontal"
                        android:checked="true"
                        android:text="是" />

                    <RadioButton
                        android:id="@+id/rbShowNo"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="否" />
                </RadioGroup>
            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_vertical"
                android:orientation="horizontal">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="大小不超过:" />

                <EditText
                    android:id="@+id/etSize"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:inputType="number"
                    android:minWidth="42dp"
                    android:text="102400" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="B" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="20dp"
                    android:text="宽:" />

                <EditText
                    android:id="@+id/etWidthPx"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:inputType="number"
                    android:minWidth="42dp"
                    android:text="800" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="20dp"
                    android:text="高:" />

                <EditText
                    android:id="@+id/etHeightPx"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:inputType="number"
                    android:minWidth="42dp"
                    android:text="800" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="px" />
            </LinearLayout>
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:gravity="center_vertical"
            android:orientation="vertical">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="选择图片配置:"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1px"
                android:background="@android:color/darker_gray" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center_vertical"
                    android:orientation="horizontal">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="使用TakePhoto自带相册:" />

                    <RadioGroup
                        android:id="@+id/rgPickTool"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:orientation="horizontal">

                        <RadioButton
                            android:id="@+id/rbPickWithOwn"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_gravity="center_horizontal"
                            android:checked="true"
                            android:text="是" />

                        <RadioButton
                            android:id="@+id/rbPickWithOther"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:text="否" />
                    </RadioGroup>
                </LinearLayout>

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:text="提示:选择多张图片时会自动切换到TakePhoto自带相册"
                    android:textColor="#FF0000"
                    android:textSize="12sp" />

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical">

                    <LinearLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:gravity="center_vertical"
                        android:orientation="horizontal">

                        <TextView
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:text="最多选择:" />

                        <EditText
                            android:id="@+id/etLimit"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:inputType="number"
                            android:minWidth="30dp"
                            android:text="5" />

                        <TextView
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:text="张" />
                    </LinearLayout>

                    <LinearLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:gravity="center_vertical"
                        android:orientation="horizontal">

                        <TextView
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:text="从哪选择:" />

                        <RadioGroup
                            android:id="@+id/rgFrom"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:orientation="horizontal">

                            <RadioButton
                                android:id="@+id/rbGallery"
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:layout_gravity="center_horizontal"
                                android:checked="true"
                                android:text="从相册" />

                            <RadioButton
                                android:id="@+id/rbFile"
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:text="从文件" />
                        </RadioGroup>
                    </LinearLayout>
                </LinearLayout>
            </LinearLayout>


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="其他配置:"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1px"
                android:background="@android:color/darker_gray" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center_vertical"
                    android:orientation="horizontal">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="纠正拍照的照片旋转角度:" />

                    <RadioGroup
                        android:id="@+id/rgCorrectTool"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:orientation="horizontal">

                        <RadioButton
                            android:id="@+id/rbCorrectYes"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_gravity="center_horizontal"
                            android:text="是" />

                        <RadioButton
                            android:id="@+id/rbCorrectNo"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:checked="true"
                            android:text="否" />
                    </RadioGroup>
                </LinearLayout>

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center_vertical"
                    android:orientation="horizontal">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="拍照压缩后是否保存原图:" />

                    <RadioGroup
                        android:id="@+id/rgRawFile"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:orientation="horizontal">

                        <RadioButton
                            android:id="@+id/rbRawYes"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_gravity="center_horizontal"
                            android:checked="true"
                            android:text="是" />

                        <RadioButton
                            android:id="@+id/rbRawNo"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:text="否" />
                    </RadioGroup>
                </LinearLayout>

            </LinearLayout>


            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:orientation="horizontal">

                <Button
                    android:id="@+id/btnPickByTake"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:onClick="onClick"
                    android:text="拍照" />

                <Button
                    android:id="@+id/btnPickBySelect"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:onClick="onClick"
                    android:text="选择照片" />
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>
</ScrollView>

================================================
FILE: simple/src/main/res/layout/image_show.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:orientation="horizontal"
    >
    <ImageView
        android:id="@+id/imgShow1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:layout_gravity="center_horizontal"
        android:layout_marginRight="5dp"
        android:background="@android:color/darker_gray"
        android:scaleType="fitCenter" />
    <ImageView
        android:id="@+id/imgShow2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:layout_gravity="center_horizontal"
        android:layout_marginRight="5dp"
        android:background="@android:color/darker_gray"
        android:scaleType="fitCenter" />
</LinearLayout>


================================================
FILE: simple/src/main/res/layout/simple_fragment_layout.xml
================================================
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_green_dark"
    >
    <FrameLayout android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/darker_gray"
        android:id="@+id/fragment1"/>

</LinearLayout>


================================================
FILE: simple/src/main/res/menu/menu_main.xml
================================================
<menu 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" tools:context=".MainActivity">
    <item android:id="@+id/action_settings" android:title="@string/action_settings"
        android:orderInCategory="100" app:showAsAction="never" />
</menu>


================================================
FILE: simple/src/main/res/values/dimens.xml
================================================
<resources>
    <!-- Default screen margins, per the Android Design guidelines. -->
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>
</resources>


================================================
FILE: simple/src/main/res/values/strings.xml
================================================
<resources>
    <string name="app_name">TakePhoto</string>

    <string name="hello_world">Hello world!</string>
    <string name="action_settings">Settings</string>
</resources>


================================================
FILE: simple/src/main/res/values/styles.xml
================================================
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
    </style>

</resources>


================================================
FILE: simple/src/main/res/values-w820dp/dimens.xml
================================================
<resources>
    <!-- Example customization of dimensions originally defined in res/values/dimens.xml
         (such as screen margins) for screens with more than 820dp of available width. This
         would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
    <dimen name="activity_horizontal_margin">64dp</dimen>
</resources>


================================================
FILE: takephoto_library/.gitignore
================================================
# Created by .ignore support plugin (hsz.mobi)
### Android template
# Built application files
*.apk
*.ap_

# Files for the Dalvik VM
*.dex

# Java class files
*.class

# Generated files
bin/
gen/

# Gradle files
.gradle/
build/
/*/build/

# Local configuration file (sdk path, etc)
local.properties

# Proguard folder generated by Eclipse
proguard/

# Log Files
*.log


### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion

*.iml

## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:

# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries

# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml

# Gradle:
# .idea/gradle.xml
# .idea/libraries

# Mongo Explorer plugin:
# .idea/mongoSettings.xml

## File-based project format:
*.ipr
*.iws

## Plugin-specific files:

# IntelliJ
/out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties


### Gradle template
.gradle

# Ignore Gradle GUI config
gradle-app.setting

# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar  
bintrayUpload.gradle




================================================
FILE: takephoto_library/build.gradle
================================================
apply plugin: 'com.android.library'

android {
    compileSdkVersion 27
    buildToolsVersion '26.0.3'

    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 27
        versionCode 45
        versionName "4.1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile 'com.soundcloud.android.crop:lib_crop:1.0.0'
    compile 'com.darsh.multipleimageselect:multipleimageselect:1.0.5'
    compile 'me.shaohui.advancedluban:library:1.3.2'
}
//apply from: "bintrayUpload.gradle"

================================================
FILE: takephoto_library/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in D:\Program Files\adt-bundle-windows-x86_64-20140702\sdk1/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}


-dontwarn android.support.**
-keep class android.support.** { *; }


-keepattributes InnerClasses
-dontoptimize


-keep class com.jph.takephoto.** { *; }
-dontwarn com.jph.takephoto.**

-keep class com.darsh.multipleimageselect.** { *; }
-dontwarn com.darsh.multipleimageselect.**

-keep class com.soundcloud.android.crop.** { *; }
-dontwarn com.soundcloud.android.crop.**



================================================
FILE: takephoto_library/src/androidTest/java/org/devio/takephoto/ApplicationTest.java
================================================
package org.devio.takephoto;

import android.app.Application;
import android.test.ApplicationTestCase;

/**
 * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
 */
public class ApplicationTest extends ApplicationTestCase<Application> {
    public ApplicationTest() {
        super(Application.class);
    }
}

================================================
FILE: takephoto_library/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.devio.takephoto">

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.CAMERA" />

    <application android:allowBackup="true">
        <activity android:name="com.soundcloud.android.crop.CropImageActivity" />
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:grantUriPermissions="true"
            android:exported="false">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>
    </application>
</manifest>


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/app/TakePhoto.java
================================================
package org.devio.takephoto.app;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;

import org.devio.takephoto.model.MultipleCrop;
import org.devio.takephoto.model.TException;
import org.devio.takephoto.permission.PermissionManager;
import org.devio.takephoto.compress.CompressConfig;
import org.devio.takephoto.model.CropOptions;
import org.devio.takephoto.model.TResult;
import org.devio.takephoto.model.TakePhotoOptions;


/**
 * - 支持通过相机拍照获取图片
 * - 支持从相册选择图片
 * - 支持从文件选择图片
 * - 支持多图选择
 * - 支持批量图片裁切
 * - 支持批量图片压缩
 * - 支持对图片进行压缩
 * - 支持对图片进行裁剪
 * - 支持对裁剪及压缩参数自定义
 * - 提供自带裁剪工具(可选)
 * - 支持智能选取及裁剪异常处理
 * - 支持因拍照Activity被回收后的自动恢复
 * Author: crazycodeboy
 * Date: 2016/9/21 0007 20:10
 * Version:4.0.0
 * 技术博文:http://www.devio.org
 * GitHub:https://github.com/crazycodeboy
 * Email:crazycodeboy@gmail.com
 */
public interface TakePhoto {
    /**
     * 图片多选
     *
     * @param limit 最多选择图片张数的限制
     */
    void onPickMultiple(int limit);

    /**
     * 图片多选,并裁切
     *
     * @param limit   最多选择图片张数的限制
     * @param options 裁剪配置
     */
    void onPickMultipleWithCrop(int limit, CropOptions options);

    /**
     * 从文件中获取图片(不裁剪)
     */
    void onPickFromDocuments();

    /**
     * 从文件中获取图片并裁剪
     *
     * @param outPutUri 图片裁剪之后保存的路径
     * @param options   裁剪配置
     */
    void onPickFromDocumentsWithCrop(Uri outPutUri, CropOptions options);

    /**
     * 从相册中获取图片(不裁剪)
     */
    void onPickFromGallery();

    /**
     * 从相册中获取图片并裁剪
     *
     * @param outPutUri 图片裁剪之后保存的路径
     * @param options   裁剪配置
     */
    void onPickFromGalleryWithCrop(Uri outPutUri, CropOptions options);

    /**
     * 从相机获取图片(不裁剪)
     *
     * @param outPutUri 图片保存的路径
     */
    void onPickFromCapture(Uri outPutUri);

    /**
     * 从相机获取图片并裁剪
     *
     * @param outPutUri 图片裁剪之后保存的路径
     * @param options   裁剪配置
     */
    void onPickFromCaptureWithCrop(Uri outPutUri, CropOptions options);

    /**
     * 裁剪图片
     *
     * @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;

    void permissionNotify(PermissionManager.TPermissionType type);

    /**
     * 启用图片压缩
     *
     * @param config             压缩图片配置
     * @param showCompressDialog 压缩时是否显示进度对话框
     */
    void onEnableCompress(CompressConfig config, boolean showCompressDialog);

    /**
     * 设置TakePhoto相关配置
     *
     * @param options
     */
    void setTakePhotoOptions(TakePhotoOptions options);

    void onCreate(Bundle savedInstanceState);

    void onSaveInstanceState(Bundle outState);

    /**
     * 处理拍照或从相册选择的图片或裁剪的结果
     *
     * @param requestCode
     * @param resultCode
     * @param data
     */
    void onActivityResult(int requestCode, int resultCode, Intent data);

    /**
     * 拍照结果监听接口
     */
    interface TakeResultListener {
        void takeSuccess(TResult result);

        void takeFail(TResult result, String msg);

        void takeCancel();
    }
}

================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/app/TakePhotoActivity.java
================================================
package org.devio.takephoto.app;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

import org.devio.takephoto.model.InvokeParam;
import org.devio.takephoto.permission.PermissionManager;
import org.devio.takephoto.permission.TakePhotoInvocationHandler;
import org.devio.takephoto.R;
import org.devio.takephoto.model.TContextWrap;
import org.devio.takephoto.model.TResult;
import org.devio.takephoto.permission.InvokeListener;

/**
 * 继承这个类来让Activity获取拍照的能力<br>
 * Author: crazycodeboy
 * Date: 2016/9/21 0007 20:10
 * Version:3.0.0
 * 技术博文:http://www.devio.org
 * GitHub:https://github.com/crazycodeboy
 * Email:crazycodeboy@gmail.com
 */
public class TakePhotoActivity extends Activity implements TakePhoto.TakeResultListener, InvokeListener {
    private static final String TAG = TakePhotoActivity.class.getName();
    private TakePhoto takePhoto;
    private InvokeParam invokeParam;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        getTakePhoto().onCreate(savedInstanceState);
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        getTakePhoto().onSaveInstanceState(outState);
        super.onSaveInstanceState(outState);
    }

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

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

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

    @Override
    public void takeSuccess(TResult result) {
        Log.i(TAG, "takeSuccess:" + result.getImage().getCompressPath());
    }

    @Override
    public void takeFail(TResult result, String msg) {
        Log.i(TAG, "takeFail:" + msg);
    }

    @Override
    public void takeCancel() {
        Log.i(TAG, getResources().getString(R.string.msg_operation_canceled));
    }

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


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/app/TakePhotoFragment.java
================================================
package org.devio.takephoto.app;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;

import org.devio.takephoto.permission.PermissionManager;
import org.devio.takephoto.permission.TakePhotoInvocationHandler;
import org.devio.takephoto.model.InvokeParam;
import org.devio.takephoto.model.TContextWrap;
import org.devio.takephoto.model.TResult;
import org.devio.takephoto.permission.InvokeListener;

/**
 * 继承这个类来让Fragment获取拍照的能力<br>
 * Author: crazycodeboy
 * Date: 2016/9/21 0007 20:10
 * Version:3.0.0
 * 技术博文:http://www.devio.org
 * GitHub:https://github.com/crazycodeboy
 * Email:crazycodeboy@gmail.com
 */
public class TakePhotoFragment extends Fragment implements TakePhoto.TakeResultListener, InvokeListener {
    private static final String TAG = TakePhotoFragment.class.getName();
    private InvokeParam invokeParam;
    private TakePhoto takePhoto;

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

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

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

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

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

    @Override
    public void takeSuccess(TResult result) {
        Log.i(TAG, "takeSuccess:" + result.getImage().getCompressPath());
    }

    @Override
    public void takeFail(TResult result, String msg) {
        Log.i(TAG, "takeFail:" + msg);
    }

    @Override
    public void takeCancel() {
        Log.i(TAG, getResources().getString(org.devio.takephoto.R.string.msg_operation_canceled));
    }

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


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/app/TakePhotoFragmentActivity.java
================================================
package org.devio.takephoto.app;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;

import org.devio.takephoto.permission.PermissionManager;
import org.devio.takephoto.model.InvokeParam;
import org.devio.takephoto.model.TContextWrap;
import org.devio.takephoto.model.TResult;
import org.devio.takephoto.permission.InvokeListener;
import org.devio.takephoto.permission.TakePhotoInvocationHandler;

/**
 * 继承这个类来让Activity获取拍照的能力<br>
 * Author: crazycodeboy
 * Date: 2016/9/21 0007 20:10
 * Version:3.0.0
 * 技术博文:http://www.devio.org
 * GitHub:https://github.com/crazycodeboy
 * Email:crazycodeboy@gmail.com
 */
public class TakePhotoFragmentActivity extends FragmentActivity implements TakePhoto.TakeResultListener, InvokeListener {
    private static final String TAG = TakePhotoFragmentActivity.class.getName();
    private TakePhoto takePhoto;
    private InvokeParam invokeParam;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        getTakePhoto().onCreate(savedInstanceState);
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        getTakePhoto().onSaveInstanceState(outState);
        super.onSaveInstanceState(outState);
    }

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

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

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

    @Override
    public void takeSuccess(TResult result) {
        Log.i(TAG, "takeSuccess:" + result.getImage().getCompressPath());
    }

    @Override
    public void takeFail(TResult result, String msg) {
        Log.i(TAG, "takeFail:" + msg);
    }

    @Override
    public void takeCancel() {
        Log.i(TAG, getResources().getString(org.devio.takephoto.R.string.msg_operation_canceled));
    }

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


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/app/TakePhotoImpl.java
================================================
package org.devio.takephoto.app;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.widget.Toast;

import com.darsh.multipleimageselect.helpers.Constants;
import com.darsh.multipleimageselect.models.Image;
import org.devio.takephoto.compress.CompressImage;
import org.devio.takephoto.compress.CompressImageImpl;
import org.devio.takephoto.model.MultipleCrop;
import org.devio.takephoto.model.TException;
import org.devio.takephoto.model.TExceptionType;
import org.devio.takephoto.model.TImage;
import org.devio.takephoto.model.TIntentWap;
import org.devio.takephoto.permission.PermissionManager;
import org.devio.takephoto.uitl.TUriParse;
import org.devio.takephoto.compress.CompressConfig;
import org.devio.takephoto.model.CropOptions;
import org.devio.takephoto.model.TContextWrap;
import org.devio.takephoto.model.TResult;
import org.devio.takephoto.model.TakePhotoOptions;
import org.devio.takephoto.uitl.ImageRotateUtil;
import org.devio.takephoto.uitl.IntentUtils;
import org.devio.takephoto.uitl.TConstant;
import org.devio.takephoto.uitl.TFileUtils;
import org.devio.takephoto.uitl.TImageFiles;
import org.devio.takephoto.uitl.TUtils;
import com.soundcloud.android.crop.Crop;

import java.io.File;
import java.util.ArrayList;
import java.util.Map;

/**
 * - 支持通过相机拍照获取图片
 * - 支持从相册选择图片
 * - 支持从文件选择图片
 * - 支持多图选择
 * - 支持批量图片裁切
 * - 支持批量图片压缩
 * - 支持对图片进行压缩
 * - 支持对图片进行裁剪
 * - 支持对裁剪及压缩参数自定义
 * - 提供自带裁剪工具(可选)
 * - 支持智能选取及裁剪异常处理
 * - 支持因拍照Activity被回收后的自动恢复
 * Date: 2016/9/21 0007 20:10
 * Version:4.0.0
 * 技术博文:http://www.devio.org
 * GitHub:https://github.com/crazycodeboy
 * Email:crazycodeboy@gmail.com
 */
public class TakePhotoImpl implements TakePhoto {
    private static final String TAG = IntentUtils.class.getName();
    private TContextWrap contextWrap;
    private TakeResultListener listener;
    private Uri outPutUri;
    private Uri tempUri;
    private CropOptions cropOptions;
    private TakePhotoOptions takePhotoOptions;
    private CompressConfig compressConfig;
    private MultipleCrop multipleCrop;
    private PermissionManager.TPermissionType permissionType;
    private TImage.FromType fromType; //CAMERA图片来源相机,OTHER图片来源其他
    /**
     * 是否显示压缩对话框
     */
    private boolean showCompressDialog;
    private ProgressDialog wailLoadDialog;

    public TakePhotoImpl(Activity activity, TakeResultListener listener) {
        contextWrap = TContextWrap.of(activity);
        this.listener = listener;
    }

    public TakePhotoImpl(Fragment fragment, TakeResultListener listener) {
        contextWrap = TContextWrap.of(fragment);
        this.listener = listener;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        if (savedInstanceState != null) {
            cropOptions = (CropOptions) savedInstanceState.getSerializable("cropOptions");
            takePhotoOptions = (TakePhotoOptions) savedInstanceState.getSerializable("takePhotoOptions");
            showCompressDialog = savedInstanceState.getBoolean("showCompressDialog");
            outPutUri = savedInstanceState.getParcelable("outPutUri");
            tempUri = savedInstanceState.getParcelable("tempUri");
            compressConfig = (CompressConfig) savedInstanceState.getSerializable("compressConfig");
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        outState.putSerializable("cropOptions", cropOptions);
        outState.putSerializable("takePhotoOptions", takePhotoOptions);
        outState.putBoolean("showCompressDialog", showCompressDialog);
        outState.putParcelable("outPutUri", outPutUri);
        outState.putParcelable("tempUri", tempUri);
        outState.putSerializable("compressConfig", compressConfig);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case TConstant.RC_PICK_PICTURE_FROM_GALLERY_CROP:
                if (resultCode == Activity.RESULT_OK && data != null) {//从相册选择照片并裁剪
                    try {
                        onCrop(data.getData(), outPutUri, cropOptions);
                    } catch (TException e) {
                        takeResult(TResult.of(TImage.of(outPutUri, fromType)), e.getDetailMessage());
                        e.printStackTrace();
                    }
                } else {
                    listener.takeCancel();
                }
                break;
            case TConstant.RC_PICK_PICTURE_FROM_GALLERY_ORIGINAL://从相册选择照片不裁剪
                if (resultCode == Activity.RESULT_OK) {
                    try {
                        takeResult(
                            TResult.of(TImage.of(TUriParse.getFilePathWithUri(data.getData(), contextWrap.getActivity()), fromType)));
                    } catch (TException e) {
                        takeResult(TResult.of(TImage.of(data.getData(), fromType)), e.getDetailMessage());
                        e.printStackTrace();
                    }
                } else {
                    listener.takeCancel();
                }
                break;
            case TConstant.RC_PICK_PICTURE_FROM_DOCUMENTS_ORIGINAL://从文件选择照片不裁剪
                if (resultCode == Activity.RESULT_OK) {
                    try {
                        takeResult(TResult.of(
                            TImage.of(TUriParse.getFilePathWithDocumentsUri(data.getData(), contextWrap.getActivity()), fromType)));
                    } catch (TException e) {
                        takeResult(TResult.of(TImage.of(outPutUri, fromType)), e.getDetailMessage());
                        e.printStackTrace();
                    }
                } else {
                    listener.takeCancel();
                }
                break;
            case TConstant.RC_PICK_PICTURE_FROM_DOCUMENTS_CROP://从文件选择照片,并裁剪
                if (resultCode == Activity.RESULT_OK) {
                    try {
                        onCrop(data.getData(), outPutUri, cropOptions);
                    } catch (TException e) {
                        takeResult(TResult.of(TImage.of(outPutUri, fromType)), e.getDetailMessage());
                        e.printStackTrace();
                    }
                } else {
                    listener.takeCancel();
                }
                break;
            case TConstant.RC_PICK_PICTURE_FROM_CAPTURE_CROP://拍取照片,并裁剪
                if (resultCode == Activity.RESULT_OK) {
                    if (takePhotoOptions != null && takePhotoOptions.isCorrectImage()) {
                        ImageRotateUtil.of().correctImage(contextWrap.getActivity(), tempUri);
                    }
                    try {
                        onCrop(tempUri, Uri.fromFile(new File(TUriParse.parseOwnUri(contextWrap.getActivity(), outPutUri))), cropOptions);
                    } catch (TException e) {
                        takeResult(TResult.of(TImage.of(outPutUri, fromType)), e.getDetailMessage());
                        e.printStackTrace();
                    }
                } else {
                    listener.takeCancel();
                }
                break;
            case TConstant.RC_PICK_PICTURE_FROM_CAPTURE://拍取照片
                if (resultCode == Activity.RESULT_OK) {
                    if (takePhotoOptions != null && takePhotoOptions.isCorrectImage()) {
                        ImageRotateUtil.of().correctImage(contextWrap.getActivity(), outPutUri);
                    }
                    try {
                        takeResult(TResult.of(TImage.of(TUriParse.getFilePathWithUri(outPutUri, contextWrap.getActivity()), fromType)));
                    } catch (TException e) {
                        takeResult(TResult.of(TImage.of(outPutUri, fromType)), e.getDetailMessage());
                        e.printStackTrace();
                    }
                } else {
                    listener.takeCancel();
                }
                break;
            case TConstant.RC_CROP://裁剪照片返回结果
            case Crop.REQUEST_CROP://裁剪照片返回结果
                if (resultCode == Activity.RESULT_OK) {
                    if (multipleCrop != null) {
                        cropContinue(true);
                    } else {
                        try {
                            TImage image = TImage.of(TUriParse.getFilePathWithUri(outPutUri, contextWrap.getActivity()), fromType);
                            image.setCropped(true);
                            takeResult(TResult.of(image));
                        } catch (TException e) {
                            takeResult(TResult.of(TImage.of(outPutUri.getPath(), fromType)), e.getDetailMessage());
                            e.printStackTrace();
                        }
                    }
                } else if (resultCode == Activity.RESULT_CANCELED) {//裁剪的照片没有保存
                    if (multipleCrop != null) {
                        if (data != null) {
                            Bitmap bitmap = data.getParcelableExtra("data");//获取裁剪的结果数据
                            TImageFiles.writeToFile(bitmap, outPutUri);//将裁剪的结果写入到文件
                            cropContinue(true);
                        } else {
                            cropContinue(false);
                        }
                    } else {
                        if (data != null) {
                            Bitmap bitmap = data.getParcelableExtra("data");//获取裁剪的结果数据
                            TImageFiles.writeToFile(bitmap, outPutUri);//将裁剪的结果写入到文件

                            TImage image = TImage.of(outPutUri.getPath(), fromType);
                            image.setCropped(true);
                            takeResult(TResult.of(image));
                        } else {
                            listener.takeCancel();
                        }
                    }
                } else {
                    if (multipleCrop != null) {
                        cropContinue(false);
                    } else {
                        listener.takeCancel();
                    }
                }
                break;
            case TConstant.RC_PICK_MULTIPLE://多选图片返回结果
                if (resultCode == Activity.RESULT_OK && data != null) {
                    ArrayList<Image> images = data.getParcelableArrayListExtra(Constants.INTENT_EXTRA_IMAGES);
                    if (cropOptions != null) {
                        try {
                            onCrop(MultipleCrop.of(TUtils.convertImageToUri(contextWrap.getActivity(), images), contextWrap.getActivity(),
                                fromType), cropOptions);
                        } catch (TException e) {
                            cropContinue(false);
                            e.printStackTrace();
                        }
                    } else {
                        takeResult(TResult.of(TUtils.getTImagesWithImages(images, fromType)));
                    }

                } else {
                    listener.takeCancel();
                }
                break;
            default:
                break;
        }
    }

    @Override
    public void onPickMultiple(int limit) {
        if (PermissionManager.TPermissionType.WAIT.equals(permissionType)) {
            return;
        }
        TUtils.startActivityForResult(contextWrap,
            new TIntentWap(IntentUtils.getPickMultipleIntent(contextWrap, limit), TConstant.RC_PICK_MULTIPLE));
    }

    @Override
    public void onPickMultipleWithCrop(int limit, CropOptions options) {
        this.fromType = TImage.FromType.OTHER;
        onPickMultiple(limit);
        this.cropOptions = options;
    }

    /**
     * -----crop------
     **/
    @Override
    public void onCrop(Uri imageUri, Uri outPutUri, CropOptions options) throws TException {
        if (PermissionManager.TPermissionType.WAIT.equals(permissionType)) {
            return;
        }
        this.outPutUri = outPutUri;
        if (!TImageFiles.checkMimeType(contextWrap.getActivity(), TImageFiles.getMimeType(contextWrap.getActivity(), imageUri))) {
            Toast.makeText(contextWrap.getActivity(), contextWrap.getActivity().getResources().getText(org.devio.takephoto.R.string.tip_type_not_image),
                Toast.LENGTH_SHORT).show();
            throw new TException(TExceptionType.TYPE_NOT_IMAGE);
        }
        cropWithNonException(imageUri, outPutUri, options);
    }

    @Override
    public void onCrop(MultipleCrop multipleCrop, CropOptions options) throws TException {
        this.multipleCrop = multipleCrop;
        onCrop(multipleCrop.getUris().get(0), multipleCrop.getOutUris().get(0), options);
    }

    private void cropWithNonException(Uri imageUri, Uri outPutUri, CropOptions options) {
        this.outPutUri = outPutUri;
        if (options.isWithOwnCrop()) {
            TUtils.cropWithOwnApp(contextWrap, imageUri, outPutUri, options);
        } else {
            TUtils.cropWithOtherAppBySafely(contextWrap, imageUri, outPutUri, options);
        }
    }

    private void cropContinue(boolean preSuccess) {
        Map result = multipleCrop.setCropWithUri(outPutUri, preSuccess);
        int index = (int) result.get("index");
        boolean isLast = (boolean) result.get("isLast");

        if (isLast) {
            if (preSuccess) {
                takeResult(TResult.of(multipleCrop.gettImages()));
            } else {
                takeResult(TResult.of(multipleCrop.gettImages()),
                    outPutUri.getPath() + contextWrap.getActivity().getResources().getString(org.devio.takephoto.R.string.msg_crop_canceled));
            }
        } else {
            cropWithNonException(multipleCrop.getUris().get(index + 1), multipleCrop.getOutUris().get(index + 1), cropOptions);
        }
    }

    @Override
    public void onPickFromDocuments() {
        selectPicture(0, false);
    }

    @Override
    public void onPickFromGallery() {
        selectPicture(1, false);
    }

    private void selectPicture(int defaultIndex, boolean isCrop) {
        this.fromType = TImage.FromType.OTHER;
        if (takePhotoOptions != null && takePhotoOptions.isWithOwnGallery()) {
            onPickMultiple(1);
            return;
        }
        if (PermissionManager.TPermissionType.WAIT.equals(permissionType)) {
            return;
        }
        ArrayList<TIntentWap> intentWapList = new ArrayList<>();
        intentWapList.add(new TIntentWap(IntentUtils.getPickIntentWithDocuments(),
            isCrop ? TConstant.RC_PICK_PICTURE_FROM_DOCUMENTS_CROP : TConstant.RC_PICK_PICTURE_FROM_DOCUMENTS_ORIGINAL));
        intentWapList.add(new TIntentWap(IntentUtils.getPickIntentWithGallery(),
            isCrop ? TConstant.RC_PICK_PICTURE_FROM_GALLERY_CROP : TConstant.RC_PICK_PICTURE_FROM_GALLERY_ORIGINAL));
        try {
            TUtils.sendIntentBySafely(contextWrap, intentWapList, defaultIndex, isCrop);
        } catch (TException e) {
            takeResult(TResult.of(TImage.of("", fromType)), e.getDetailMessage());
            e.printStackTrace();
        }
    }

    @Override
    public void onPickFromGalleryWithCrop(Uri outPutUri, CropOptions options) {
        this.cropOptions = options;
        this.outPutUri = outPutUri;
        selectPicture(1, true);
    }

    @Override
    public void onPickFromDocumentsWithCrop(Uri outPutUri, CropOptions options) {
        this.cropOptions = options;
        this.outPutUri = outPutUri;
        selectPicture(0, true);
    }

    @Override
    public void onPickFromCapture(Uri outPutUri) {
        this.fromType = TImage.FromType.CAMERA;
        if (PermissionManager.TPermissionType.WAIT.equals(permissionType)) {
            return;
        }
        if (Build.VERSION.SDK_INT >= 23) {
            this.outPutUri = TUriParse.convertFileUriToFileProviderUri(contextWrap.getActivity(), outPutUri);
        } else {
            this.outPutUri = outPutUri;
        }

        try {
            TUtils.captureBySafely(contextWrap,
                new TIntentWap(IntentUtils.getCaptureIntent(this.outPutUri), TConstant.RC_PICK_PICTURE_FROM_CAPTURE));
        } catch (TException e) {
            takeResult(TResult.of(TImage.of("", fromType)), e.getDetailMessage());
            e.printStackTrace();
        }
    }

    @Override
    public void onPickFromCaptureWithCrop(Uri outPutUri, CropOptions options) {
        this.fromType = TImage.FromType.CAMERA;
        if (PermissionManager.TPermissionType.WAIT.equals(permissionType)) {
            return;
        }
        this.cropOptions = options;
        this.outPutUri = outPutUri;
        if (Build.VERSION.SDK_INT >= 23) {
            this.tempUri = TUriParse.getTempUri(contextWrap.getActivity());
        } else {
            this.tempUri = outPutUri;
        }

        try {
            TUtils.captureBySafely(contextWrap,
                new TIntentWap(IntentUtils.getCaptureIntent(this.tempUri), TConstant.RC_PICK_PICTURE_FROM_CAPTURE_CROP));
        } catch (TException e) {
            takeResult(TResult.of(TImage.of("", fromType)), e.getDetailMessage());
            e.printStackTrace();
        }
    }

    @Override
    public void onEnableCompress(CompressConfig config, boolean showCompressDialog) {
        this.compressConfig = config;
        this.showCompressDialog = showCompressDialog;
    }

    @Override
    public void setTakePhotoOptions(TakePhotoOptions options) {
        this.takePhotoOptions = options;
    }

    @Override
    public void permissionNotify(PermissionManager.TPermissionType type) {
        this.permissionType = type;
    }

    private void takeResult(final TResult result, final String... message) {
        if (null == compressConfig) {
            handleTakeCallBack(result, message);
        } else {
            if (showCompressDialog) {
                wailLoadDialog = TUtils.showProgressDialog(contextWrap.getActivity(),
                    contextWrap.getActivity().getResources().getString(org.devio.takephoto.R.string.tip_compress));
            }

            CompressImageImpl.of(contextWrap.getActivity(), compressConfig, result.getImages(), new CompressImage.CompressListener() {
                @Override
                public void onCompressSuccess(ArrayList<TImage> images) {
                    if (!compressConfig.isEnableReserveRaw()) {
                        deleteRawFile(images);
                    }
                    handleTakeCallBack(result);
                    if (wailLoadDialog != null && !contextWrap.getActivity().isFinishing()) {
                        wailLoadDialog.dismiss();
                    }
                }

                @Override
                public void onCompressFailed(ArrayList<TImage> images, String msg) {
                    if (!compressConfig.isEnableReserveRaw()) {
                        deleteRawFile(images);
                    }
                    handleTakeCallBack(TResult.of(images),
                        String.format(contextWrap.getActivity().getResources().getString(org.devio.takephoto.R.string.tip_compress_failed),
                            message.length > 0 ? message[0] : "", msg, result.getImage().getCompressPath()));
                    if (wailLoadDialog != null && !contextWrap.getActivity().isFinishing()) {
                        wailLoadDialog.dismiss();
                    }
                }
            }).compress();
        }
    }

    private void deleteRawFile(ArrayList<TImage> images) {
        for (TImage image : images) {
            if (TImage.FromType.CAMERA == fromType) {
                TFileUtils.delete(image.getOriginalPath());
                image.setOriginalPath("");
            }
        }
    }

    private void handleTakeCallBack(final TResult result, String... message) {
        if (message.length > 0) {
            listener.takeFail(result, message[0]);
        } else if (multipleCrop != null && multipleCrop.hasFailed) {
            listener.takeFail(result, contextWrap.getActivity().getResources().getString(org.devio.takephoto.R.string.msg_crop_failed));
        } else if (compressConfig != null) {
            boolean hasFailed = false;
            for (TImage image : result.getImages()) {
                if (image == null || !image.isCompressed()) {
                    hasFailed = true;
                    break;
                }
            }
            if (hasFailed) {
                listener.takeFail(result, contextWrap.getActivity().getString(org.devio.takephoto.R.string.msg_compress_failed));
            } else {
                listener.takeSuccess(result);
            }
        } else {
            listener.takeSuccess(result);
        }
        clearParams();
    }

    private void clearParams() {
        compressConfig = null;
        takePhotoOptions = null;
        cropOptions = null;
        multipleCrop = null;
    }
}

================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/compress/CompressConfig.java
================================================
package org.devio.takephoto.compress;


import org.devio.takephoto.model.LubanOptions;

import java.io.Serializable;

/**
 * 压缩配置类
 * Author: JPH
 * Date: 2016/6/7 0007 18:01
 */
public class CompressConfig implements Serializable {

    /**
     * 长或宽不超过的最大像素,单位px
     */
    private int maxPixel = 1200;
    /**
     * 压缩到的最大大小,单位B
     */
    private int maxSize = 100 * 1024;

    /**
     * 是否启用像素压缩
     */
    private boolean enablePixelCompress = true;
    /**
     * 是否启用质量压缩
     */
    private boolean enableQualityCompress = true;

    /**
     * 是否保留原文件
     */
    private boolean enableReserveRaw = true;

    /**
     * Luban压缩配置
     */
    private LubanOptions lubanOptions;

    public static CompressConfig ofDefaultConfig() {
        return new CompressConfig();
    }

    public static CompressConfig ofLuban(LubanOptions options) {
        return new CompressConfig(options);
    }

    private CompressConfig() {
    }

    private CompressConfig(LubanOptions options) {
        this.lubanOptions = options;
    }

    public LubanOptions getLubanOptions() {
        return lubanOptions;
    }

    public int getMaxPixel() {
        return maxPixel;
    }

    public CompressConfig setMaxPixel(int maxPixel) {
        this.maxPixel = maxPixel;
        return this;
    }

    public int getMaxSize() {
        return maxSize;
    }

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

    public boolean isEnablePixelCompress() {
        return enablePixelCompress;
    }

    public void enablePixelCompress(boolean enablePixelCompress) {
        this.enablePixelCompress = enablePixelCompress;
    }

    public boolean isEnableQualityCompress() {
        return enableQualityCompress;
    }

    public void enableQualityCompress(boolean enableQualityCompress) {
        this.enableQualityCompress = enableQualityCompress;
    }

    public boolean isEnableReserveRaw() {
        return enableReserveRaw;
    }

    public void enableReserveRaw(boolean enableReserveRaw) {
        this.enableReserveRaw = enableReserveRaw;
    }

    public static class Builder {
        private CompressConfig config;

        public Builder() {
            config = new CompressConfig();
        }

        public Builder setMaxSize(int maxSize) {
            config.setMaxSize(maxSize);
            return this;
        }

        public Builder setMaxPixel(int maxPixel) {
            config.setMaxPixel(maxPixel);
            return this;
        }

        public Builder enablePixelCompress(boolean enablePixelCompress) {
            config.enablePixelCompress(enablePixelCompress);
            return this;
        }

        public Builder enableQualityCompress(boolean enableQualityCompress) {
            config.enableQualityCompress(enableQualityCompress);
            return this;
        }

        public Builder enableReserveRaw(boolean enableReserveRaw) {
            config.enableReserveRaw(enableReserveRaw);
            return this;
        }

        public CompressConfig create() {
            return config;
        }
    }
}



================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/compress/CompressImage.java
================================================
package org.devio.takephoto.compress;

import org.devio.takephoto.model.TImage;

import java.util.ArrayList;

/**
 * 压缩照片2.0
 * <p>
 * Author JPH
 * Date 2015-08-26 下午1:44:26
 */
public interface CompressImage {
    void compress();

    /**
     * 压缩结果监听器
     */
    interface CompressListener {
        /**
         * 压缩成功
         *
         * @param images 已经压缩图片
         */
        void onCompressSuccess(ArrayList<TImage> images);

        /**
         * 压缩失败
         *
         * @param images 压缩失败的图片
         * @param msg    失败的原因
         */
        void onCompressFailed(ArrayList<TImage> images, String msg);
    }
}


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/compress/CompressImageImpl.java
================================================
package org.devio.takephoto.compress;

import android.content.Context;
import android.text.TextUtils;

import org.devio.takephoto.model.TImage;

import java.io.File;
import java.util.ArrayList;

/**
 * 压缩照片
 * <p>
 * Date: 2016/9/21 0007 20:10
 * Version:3.0.0
 * 技术博文:http://www.devio.org
 * GitHub:https://github.com/crazycodeboy
 * Email:crazycodeboy@gmail.com
 */
public class CompressImageImpl implements CompressImage {
    private CompressImageUtil compressImageUtil;
    private ArrayList<TImage> images;
    private CompressImage.CompressListener listener;

    public static CompressImage of(Context context, CompressConfig config, ArrayList<TImage> images,
        CompressImage.CompressListener listener) {
        if (config.getLubanOptions() != null) {
            return new CompressWithLuBan(context, config, images, listener);
        } else {
            return new CompressImageImpl(context, config, images, listener);
        }
    }

    private CompressImageImpl(Context context, CompressConfig config, ArrayList<TImage> images, CompressImage.CompressListener listener) {
        compressImageUtil = new CompressImageUtil(context, config);
        this.images = images;
        this.listener = listener;
    }

    @Override
    public void compress() {
        if (images == null || images.isEmpty()) {
            listener.onCompressFailed(images, " images is null");
        }
        for (TImage image : images) {
            if (image == null) {
                listener.onCompressFailed(images, " There are pictures of compress  is null.");
                return;
            }
        }
        compress(images.get(0));
    }

    private void compress(final TImage image) {
        if (TextUtils.isEmpty(image.getOriginalPath())) {
            continueCompress(image, false);
            return;
        }

        File file = new File(image.getOriginalPath());
        if (file == null || !file.exists() || !file.isFile()) {
            continueCompress(image, false);
            return;
        }

        compressImageUtil.compress(image.getOriginalPath(), new CompressImageUtil.CompressListener() {
            @Override
            public void onCompressSuccess(String imgPath) {
                image.setCompressPath(imgPath);
                continueCompress(image, true);
            }

            @Override
            public void onCompressFailed(String imgPath, String msg) {
                continueCompress(image, false, msg);
            }
        });
    }

    private void continueCompress(TImage image, boolean preSuccess, String... message) {
        image.setCompressed(preSuccess);
        int index = images.indexOf(image);
        boolean isLast = index == images.size() - 1;
        if (isLast) {
            handleCompressCallBack(message);
        } else {
            compress(images.get(index + 1));
        }
    }

    private void handleCompressCallBack(String... message) {
        if (message.length > 0) {
            listener.onCompressFailed(images, message[0]);
            return;
        }

        for (TImage image : images) {
            if (!image.isCompressed()) {
                listener.onCompressFailed(images, image.getCompressPath() + " is compress failures");
                return;
            }
        }
        listener.onCompressSuccess(images);
    }
}


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/compress/CompressImageUtil.java
================================================
package org.devio.takephoto.compress;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.os.Handler;

import org.devio.takephoto.uitl.TFileUtils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

/**
 * 压缩照片
 *
 * @author JPH
 *         Date 2015-08-26 下午1:44:26
 *         Version:1.0.3
 */
public class CompressImageUtil {
    private CompressConfig config;
    private Context context;
    Handler mhHandler = new Handler();

    public CompressImageUtil(Context context, CompressConfig config) {
        this.context = context;
        this.config = config == null ? CompressConfig.ofDefaultConfig() : config;
    }

    public void compress(String imagePath, CompressListener listener) {
        if (config.isEnablePixelCompress()) {
            try {
                compressImageByPixel(imagePath, listener);
            } catch (FileNotFoundException e) {
                listener.onCompressFailed(imagePath, String.format("图片压缩失败,%s", e.toString()));
                e.printStackTrace();
            }
        } else {
            compressImageByQuality(BitmapFactory.decodeFile(imagePath), imagePath, listener);
        }
    }

    /**
     * 多线程压缩图片的质量
     *
     * @param bitmap  内存中的图片
     * @param imgPath 图片的保存路径
     * @author JPH
     * @date 2014-12-5下午11:30:43
     */
    private void compressImageByQuality(final Bitmap bitmap, final String imgPath, final CompressListener listener) {
        if (bitmap == null) {
            sendMsg(false, imgPath, "像素压缩失败,bitmap is null", listener);
            return;
        }
        new Thread(new Runnable() {//开启多线程进行压缩处理
            @Override
            public void run() {
                // TODO Auto-generated method stub
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                int options = 100;
                bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);//质量压缩方法,把压缩后的数据存放到baos中 (100表示不压缩,0表示压缩到最小)
                while (baos.toByteArray().length > config.getMaxSize()) {//循环判断如果压缩后图片是否大于指定大小,大于继续压缩
                    baos.reset();//重置baos即让下一次的写入覆盖之前的内容
                    options -= 5;//图片质量每次减少5
                    if (options <= 5) {
                        options = 5;//如果图片质量小于5,为保证压缩后的图片质量,图片最底压缩质量为5
                    }
                    bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);//将压缩后的图片保存到baos中
                    if (options == 5) {
                        break;//如果图片的质量已降到最低则,不再进行压缩
                    }
                }
                //				if(bitmap!=null&&!bitmap.isRecycled()){
                //					bitmap.recycle();//回收内存中的图片
                //				}
                try {
                    File thumbnailFile = getThumbnailFile(new File(imgPath));
                    FileOutputStream fos = new FileOutputStream(thumbnailFile);//将压缩后的图片保存的本地上指定路径中
                    fos.write(baos.toByteArray());
                    fos.flush();
                    fos.close();
                    sendMsg(true, thumbnailFile.getPath(), null, listener);
                } catch (Exception e) {
                    sendMsg(false, imgPath, "质量压缩失败", listener);
                    e.printStackTrace();
                }
            }
        }).start();
    }

    /**
     * 按比例缩小图片的像素以达到压缩的目的
     *
     * @param imgPath
     * @return
     * @author JPH
     * @date 2014-12-5下午11:30:59
     */
    private void compressImageByPixel(String imgPath, CompressListener listener) throws FileNotFoundException {
        if (imgPath == null) {
            sendMsg(false, imgPath, "要压缩的文件不存在", listener);
            return;
        }
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        newOpts.inJustDecodeBounds = true;//只读边,不读内容
        BitmapFactory.decodeFile(imgPath, newOpts);
        newOpts.inJustDecodeBounds = false;
        int width = newOpts.outWidth;
        int height = newOpts.outHeight;
        float maxSize = config.getMaxPixel();
        int be = 1;
        if (width >= height && width > maxSize) {//缩放比,用高或者宽其中较大的一个数据进行计算
            be = (int) (newOpts.outWidth / maxSize);
            be++;
        } else if (width < height && height > maxSize) {
            be = (int) (newOpts.outHeight / maxSize);
            be++;
        }
        newOpts.inSampleSize = be;//设置采样率
        newOpts.inPreferredConfig = Config.ARGB_8888;//该模式是默认的,可不设
        newOpts.inPurgeable = true;// 同时设置才会有效
        newOpts.inInputShareable = true;//。当系统内存不够时候图片自动被回收
        Bitmap bitmap = BitmapFactory.decodeFile(imgPath, newOpts);
        if (config.isEnableQualityCompress()) {
            compressImageByQuality(bitmap, imgPath, listener);//压缩好比例大小后再进行质量压缩
        } else {
            File thumbnailFile = getThumbnailFile(new File(imgPath));
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(thumbnailFile));

            listener.onCompressSuccess(thumbnailFile.getPath());
        }
    }

    /**
     * 发送压缩结果的消息
     *
     * @param isSuccess 压缩是否成功
     * @param imagePath
     * @param message
     */
    private void sendMsg(final boolean isSuccess, final String imagePath, final String message, final CompressListener listener) {
        mhHandler.post(new Runnable() {
            @Override
            public void run() {
                if (isSuccess) {
                    listener.onCompressSuccess(imagePath);
                } else {
                    listener.onCompressFailed(imagePath, message);
                }
            }
        });
    }

    private File getThumbnailFile(File file) {
        if (file == null || !file.exists()) {
            return file;
        }
        return TFileUtils.getPhotoCacheDir(context, file);
    }

    /**
     * 压缩结果监听器
     */
    public interface CompressListener {
        /**
         * 压缩成功
         *
         * @param imgPath 压缩图片的路径
         */
        void onCompressSuccess(String imgPath);

        /**
         * 压缩失败
         *
         * @param imgPath 压缩失败的图片
         * @param msg     失败的原因
         */
        void onCompressFailed(String imgPath, String msg);
    }
}


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/compress/CompressWithLuBan.java
================================================
package org.devio.takephoto.compress;

import android.content.Context;

import org.devio.takephoto.model.LubanOptions;
import org.devio.takephoto.model.TImage;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import me.shaohui.advancedluban.Luban;
import me.shaohui.advancedluban.OnCompressListener;
import me.shaohui.advancedluban.OnMultiCompressListener;

/**
 * 压缩照片,采用luban
 * Author: crazycodeboy
 * Date: 2016/11/5 0007 20:10
 * Version:4.0.0
 * 技术博文:http://www.devio.org/
 * GitHub:https://github.com/crazycodeboy
 * Email:crazycodeboy@gmail.com
 */
public class CompressWithLuBan implements CompressImage {
    private ArrayList<TImage> images;
    private CompressListener listener;
    private Context context;
    private LubanOptions options;
    private ArrayList<File> files = new ArrayList<>();

    public CompressWithLuBan(Context context, CompressConfig config, ArrayList<TImage> images, CompressListener listener) {
        options = config.getLubanOptions();
        this.images = images;
        this.listener = listener;
        this.context = context;
    }

    @Override
    public void compress() {
        if (images == null || images.isEmpty()) {
            listener.onCompressFailed(images, " images is null");
            return;
        }
        for (TImage image : images) {
            if (image == null) {
                listener.onCompressFailed(images, " There are pictures of compress  is null.");
                return;
            }
            files.add(new File(image.getOriginalPath()));
        }
        if (images.size() == 1) {
            compressOne();
        } else {
            compressMulti();
        }
    }

    private void compressOne() {
        Luban.compress(context, files.get(0))
            .putGear(Luban.CUSTOM_GEAR)
            .setMaxHeight(options.getMaxHeight())
            .setMaxWidth(options.getMaxWidth())
            .setMaxSize(options.getMaxSize() / 1000)
            .launch(new OnCompressListener() {
                @Override
                public void onStart() {

                }

                @Override
                public void onSuccess(File file) {
                    TImage image = images.get(0);
                    image.setCompressPath(file.getPath());
                    image.setCompressed(true);
                    listener.onCompressSuccess(images);
                }

                @Override
                public void onError(Throwable e) {
                    listener.onCompressFailed(images, e.getMessage() + " is compress failures");
                }
            });
    }

    private void compressMulti() {
        Luban.compress(context, files)
            .putGear(Luban.CUSTOM_GEAR)
            .setMaxSize(options.getMaxSize() / 1000)                // limit the final image size(unit:Kb)
            .setMaxHeight(options.getMaxHeight())             // limit image height
            .setMaxWidth(options.getMaxWidth())
            .launch(new OnMultiCompressListener() {
                @Override
                public void onStart() {

                }

                @Override
                public void onSuccess(List<File> fileList) {
                    handleCompressCallBack(fileList);
                }

                @Override
                public void onError(Throwable e) {
                    listener.onCompressFailed(images, e.getMessage() + " is compress failures");
                }
            });
    }

    private void handleCompressCallBack(List<File> files) {
        for (int i = 0, j = images.size(); i < j; i++) {
            TImage image = images.get(i);
            image.setCompressed(true);
            image.setCompressPath(files.get(i).getPath());
        }
        listener.onCompressSuccess(images);
    }
}


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/model/CropOptions.java
================================================
package org.devio.takephoto.model;

import java.io.Serializable;

/**
 * 裁剪配置类
 * Author: JPH
 * Date: 2016/7/27 13:19
 */
public class CropOptions implements Serializable {
    /**
     * 使用TakePhoto自带的裁切工具进行裁切
     */
    private boolean withOwnCrop;
    private int aspectX;
    private int aspectY;
    private int outputX;
    private int outputY;

    private CropOptions() {
    }

    public int getAspectX() {
        return aspectX;
    }

    public void setAspectX(int aspectX) {
        this.aspectX = aspectX;
    }

    public int getAspectY() {
        return aspectY;
    }

    public void setAspectY(int aspectY) {
        this.aspectY = aspectY;
    }

    public int getOutputX() {
        return outputX;
    }

    public void setOutputX(int outputX) {
        this.outputX = outputX;
    }

    public int getOutputY() {
        return outputY;
    }

    public void setOutputY(int outputY) {
        this.outputY = outputY;
    }

    public boolean isWithOwnCrop() {
        return withOwnCrop;
    }

    public void setWithOwnCrop(boolean withOwnCrop) {
        this.withOwnCrop = withOwnCrop;
    }

    public static class Builder {
        private CropOptions options;

        public Builder() {
            options = new CropOptions();
        }

        public Builder setAspectX(int aspectX) {
            options.setAspectX(aspectX);
            return this;
        }

        public Builder setAspectY(int aspectY) {
            options.setAspectY(aspectY);
            return this;
        }

        public Builder setOutputX(int outputX) {
            options.setOutputX(outputX);
            return this;
        }

        public Builder setOutputY(int outputY) {
            options.setOutputY(outputY);
            return this;
        }

        public Builder setWithOwnCrop(boolean withOwnCrop) {
            options.setWithOwnCrop(withOwnCrop);
            return this;
        }

        public CropOptions create() {
            return options;
        }
    }
}


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/model/InvokeParam.java
================================================
package org.devio.takephoto.model;

import java.lang.reflect.Method;

/**
 * Created by penn on 16/9/22.
 */
public class InvokeParam {
    private Object proxy;
    private Method method;
    private Object[] args;

    public InvokeParam(Object proxy, Method method, Object[] args) {
        this.proxy = proxy;
        this.method = method;
        this.args = args;
    }

    public Object getProxy() {
        return proxy;
    }

    public void setProxy(Object proxy) {
        this.proxy = proxy;
    }

    public Method getMethod() {
        return method;
    }

    public void setMethod(Method method) {
        this.method = method;
    }

    public Object[] getArgs() {
        return args;
    }

    public void setArgs(Object[] args) {
        this.args = args;
    }
}


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/model/LubanOptions.java
================================================
package org.devio.takephoto.model;

import java.io.Serializable;

/**
 * Luban配置类
 * Author: crazycodeboy
 * Date: 2016/11/5 0007 20:10
 * Version:4.0.1
 * 技术博文:http://www.devio.org/
 * GitHub:https://github.com/crazycodeboy
 * Email:crazycodeboy@gmail.com
 */
public class LubanOptions implements Serializable {
    /**
     * 压缩到的最大大小,单位B
     */
    private int maxSize;
    private int maxHeight;
    private int maxWidth;

    private LubanOptions() {
    }

    public int getMaxSize() {
        return maxSize;
    }

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

    public int getMaxHeight() {
        return maxHeight;
    }

    public void setMaxHeight(int maxHeight) {
        this.maxHeight = maxHeight;
    }

    public int getMaxWidth() {
        return maxWidth;
    }

    public void setMaxWidth(int maxWidth) {
        this.maxWidth = maxWidth;
    }

    public static class Builder {
        private LubanOptions options;

        public Builder() {
            options = new LubanOptions();
        }

        public Builder setMaxSize(int maxSize) {
            options.setMaxSize(maxSize);
            return this;
        }

        public Builder setMaxHeight(int maxHeight) {
            options.setMaxHeight(maxHeight);
            return this;
        }

        public Builder setMaxWidth(int maxWidth) {
            options.setMaxWidth(maxWidth);
            return this;
        }

        public LubanOptions create() {
            return options;
        }
    }
}


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/model/MultipleCrop.java
================================================
package org.devio.takephoto.model;

import android.app.Activity;
import android.net.Uri;

import org.devio.takephoto.uitl.TImageFiles;
import org.devio.takephoto.uitl.TUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * Author: JPH
 * Date: 2016/8/11 17:01
 */
public class MultipleCrop {
    private ArrayList<Uri> uris;
    private ArrayList<Uri> outUris;
    private ArrayList<TImage> tImages;
    private TImage.FromType fromType;
    public boolean hasFailed;//是否有裁切失败的标识

    public static MultipleCrop of(ArrayList<Uri> uris, Activity activity, TImage.FromType fromType) throws TException {
        return new MultipleCrop(uris, activity, fromType);
    }

    public static MultipleCrop of(ArrayList<Uri> uris, ArrayList<Uri> outUris, TImage.FromType fromType) {
        return new MultipleCrop(uris, outUris, fromType);
    }

    private MultipleCrop(ArrayList<Uri> uris, Activity activity, TImage.FromType fromType) throws TException {
        this.uris = uris;
        ArrayList<Uri> outUris = new ArrayList<>();
        for (Uri uri : uris) {
            outUris.add(Uri.fromFile(TImageFiles.getTempFile(activity, uri)));//生成临时裁切输出路径
        }
        this.outUris = outUris;
        this.tImages = TUtils.getTImagesWithUris(outUris, fromType);
        this.fromType = fromType;
    }

    private MultipleCrop(ArrayList<Uri> uris, ArrayList<Uri> outUris, TImage.FromType fromType) {
        this.uris = uris;
        this.outUris = outUris;
        this.tImages = TUtils.getTImagesWithUris(outUris, fromType);
        this.fromType = fromType;
    }

    public ArrayList<Uri> getUris() {
        return uris;
    }

    public void setUris(ArrayList<Uri> uris) {
        this.uris = uris;
    }

    public ArrayList<Uri> getOutUris() {
        return outUris;
    }

    public void setOutUris(ArrayList<Uri> outUris) {
        this.outUris = outUris;
    }

    public ArrayList<TImage> gettImages() {
        return tImages;
    }

    public void settImages(ArrayList<TImage> tImages) {
        this.tImages = tImages;
    }

    /**
     * 为被裁切的图片设置已被裁切的标识
     *
     * @param uri 被裁切的图片
     * @return 该图片是否是最后一张
     */
    public Map setCropWithUri(Uri uri, boolean cropped) {
        if (!cropped) {
            hasFailed = true;
        }
        int index = outUris.indexOf(uri);
        tImages.get(index).setCropped(cropped);
        Map result = new HashMap();
        result.put("index", index);
        result.put("isLast", index == outUris.size() - 1 ? true : false);
        return result;
    }
}


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/model/TContextWrap.java
================================================
package org.devio.takephoto.model;

import android.app.Activity;
import android.support.v4.app.Fragment;

/**
 * Author: JPH
 * Date: 2016/8/11 17:01
 */
public class TContextWrap {
    private Activity activity;
    private Fragment fragment;

    public static TContextWrap of(Activity activity) {
        return new TContextWrap(activity);
    }

    public static TContextWrap of(Fragment fragment) {
        return new TContextWrap(fragment);
    }

    private TContextWrap(Activity activity) {
        this.activity = activity;
    }

    private TContextWrap(Fragment fragment) {
        this.fragment = fragment;
        this.activity = fragment.getActivity();
    }

    public Activity getActivity() {
        return activity;
    }

    public void setActivity(Activity activity) {
        this.activity = activity;
    }

    public Fragment getFragment() {
        return fragment;
    }

    public void setFragment(Fragment fragment) {
        this.fragment = fragment;
    }
}


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/model/TException.java
================================================
package org.devio.takephoto.model;

/**
 * Author: JPH
 * Date: 2016/7/26 10:53
 */
public class TException extends Exception {
    String detailMessage;

    public TException(TExceptionType exceptionType) {
        super(exceptionType.getStringValue());
        this.detailMessage = exceptionType.getStringValue();
    }

    public String getDetailMessage() {
        return detailMessage;
    }
}


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/model/TExceptionType.java
================================================
package org.devio.takephoto.model;

/**
 * Author: JPH
 * Date: 2016/7/26 11:01
 */
public enum TExceptionType {
    TYPE_NOT_IMAGE("选择的文件不是图片"), TYPE_WRITE_FAIL("保存选择的的文件失败"), TYPE_URI_NULL("所选照片的Uri 为null"), TYPE_URI_PARSE_FAIL("从Uri中获取文件路径失败"),
    TYPE_NO_MATCH_PICK_INTENT("没有匹配到选择图片的Intent"), TYPE_NO_MATCH_CROP_INTENT("没有匹配到裁切图片的Intent"), TYPE_NO_CAMERA("没有相机"),
    TYPE_NO_FIND("选择的文件没有找到");

    String stringValue;

    TExceptionType(String stringValue) {
        this.stringValue = stringValue;
    }

    public String getStringValue() {
        return stringValue;
    }
}


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/model/TImage.java
================================================
package org.devio.takephoto.model;

import android.net.Uri;

import java.io.Serializable;

/**
 * TakePhoto 操作成功返回的处理结果
 * <p>
 * Author: JPH
 * Date: 2016/8/11 17:01
 */
public class TImage implements Serializable {
    private String originalPath;
    private String compressPath;
    private FromType fromType;
    private boolean cropped;
    private boolean compressed;

    public static TImage of(String path, FromType fromType) {
        return new TImage(path, fromType);
    }

    public static TImage of(Uri uri, FromType fromType) {
        return new TImage(uri, fromType);
    }

    private TImage(String path, FromType fromType) {
        this.originalPath = path;
        this.fromType = fromType;
    }

    private TImage(Uri uri, FromType fromType) {
        this.originalPath = uri.getPath();
        this.fromType = fromType;
    }

    public String getOriginalPath() {
        return originalPath;
    }

    public void setOriginalPath(String originalPath) {
        this.originalPath = originalPath;
    }

    public String getCompressPath() {
        return compressPath;
    }

    public void setCompressPath(String compressPath) {
        this.compressPath = compressPath;
    }

    public FromType getFromType() {
        return fromType;
    }

    public void setFromType(FromType fromType) {
        this.fromType = fromType;
    }

    public boolean isCropped() {
        return cropped;
    }

    public void setCropped(boolean cropped) {
        this.cropped = cropped;
    }

    public boolean isCompressed() {
        return compressed;
    }

    public void setCompressed(boolean compressed) {
        this.compressed = compressed;
    }

    public enum FromType {
        CAMERA, OTHER
    }
}


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/model/TIntentWap.java
================================================
package org.devio.takephoto.model;

import android.content.Intent;

/**
 * Author: JPH
 * Date: 2016/7/26 14:23
 */
public class TIntentWap {
    private Intent intent;
    private int requestCode;

    public TIntentWap() {
    }

    public TIntentWap(Intent intent, int requestCode) {
        this.intent = intent;
        this.requestCode = requestCode;
    }

    public Intent getIntent() {
        return intent;
    }

    public void setIntent(Intent intent) {
        this.intent = intent;
    }

    public int getRequestCode() {
        return requestCode;
    }

    public void setRequestCode(int requestCode) {
        this.requestCode = requestCode;
    }
}


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/model/TResult.java
================================================
package org.devio.takephoto.model;

import java.util.ArrayList;

/**
 * TakePhoto 操作成功返回的处理结果
 * Author: JPH
 * Date: 2016/8/11 17:01
 */
public class TResult {
    private ArrayList<TImage> images;
    private TImage image;

    public static TResult of(TImage image) {
        ArrayList<TImage> images = new ArrayList<>(1);
        images.add(image);
        return new TResult(images);
    }

    public static TResult of(ArrayList<TImage> images) {
        return new TResult(images);
    }

    private TResult(ArrayList<TImage> images) {
        this.images = images;
        if (images != null && !images.isEmpty()) {
            this.image = images.get(0);
        }
    }

    public ArrayList<TImage> getImages() {
        return images;
    }

    public void setImages(ArrayList<TImage> images) {
        this.images = images;
    }

    public TImage getImage() {
        return image;
    }

    public void setImage(TImage image) {
        this.image = image;
    }
}


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/model/TakePhotoOptions.java
================================================
package org.devio.takephoto.model;

import java.io.Serializable;

/**
 * Author: crazycodeboy
 * Date: 2016/11/5 0007 20:10
 * Version:4.0.0
 * 技术博文:http://www.devio.org/
 * GitHub:https://github.com/crazycodeboy
 * Email:crazycodeboy@gmail.com
 */
public class TakePhotoOptions implements Serializable {
    /**
     * 是否使用TakePhoto自带的相册进行图片选择,默认不使用,但选择多张图片会使用
     */
    private boolean withOwnGallery;
    /**
     * 是对拍的照片进行旋转角度纠正
     */
    private boolean correctImage;

    private TakePhotoOptions() {
    }

    public boolean isWithOwnGallery() {
        return withOwnGallery;
    }

    public void setWithOwnGallery(boolean withOwnGallery) {
        this.withOwnGallery = withOwnGallery;
    }

    public boolean isCorrectImage() {
        return correctImage;
    }

    public void setCorrectImage(boolean correctImage) {
        this.correctImage = correctImage;
    }

    public static class Builder {
        private TakePhotoOptions options;

        public Builder() {
            this.options = new TakePhotoOptions();
        }

        public Builder setWithOwnGallery(boolean withOwnGallery) {
            options.setWithOwnGallery(withOwnGallery);
            return this;
        }

        public Builder setCorrectImage(boolean isCorrectImage) {
            options.setCorrectImage(isCorrectImage);
            return this;
        }

        public TakePhotoOptions create() {
            return options;
        }
    }
}


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/permission/InvokeListener.java
================================================
package org.devio.takephoto.permission;

import org.devio.takephoto.model.InvokeParam;

/**
 * 授权管理回调
 */
public interface InvokeListener {
    PermissionManager.TPermissionType invoke(InvokeParam invokeParam);
}


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/permission/PermissionManager.java
================================================
package org.devio.takephoto.permission;

import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.widget.Toast;

import org.devio.takephoto.app.TakePhoto;
import org.devio.takephoto.model.InvokeParam;
import org.devio.takephoto.model.TContextWrap;
import org.devio.takephoto.uitl.TConstant;

import java.lang.reflect.Method;
import java.util.ArrayList;

/**
 * Created by penn on 16/9/22.
 */
public class PermissionManager {
    public enum TPermission {
        STORAGE(Manifest.permission.WRITE_EXTERNAL_STORAGE), CAMERA(Manifest.permission.CAMERA);
        String stringValue;

        TPermission(String stringValue) {
            this.stringValue = stringValue;
        }

        public String stringValue() {
            return stringValue;
        }
    }


    public enum TPermissionType {
        GRANTED("已授权"), DENIED("未授权"), WAIT("等待授权"), NOT_NEED("无需授权"), ONLY_CAMERA_DENIED("没有拍照权限"), ONLY_STORAGE_DENIED("没有读写SD卡权限");
        String stringValue;

        TPermissionType(String stringValue) {
            this.stringValue = stringValue;
        }

        public String stringValue() {
            return stringValue;
        }
    }


    private final static String[] methodNames =
        {"onPickFromCapture", "onPickFromCaptureWithCrop", "onPickMultiple", "onPickMultipleWithCrop", "onPickFromDocuments",
            "onPickFromDocumentsWithCrop", "onPickFromGallery", "onPickFromGalleryWithCrop", "onCrop"};

    /**
     * 检查当前应用是否被授予相应权限
     *
     * @param contextWrap
     * @param method
     * @return
     */
    public static TPermissionType checkPermission(@NonNull TContextWrap contextWrap, @NonNull Method method) {
        String methodName = method.getName();
        boolean contain = false;
        for (int i = 0, j = methodNames.length; i < j; i++) {
            if (TextUtils.equals(methodName, methodNames[i])) {
                contain = true;
                break;
            }
        }
        if (!contain) {
            return TPermissionType.NOT_NEED;
        }

        boolean cameraGranted = true, storageGranted =
            ContextCompat.checkSelfPermission(contextWrap.getActivity(), TPermission.STORAGE.stringValue())
                == PackageManager.PERMISSION_GRANTED ? true : false;

        if (TextUtils.equals(methodName, "onPickFromCapture") || TextUtils.equals(methodName, "onPickFromCaptureWithCrop")) {
            cameraGranted = ContextCompat.checkSelfPermission(contextWrap.getActivity(), TPermission.CAMERA.stringValue())
                == PackageManager.PERMISSION_GRANTED ? true : false;
        }

        boolean granted = storageGranted && cameraGranted;
        if (!granted) {
            ArrayList<String> permissions = new ArrayList<>();
            if (!storageGranted) {
                permissions.add(TPermission.STORAGE.stringValue());
            }
            if (!cameraGranted) {
                permissions.add(TPermission.CAMERA.stringValue());
            }
            requestPermission(contextWrap, permissions.toArray(new String[permissions.size()]));
        }
        return granted ? TPermissionType.GRANTED : TPermissionType.WAIT;
    }

    public static void requestPermission(@NonNull TContextWrap contextWrap, @NonNull String[] permissions) {
        if (contextWrap.getFragment() != null) {
            contextWrap.getFragment().requestPermissions(permissions, TConstant.PERMISSION_REQUEST_TAKE_PHOTO);
        } else {
            ActivityCompat.requestPermissions(contextWrap.getActivity(), permissions, TConstant.PERMISSION_REQUEST_TAKE_PHOTO);
        }
    }

    public static TPermissionType onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode == TConstant.PERMISSION_REQUEST_TAKE_PHOTO) {
            boolean cameraGranted = true, storageGranted = true;
            for (int i = 0, j = permissions.length; i < j; i++) {
                if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                    if (TextUtils.equals(TPermission.STORAGE.stringValue(), permissions[i])) {
                        storageGranted = false;
                    } else if (TextUtils.equals(TPermission.CAMERA.stringValue(), permissions[i])) {
                        cameraGranted = false;
                    }
                }
            }
            if (cameraGranted && storageGranted) {
                return TPermissionType.GRANTED;
            }
            if (!cameraGranted && storageGranted) {
                return TPermissionType.ONLY_CAMERA_DENIED;
            }
            if (!storageGranted && cameraGranted) {
                return TPermissionType.ONLY_STORAGE_DENIED;
            }
            if (!storageGranted && !cameraGranted) {
                return TPermissionType.DENIED;
            }
        }
        return TPermissionType.WAIT;
    }

    public static void handlePermissionsResult(Activity activity, TPermissionType type, InvokeParam invokeParam,
        TakePhoto.TakeResultListener listener) {
        String tip = null;
        switch (type) {
            case DENIED:
                listener.takeFail(null, tip = activity.getResources().getString(org.devio.takephoto.R.string.tip_permission_camera_storage));
                break;
            case ONLY_CAMERA_DENIED:
                listener.takeFail(null, tip = activity.getResources().getString(org.devio.takephoto.R.string.tip_permission_camera));
                break;
            case ONLY_STORAGE_DENIED:
                listener.takeFail(null, tip = activity.getResources().getString(org.devio.takephoto.R.string.tip_permission_storage));
                break;
            case GRANTED:
                try {
                    invokeParam.getMethod().invoke(invokeParam.getProxy(), invokeParam.getArgs());
                } catch (Exception e) {
                    e.printStackTrace();
                    listener.takeFail(null, tip = activity.getResources().getString(org.devio.takephoto.R.string.tip_permission_camera_storage));
                }
                break;
            default:
                break;
        }
        if (tip != null) {
            Toast.makeText(activity, tip, Toast.LENGTH_LONG).show();
        }

    }
}


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/permission/TakePhotoInvocationHandler.java
================================================
package org.devio.takephoto.permission;

import org.devio.takephoto.app.TakePhoto;
import org.devio.takephoto.model.InvokeParam;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TakePhotoInvocationHandler implements InvocationHandler {
    private TakePhoto delegate;
    private InvokeListener listener;

    public static TakePhotoInvocationHandler of(InvokeListener listener) {
        return new TakePhotoInvocationHandler(listener);
    }

    private TakePhotoInvocationHandler(InvokeListener listener) {
        this.listener = listener;
    }

    /**
     * 绑定委托对象并返回一个代理类
     *
     * @param delegate
     * @return
     */
    public Object bind(TakePhoto delegate) {
        this.delegate = delegate;
        return Proxy.newProxyInstance(delegate.getClass().getClassLoader(), delegate.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        PermissionManager.TPermissionType type = listener.invoke(new InvokeParam(proxy, method, args));
        if (proxy instanceof TakePhoto) {
            if (!PermissionManager.TPermissionType.NOT_NEED.equals(type)) {
                ((TakePhoto) proxy).permissionNotify(type);
            }
        }
        return method.invoke(delegate, args);
    }
}

================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/uitl/ImageRotateUtil.java
================================================
package org.devio.takephoto.uitl;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.Uri;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 图片旋转角度修正工具类
 * Author: crazycodeboy
 * Date: 2016/9/21 0007 20:10
 * Version:3.0.0
 * 技术博文:http://www.devio.org
 * GitHub:https://github.com/crazycodeboy
 * Email:crazycodeboy@gmail.com
 */
public class ImageRotateUtil {

    public static ImageRotateUtil of() {
        return new ImageRotateUtil();
    }

    private ImageRotateUtil() {
    }

    /**
     * 纠正照片的旋转角度
     *
     * @param path
     */
    public void correctImage(Context context, Uri path) {

        String imagePath = TUriParse.parseOwnUri(context, path);
        int degree;
        if ((degree = getBitmapDegree(imagePath)) != 0) {
            Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
            if (bitmap == null) {
                return;
            }
            Bitmap resultBitmap = rotateBitmapByDegree(bitmap, degree);
            if (resultBitmap == null) {
                return;
            }
            try {
                resultBitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(new File(imagePath)));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (OutOfMemoryError e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 读取图片的旋转的角度
     *
     * @param path 图片绝对路径
     * @return 图片的旋转角度
     */
    private int getBitmapDegree(String path) {
        int degree = 0;
        try {
            // 从指定路径下读取图片,并获取其EXIF信息
            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;
    }

    /**
     * 将图片按照某个角度进行旋转
     *
     * @param bm     需要旋转的图片
     * @param degree 旋转角度
     * @return 旋转后的图片
     */
    private Bitmap rotateBitmapByDegree(Bitmap bm, int degree) {
        Bitmap returnBm = null;

        // 根据旋转角度,生成旋转矩阵
        Matrix matrix = new Matrix();
        matrix.postRotate(degree);
        try {
            // 将原始图片按照旋转矩阵进行旋转,并得到新的图片
            returnBm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
        } catch (OutOfMemoryError e) {
        }
        if (returnBm == null) {
            returnBm = bm;
        }
        if (bm != returnBm) {
            bm.recycle();
        }
        return returnBm;
    }
}


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/uitl/IntentUtils.java
================================================
package org.devio.takephoto.uitl;

import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.provider.MediaStore;
import android.util.Log;

import com.darsh.multipleimageselect.activities.AlbumSelectActivity;
import com.darsh.multipleimageselect.helpers.Constants;
import org.devio.takephoto.model.CropOptions;
import org.devio.takephoto.model.TContextWrap;

/**
 * Intent工具类用于生成拍照、
 * 从相册选择照片,裁剪照片所需的Intent
 * Author: JPH
 * Date: 2016/6/7 0007 13:41
 */
public class IntentUtils {
    private static final String TAG = IntentUtils.class.getName();

    /**
     * 获取图片多选的Intent
     *
     * @param limit 最多选择图片张数的限制
     */
    public static Intent getPickMultipleIntent(TContextWrap contextWrap, int limit) {
        Intent intent = new Intent(contextWrap.getActivity(), AlbumSelectActivity.class);
        intent.putExtra(Constants.INTENT_EXTRA_LIMIT, limit > 0 ? limit : 1);
        return intent;
    }

    /**
     * 获取裁剪照片的Intent
     *
     * @param targetUri 要裁剪的照片
     * @param outPutUri 裁剪完成的照片
     * @param options   裁剪配置
     * @return
     */
    public static Intent getCropIntentWithOtherApp(Uri targetUri, Uri outPutUri, CropOptions options) {
        boolean isReturnData = TUtils.isReturnData();
        Log.w(TAG, "getCaptureIntentWithCrop:isReturnData:" + (isReturnData ? "true" : "false"));
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.setDataAndType(targetUri, "image/*");
        intent.putExtra("crop", "true");
        if (options.getAspectX() * options.getAspectY() > 0) {
            intent.putExtra("aspectX", options.getAspectX());
            intent.putExtra("aspectY", options.getAspectY());
        }
        if (options.getOutputX() * options.getOutputY() > 0) {
            intent.putExtra("outputX", options.getOutputX());
            intent.putExtra("outputY", options.getOutputY());
        }
        intent.putExtra("scale", true);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, outPutUri);
        intent.putExtra("return-data", isReturnData);
        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
        intent.putExtra("noFaceDetection", true); // no face detection
        return intent;
    }

    /**
     * 获取拍照的Intent
     *
     * @return
     */
    public static Intent getCaptureIntent(Uri outPutUri) {
        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//设置Action为拍照
        intent.putExtra(MediaStore.EXTRA_OUTPUT, outPutUri);//将拍取的照片保存到指定URI
        return intent;
    }

    /**
     * 获取选择照片的Intent
     *
     * @return
     */
    public static Intent getPickIntentWithGallery() {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_PICK);//Pick an item from the data
        intent.setType("image/*");//从所有图片中进行选择
        return intent;
    }

    /**
     * 获取从文件中选择照片的Intent
     *
     * @return
     */
    public static Intent getPickIntentWithDocuments() {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("image/*");
        return intent;
    }
}


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/uitl/TConstant.java
================================================
package org.devio.takephoto.uitl;

import android.content.Context;

/**
 * 常量类
 *
 * @author JPH
 *         Date 2016/6/7 0007 9:39
 */
public class TConstant {


    /**
     * request Code 裁剪照片
     **/
    public final static int RC_CROP = 1001;
    /**
     * request Code 从相机获取照片并裁剪
     **/
    public final static int RC_PICK_PICTURE_FROM_CAPTURE_CROP = 1002;
    /**
     * request Code 从相机获取照片不裁剪
     **/
    public final static int RC_PICK_PICTURE_FROM_CAPTURE = 1003;
    /**
     * request Code 从文件中选择照片
     **/
    public final static int RC_PICK_PICTURE_FROM_DOCUMENTS_ORIGINAL = 1004;
    /**
     * request Code 从文件中选择照片并裁剪
     **/
    public final static int RC_PICK_PICTURE_FROM_DOCUMENTS_CROP = 1005;
    /**
     * request Code 从相册选择照
     **/
    public final static int RC_PICK_PICTURE_FROM_GALLERY_ORIGINAL = 1006;
    /**
     * request Code 从相册选择照片并裁剪
     **/
    public final static int RC_PICK_PICTURE_FROM_GALLERY_CROP = 1007;
    /**
     * request Code 选择多张照片
     **/
    public final static int RC_PICK_MULTIPLE = 1008;


    /**
     * requestCode 请求权限
     **/
    public final static int PERMISSION_REQUEST_TAKE_PHOTO = 2000;

    public final static String getFileProviderName(Context context) {
        return context.getPackageName() + ".fileprovider";
    }
}

================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/uitl/TFileUtils.java
================================================
package org.devio.takephoto.uitl;

import android.content.Context;
import android.util.Log;

import java.io.File;

/**
 * Author: crazycodeboy
 * Date: 2016/11/5 0007 20:10
 * Version:4.0.0
 * 技术博文:http://www.devio.org/
 * GitHub:https://github.com/crazycodeboy
 * Email:crazycodeboy@gmail.com
 */
public class TFileUtils {
    private static final String TAG = "TFileUtils";
    private static String DEFAULT_DISK_CACHE_DIR = "takephoto_cache";

    public static File getPhotoCacheDir(Context context, File file) {
        File cacheDir = context.getCacheDir();
        if (cacheDir != null) {
            File mCacheDir = new File(cacheDir, DEFAULT_DISK_CACHE_DIR);
            if (!mCacheDir.mkdirs() && (!mCacheDir.exists() || !mCacheDir.isDirectory())) {
                return file;
            } else {
                return new File(mCacheDir, file.getName());
            }
        }
        if (Log.isLoggable(TAG, Log.ERROR)) {
            Log.e(TAG, "default disk cache dir is null");
        }
        return file;
    }

    public static void delete(String path) {
        try {
            if (path == null) {
                return;
            }
            File file = new File(path);
            if (!file.delete()) {
                file.deleteOnExit();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/uitl/TImageFiles.java
================================================
package org.devio.takephoto.uitl;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.MimeTypeMap;
import android.widget.Toast;

import org.devio.takephoto.model.TException;
import org.devio.takephoto.model.TExceptionType;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;

/**
 * ImageFiles工具类
 *
 * @author JPH
 *         Date 2016/6/7 0007 9:39
 */
public class TImageFiles {
    private static final String TAG = IntentUtils.class.getName();

    /**
     * 将bitmap写入到文件
     *
     * @param bitmap
     */
    public static void writeToFile(Bitmap bitmap, Uri imageUri) {
        if (bitmap == null) {
            return;
        }
        File file = new File(imageUri.getPath());
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
            fos.write(bos.toByteArray());
            bos.flush();
            fos.flush();
        } catch (java.io.IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                    if (bos != null) {
                        bos.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * InputStream 转File
     */
    public static void inputStreamToFile(InputStream is, File file) throws TException {
        if (file == null) {
            Log.i(TAG, "inputStreamToFile:file not be null");
            throw new TException(TExceptionType.TYPE_WRITE_FAIL);
        }
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
            byte[] buffer = new byte[1024 * 10];
            int i;
            while ((i = is.read(buffer)) != -1) {
                fos.write(buffer, 0, i);
            }
        } catch (IOException e) {
            Log.e(TAG, "InputStream 写入文件出错:" + e.toString());
            throw new TException(TExceptionType.TYPE_WRITE_FAIL);
        } finally {
            try {
                fos.flush();
                fos.close();
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 获取临时文件
     *
     * @param context
     * @param photoUri
     * @return
     */
    public static File getTempFile(Activity context, Uri photoUri) throws TException {
        String minType = getMimeType(context, photoUri);
        if (!checkMimeType(context, minType)) {
            throw new TException(TExceptionType.TYPE_NOT_IMAGE);
        }
        File filesDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        if (!filesDir.exists()) {
            filesDir.mkdirs();
        }
        File photoFile = new File(filesDir, UUID.randomUUID().toString() + "." + minType);
        return photoFile;
    }

    /**
     * 检查文件类型是否是图片
     *
     * @param minType
     * @return
     */
    public static boolean checkMimeType(Context context, String minType) {
        boolean isPicture =
            TextUtils.isEmpty(minType) ? false : ".jpg|.gif|.png|.bmp|.jpeg|.webp|".contains(minType.toLowerCase()) ? true : false;
        if (!isPicture) {
            Toast.makeText(context, context.getResources().getText(org.devio.takephoto.R.string.tip_type_not_image), Toast.LENGTH_SHORT).show();
        }
        return isPicture;
    }

    /**
     * To find out the extension of required object in given uri
     * Solution by http://stackoverflow.com/a/36514823/1171484
     */
    public static String getMimeType(Activity context, Uri uri) {
        String extension;
        //Check uri format to avoid null
        if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
            //If scheme is a content
            extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(context.getContentResolver().getType(uri));
            if (TextUtils.isEmpty(extension)) {
                extension = MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(new File(uri.getPath())).toString());
            }
        } else {
            //If scheme is a File
            //This will replace white spaces with %20 and also other special characters. This will avoid returning null values on file
            // name with spaces and special characters.
            extension = MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(new File(uri.getPath())).toString());
            if (TextUtils.isEmpty(extension)) {
                extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(context.getContentResolver().getType(uri));
            }
        }
        if (TextUtils.isEmpty(extension)) {
            extension = getMimeTypeByFileName(TUriParse.getFileWithUri(uri, context).getName());
        }
        return extension;
    }

    public static String getMimeTypeByFileName(String fileName) {
        return fileName.substring(fileName.lastIndexOf("."), fileName.length());
    }
}

================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/uitl/TUriParse.java
================================================
package org.devio.takephoto.uitl;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v4.content.FileProvider;
import android.text.TextUtils;
import android.util.Log;

import org.devio.takephoto.model.TException;
import org.devio.takephoto.model.TExceptionType;

import java.io.File;
import java.io.FileNotFoundException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;


/**
 * Uri解析工具类
 * Author: JPH
 * Date: 2015/8/26 0026 16:23
 */
public class TUriParse {
    private static final String TAG = IntentUtils.class.getName();

    /**
     * 将scheme为file的uri转成FileProvider 提供的content uri
     *
     * @param context
     * @param uri
     * @return
     */
    public static Uri convertFileUriToFileProviderUri(Context context, Uri uri) {
        if (uri == null) {
            return null;
        }
        if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
            return getUriForFile(context, new File(uri.getPath()));
        }
        return uri;

    }

    /**
     * 获取一个临时的Uri, 文件名随机生成
     *
     * @param context
     * @return
     */
    public static Uri getTempUri(Context context) {
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
        File file = new File(Environment.getExternalStorageDirectory(), "/images/" + timeStamp + ".jpg");
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        return getUriForFile(context, file);
    }

    /**
     * 获取一个临时的Uri, 通过传入字符串路径
     *
     * @param context
     * @param path
     * @return
     */
    public static Uri getTempUri(Context context, String path) {
        File file = new File(path);
        return getTempUri(context, file);
    }

    /**
     * 获取一个临时的Uri, 通过传入File对象
     *
     * @param context
     * @return
     */
    public static Uri getTempUri(Context context, File file) {
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        return getUriForFile(context, file);
    }

    /**
     * 创建一个用于拍照图片输出路径的Uri (FileProvider)
     *
     * @param context
     * @return
     */
    public static Uri getUriForFile(Context context, File file) {
        return FileProvider.getUriForFile(context, TConstant.getFileProviderName(context), file);
    }

    /**
     * 将TakePhoto 提供的Uri 解析出文件绝对路径
     *
     * @param uri
     * @return
     */
    public static String parseOwnUri(Context context, Uri uri) {
        if (uri == null) {
            return null;
        }
        String path;
        if (TextUtils.equals(uri.getAuthority(), TConstant.getFileProviderName(context))) {
            path = new File(uri.getPath().replace("camera_photos/", "")).getAbsolutePath();
        } else {
            path = uri.getPath();
        }
        return path;
    }

    /**
     * 通过URI获取文件的路径
     *
     * @param uri
     * @param activity
     * @return Author JPH
     * Date 2016/6/6 0006 20:01
     */
    public static String getFilePathWithUri(Uri uri, Activity activity) throws TException {
        if (uri == null) {
            Log.w(TAG, "uri is null,activity may have been recovered?");
            throw new TException(TExceptionType.TYPE_URI_NULL);
        }
        File picture = getFileWithUri(uri, activity);
        String picturePath = picture == null ? null : picture.getPath();
        if (TextUtils.isEmpty(picturePath)) {
            throw new TException(TExceptionType.TYPE_URI_PARSE_FAIL);
        }
        if (!TImageFiles.checkMimeType(activity, TImageFiles.getMimeType(activity, uri))) {
            throw new TException(TExceptionType.TYPE_NOT_IMAGE);
        }
        return picturePath;
    }

    /**
     * 通过URI获取文件
     *
     * @param uri
     * @param activity
     * @return Author JPH
     * Date 2016/10/25
     */
    public static File getFileWithUri(Uri uri, Activity activity) {
        String picturePath = null;
        String scheme = uri.getScheme();
        if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
            String[] filePathColumn = {MediaStore.Images.Media.DATA};
            Cursor cursor = activity.getContentResolver().query(uri, filePathColumn, null, null, null);//从系统表中查询指定Uri对应的照片
            cursor.moveToFirst();
            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            if (columnIndex >= 0) {
                picturePath = cursor.getString(columnIndex);  //获取照片路径
            } else if (TextUtils.equals(uri.getAuthority(), TConstant.getFileProviderName(activity))) {
                picturePath = parseOwnUri(activity, uri);
            }
            cursor.close();
        } else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
            picturePath = uri.getPath();
        }
        return TextUtils.isEmpty(picturePath) ? null : new File(picturePath);
    }

    /**
     * 通过从文件中得到的URI获取文件的路径
     *
     * @param uri
     * @param activity
     * @return Author JPH
     * Date 2016/6/6 0006 20:01
     */
    public static String getFilePathWithDocumentsUri(Uri uri, Activity activity) throws TException {
        if (uri == null) {
            Log.e(TAG, "uri is null,activity may have been recovered?");
            return null;
        }
        if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme()) && uri.getPath().contains("document")) {
            File tempFile = TImageFiles.getTempFile(activity, uri);
            try {
                TImageFiles.inputStreamToFile(activity.getContentResolver().openInputStream(uri), tempFile);
                return tempFile.getPath();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                throw new TException(TExceptionType.TYPE_NO_FIND);
            }
        } else {
            return getFilePathWithUri(uri, activity);
        }
    }
}


================================================
FILE: takephoto_library/src/main/java/org/devio/takephoto/uitl/TUtils.java
================================================
package org.devio.takephoto.uitl;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.
Download .txt
gitextract_b4074lig/

├── .gitignore
├── LICENSE
├── README -V1.0+.md
├── README.2+.md
├── README.md
├── build.gradle
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
├── simple/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── org/
│       │           └── devio/
│       │               └── simple/
│       │                   └── ApplicationTest.java
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── org/
│           │       └── devio/
│           │           └── simple/
│           │               ├── CustomHelper.java
│           │               ├── MainActivity.java
│           │               ├── ResultActivity.java
│           │               ├── SimpleActivity.java
│           │               ├── SimpleFragment.java
│           │               └── SimpleFragmentActivity.java
│           └── res/
│               ├── layout/
│               │   ├── activity_main_layout.xml
│               │   ├── activity_result_layout.xml
│               │   ├── common_layout.xml
│               │   ├── image_show.xml
│               │   └── simple_fragment_layout.xml
│               ├── menu/
│               │   └── menu_main.xml
│               ├── values/
│               │   ├── dimens.xml
│               │   ├── strings.xml
│               │   └── styles.xml
│               └── values-w820dp/
│                   └── dimens.xml
└── takephoto_library/
    ├── .gitignore
    ├── build.gradle
    ├── proguard-rules.pro
    └── src/
        ├── androidTest/
        │   └── java/
        │       └── org/
        │           └── devio/
        │               └── takephoto/
        │                   └── ApplicationTest.java
        └── main/
            ├── AndroidManifest.xml
            ├── java/
            │   └── org/
            │       └── devio/
            │           └── takephoto/
            │               ├── app/
            │               │   ├── TakePhoto.java
            │               │   ├── TakePhotoActivity.java
            │               │   ├── TakePhotoFragment.java
            │               │   ├── TakePhotoFragmentActivity.java
            │               │   └── TakePhotoImpl.java
            │               ├── compress/
            │               │   ├── CompressConfig.java
            │               │   ├── CompressImage.java
            │               │   ├── CompressImageImpl.java
            │               │   ├── CompressImageUtil.java
            │               │   └── CompressWithLuBan.java
            │               ├── model/
            │               │   ├── CropOptions.java
            │               │   ├── InvokeParam.java
            │               │   ├── LubanOptions.java
            │               │   ├── MultipleCrop.java
            │               │   ├── TContextWrap.java
            │               │   ├── TException.java
            │               │   ├── TExceptionType.java
            │               │   ├── TImage.java
            │               │   ├── TIntentWap.java
            │               │   ├── TResult.java
            │               │   └── TakePhotoOptions.java
            │               ├── permission/
            │               │   ├── InvokeListener.java
            │               │   ├── PermissionManager.java
            │               │   └── TakePhotoInvocationHandler.java
            │               └── uitl/
            │                   ├── ImageRotateUtil.java
            │                   ├── IntentUtils.java
            │                   ├── TConstant.java
            │                   ├── TFileUtils.java
            │                   ├── TImageFiles.java
            │                   ├── TUriParse.java
            │                   └── TUtils.java
            └── res/
                ├── values/
                │   ├── dimens.xml
                │   └── strings.xml
                ├── values-en/
                │   └── strings.xml
                ├── values-w820dp/
                │   └── dimens.xml
                └── xml/
                    └── file_paths.xml
Download .txt
SYMBOL INDEX (339 symbols across 39 files)

FILE: simple/src/androidTest/java/org/devio/simple/ApplicationTest.java
  class ApplicationTest (line 9) | public class ApplicationTest extends ApplicationTestCase<Application> {
    method ApplicationTest (line 10) | public ApplicationTest() {

FILE: simple/src/main/java/org/devio/simple/CustomHelper.java
  class CustomHelper (line 38) | public class CustomHelper {
    method of (line 44) | public static CustomHelper of(View rootView) {
    method CustomHelper (line 48) | private CustomHelper(View rootView) {
    method init (line 53) | private void init() {
    method onClick (line 75) | public void onClick(View view, TakePhoto takePhoto) {
    method configTakePhotoOption (line 122) | private void configTakePhotoOption(TakePhoto takePhoto) {
    method configCompress (line 134) | private void configCompress(TakePhoto takePhoto) {
    method getCropOptions (line 160) | private CropOptions getCropOptions() {

FILE: simple/src/main/java/org/devio/simple/MainActivity.java
  class MainActivity (line 29) | public class MainActivity extends Activity implements View.OnClickListen...
    method onCreate (line 30) | @Override
    method onClick (line 36) | @Override

FILE: simple/src/main/java/org/devio/simple/ResultActivity.java
  class ResultActivity (line 38) | public class ResultActivity extends Activity {
    method onCreate (line 41) | @Override
    method showImg (line 49) | private void showImg() {

FILE: simple/src/main/java/org/devio/simple/SimpleActivity.java
  class SimpleActivity (line 35) | public class SimpleActivity extends TakePhotoActivity {
    method onCreate (line 38) | @Override
    method onClick (line 46) | public void onClick(View view) {
    method takeCancel (line 50) | @Override
    method takeFail (line 55) | @Override
    method takeSuccess (line 60) | @Override
    method showImg (line 66) | private void showImg(ArrayList<TImage> images) {

FILE: simple/src/main/java/org/devio/simple/SimpleFragment.java
  class SimpleFragment (line 37) | public class SimpleFragment extends TakePhotoFragment {
    method onCreate (line 40) | @Override
    method onCreateView (line 46) | @Nullable
    method onClick (line 54) | public void onClick(View view) {
    method takeCancel (line 58) | @Override
    method takeFail (line 63) | @Override
    method takeSuccess (line 68) | @Override
    method showImg (line 74) | private void showImg(ArrayList<TImage> images) {

FILE: simple/src/main/java/org/devio/simple/SimpleFragmentActivity.java
  class SimpleFragmentActivity (line 30) | public class SimpleFragmentActivity extends FragmentActivity {
    method onCreate (line 33) | @Override
    method onClick (line 42) | public void onClick(View v) {

FILE: takephoto_library/src/androidTest/java/org/devio/takephoto/ApplicationTest.java
  class ApplicationTest (line 9) | public class ApplicationTest extends ApplicationTestCase<Application> {
    method ApplicationTest (line 10) | public ApplicationTest() {

FILE: takephoto_library/src/main/java/org/devio/takephoto/app/TakePhoto.java
  type TakePhoto (line 36) | public interface TakePhoto {
    method onPickMultiple (line 42) | void onPickMultiple(int limit);
    method onPickMultipleWithCrop (line 50) | void onPickMultipleWithCrop(int limit, CropOptions options);
    method onPickFromDocuments (line 55) | void onPickFromDocuments();
    method onPickFromDocumentsWithCrop (line 63) | void onPickFromDocumentsWithCrop(Uri outPutUri, CropOptions options);
    method onPickFromGallery (line 68) | void onPickFromGallery();
    method onPickFromGalleryWithCrop (line 76) | void onPickFromGalleryWithCrop(Uri outPutUri, CropOptions options);
    method onPickFromCapture (line 83) | void onPickFromCapture(Uri outPutUri);
    method onPickFromCaptureWithCrop (line 91) | void onPickFromCaptureWithCrop(Uri outPutUri, CropOptions options);
    method onCrop (line 100) | void onCrop(Uri imageUri, Uri outPutUri, CropOptions options) throws T...
    method onCrop (line 108) | void onCrop(MultipleCrop multipleCrop, CropOptions options) throws TEx...
    method permissionNotify (line 110) | void permissionNotify(PermissionManager.TPermissionType type);
    method onEnableCompress (line 118) | void onEnableCompress(CompressConfig config, boolean showCompressDialog);
    method setTakePhotoOptions (line 125) | void setTakePhotoOptions(TakePhotoOptions options);
    method onCreate (line 127) | void onCreate(Bundle savedInstanceState);
    method onSaveInstanceState (line 129) | void onSaveInstanceState(Bundle outState);
    method onActivityResult (line 138) | void onActivityResult(int requestCode, int resultCode, Intent data);
    type TakeResultListener (line 143) | interface TakeResultListener {
      method takeSuccess (line 144) | void takeSuccess(TResult result);
      method takeFail (line 146) | void takeFail(TResult result, String msg);
      method takeCancel (line 148) | void takeCancel();

FILE: takephoto_library/src/main/java/org/devio/takephoto/app/TakePhotoActivity.java
  class TakePhotoActivity (line 25) | public class TakePhotoActivity extends Activity implements TakePhoto.Tak...
    method onCreate (line 30) | @Override
    method onSaveInstanceState (line 36) | @Override
    method onActivityResult (line 42) | @Override
    method onRequestPermissionsResult (line 48) | @Override
    method getTakePhoto (line 60) | public TakePhoto getTakePhoto() {
    method takeSuccess (line 67) | @Override
    method takeFail (line 72) | @Override
    method takeCancel (line 77) | @Override
    method invoke (line 82) | @Override

FILE: takephoto_library/src/main/java/org/devio/takephoto/app/TakePhotoFragment.java
  class TakePhotoFragment (line 24) | public class TakePhotoFragment extends Fragment implements TakePhoto.Tak...
    method onCreate (line 29) | @Override
    method onSaveInstanceState (line 35) | @Override
    method onActivityResult (line 41) | @Override
    method onRequestPermissionsResult (line 47) | @Override
    method getTakePhoto (line 59) | public TakePhoto getTakePhoto() {
    method takeSuccess (line 66) | @Override
    method takeFail (line 71) | @Override
    method takeCancel (line 76) | @Override
    method invoke (line 81) | @Override

FILE: takephoto_library/src/main/java/org/devio/takephoto/app/TakePhotoFragmentActivity.java
  class TakePhotoFragmentActivity (line 24) | public class TakePhotoFragmentActivity extends FragmentActivity implemen...
    method onCreate (line 29) | @Override
    method onSaveInstanceState (line 35) | @Override
    method onActivityResult (line 41) | @Override
    method onRequestPermissionsResult (line 47) | @Override
    method getTakePhoto (line 59) | public TakePhoto getTakePhoto() {
    method takeSuccess (line 66) | @Override
    method takeFail (line 71) | @Override
    method takeCancel (line 76) | @Override
    method invoke (line 81) | @Override

FILE: takephoto_library/src/main/java/org/devio/takephoto/app/TakePhotoImpl.java
  class TakePhotoImpl (line 60) | public class TakePhotoImpl implements TakePhoto {
    method TakePhotoImpl (line 78) | public TakePhotoImpl(Activity activity, TakeResultListener listener) {
    method TakePhotoImpl (line 83) | public TakePhotoImpl(Fragment fragment, TakeResultListener listener) {
    method onCreate (line 88) | @Override
    method onSaveInstanceState (line 100) | @Override
    method onActivityResult (line 110) | @Override
    method onPickMultiple (line 261) | @Override
    method onPickMultipleWithCrop (line 270) | @Override
    method onCrop (line 280) | @Override
    method onCrop (line 294) | @Override
    method cropWithNonException (line 300) | private void cropWithNonException(Uri imageUri, Uri outPutUri, CropOpt...
    method cropContinue (line 309) | private void cropContinue(boolean preSuccess) {
    method onPickFromDocuments (line 326) | @Override
    method onPickFromGallery (line 331) | @Override
    method selectPicture (line 336) | private void selectPicture(int defaultIndex, boolean isCrop) {
    method onPickFromGalleryWithCrop (line 358) | @Override
    method onPickFromDocumentsWithCrop (line 365) | @Override
    method onPickFromCapture (line 372) | @Override
    method onPickFromCaptureWithCrop (line 393) | @Override
    method onEnableCompress (line 416) | @Override
    method setTakePhotoOptions (line 422) | @Override
    method permissionNotify (line 427) | @Override
    method takeResult (line 432) | private void takeResult(final TResult result, final String... message) {
    method deleteRawFile (line 469) | private void deleteRawFile(ArrayList<TImage> images) {
    method handleTakeCallBack (line 478) | private void handleTakeCallBack(final TResult result, String... messag...
    method clearParams (line 502) | private void clearParams() {

FILE: takephoto_library/src/main/java/org/devio/takephoto/compress/CompressConfig.java
  class CompressConfig (line 13) | public class CompressConfig implements Serializable {
    method ofDefaultConfig (line 43) | public static CompressConfig ofDefaultConfig() {
    method ofLuban (line 47) | public static CompressConfig ofLuban(LubanOptions options) {
    method CompressConfig (line 51) | private CompressConfig() {
    method CompressConfig (line 54) | private CompressConfig(LubanOptions options) {
    method getLubanOptions (line 58) | public LubanOptions getLubanOptions() {
    method getMaxPixel (line 62) | public int getMaxPixel() {
    method setMaxPixel (line 66) | public CompressConfig setMaxPixel(int maxPixel) {
    method getMaxSize (line 71) | public int getMaxSize() {
    method setMaxSize (line 75) | public void setMaxSize(int maxSize) {
    method isEnablePixelCompress (line 79) | public boolean isEnablePixelCompress() {
    method enablePixelCompress (line 83) | public void enablePixelCompress(boolean enablePixelCompress) {
    method isEnableQualityCompress (line 87) | public boolean isEnableQualityCompress() {
    method enableQualityCompress (line 91) | public void enableQualityCompress(boolean enableQualityCompress) {
    method isEnableReserveRaw (line 95) | public boolean isEnableReserveRaw() {
    method enableReserveRaw (line 99) | public void enableReserveRaw(boolean enableReserveRaw) {
    class Builder (line 103) | public static class Builder {
      method Builder (line 106) | public Builder() {
      method setMaxSize (line 110) | public Builder setMaxSize(int maxSize) {
      method setMaxPixel (line 115) | public Builder setMaxPixel(int maxPixel) {
      method enablePixelCompress (line 120) | public Builder enablePixelCompress(boolean enablePixelCompress) {
      method enableQualityCompress (line 125) | public Builder enableQualityCompress(boolean enableQualityCompress) {
      method enableReserveRaw (line 130) | public Builder enableReserveRaw(boolean enableReserveRaw) {
      method create (line 135) | public CompressConfig create() {

FILE: takephoto_library/src/main/java/org/devio/takephoto/compress/CompressImage.java
  type CompressImage (line 13) | public interface CompressImage {
    method compress (line 14) | void compress();
    type CompressListener (line 19) | interface CompressListener {
      method onCompressSuccess (line 25) | void onCompressSuccess(ArrayList<TImage> images);
      method onCompressFailed (line 33) | void onCompressFailed(ArrayList<TImage> images, String msg);

FILE: takephoto_library/src/main/java/org/devio/takephoto/compress/CompressImageImpl.java
  class CompressImageImpl (line 20) | public class CompressImageImpl implements CompressImage {
    method of (line 25) | public static CompressImage of(Context context, CompressConfig config,...
    method CompressImageImpl (line 34) | private CompressImageImpl(Context context, CompressConfig config, Arra...
    method compress (line 40) | @Override
    method compress (line 54) | private void compress(final TImage image) {
    method continueCompress (line 80) | private void continueCompress(TImage image, boolean preSuccess, String...
    method handleCompressCallBack (line 91) | private void handleCompressCallBack(String... message) {

FILE: takephoto_library/src/main/java/org/devio/takephoto/compress/CompressImageUtil.java
  class CompressImageUtil (line 23) | public class CompressImageUtil {
    method CompressImageUtil (line 28) | public CompressImageUtil(Context context, CompressConfig config) {
    method compress (line 33) | public void compress(String imagePath, CompressListener listener) {
    method compressImageByQuality (line 54) | private void compressImageByQuality(final Bitmap bitmap, final String ...
    method compressImageByPixel (line 103) | private void compressImageByPixel(String imgPath, CompressListener lis...
    method sendMsg (line 145) | private void sendMsg(final boolean isSuccess, final String imagePath, ...
    method getThumbnailFile (line 158) | private File getThumbnailFile(File file) {
    type CompressListener (line 168) | public interface CompressListener {
      method onCompressSuccess (line 174) | void onCompressSuccess(String imgPath);
      method onCompressFailed (line 182) | void onCompressFailed(String imgPath, String msg);

FILE: takephoto_library/src/main/java/org/devio/takephoto/compress/CompressWithLuBan.java
  class CompressWithLuBan (line 25) | public class CompressWithLuBan implements CompressImage {
    method CompressWithLuBan (line 32) | public CompressWithLuBan(Context context, CompressConfig config, Array...
    method compress (line 39) | @Override
    method compressOne (line 59) | private void compressOne() {
    method compressMulti (line 86) | private void compressMulti() {
    method handleCompressCallBack (line 110) | private void handleCompressCallBack(List<File> files) {

FILE: takephoto_library/src/main/java/org/devio/takephoto/model/CropOptions.java
  class CropOptions (line 10) | public class CropOptions implements Serializable {
    method CropOptions (line 20) | private CropOptions() {
    method getAspectX (line 23) | public int getAspectX() {
    method setAspectX (line 27) | public void setAspectX(int aspectX) {
    method getAspectY (line 31) | public int getAspectY() {
    method setAspectY (line 35) | public void setAspectY(int aspectY) {
    method getOutputX (line 39) | public int getOutputX() {
    method setOutputX (line 43) | public void setOutputX(int outputX) {
    method getOutputY (line 47) | public int getOutputY() {
    method setOutputY (line 51) | public void setOutputY(int outputY) {
    method isWithOwnCrop (line 55) | public boolean isWithOwnCrop() {
    method setWithOwnCrop (line 59) | public void setWithOwnCrop(boolean withOwnCrop) {
    class Builder (line 63) | public static class Builder {
      method Builder (line 66) | public Builder() {
      method setAspectX (line 70) | public Builder setAspectX(int aspectX) {
      method setAspectY (line 75) | public Builder setAspectY(int aspectY) {
      method setOutputX (line 80) | public Builder setOutputX(int outputX) {
      method setOutputY (line 85) | public Builder setOutputY(int outputY) {
      method setWithOwnCrop (line 90) | public Builder setWithOwnCrop(boolean withOwnCrop) {
      method create (line 95) | public CropOptions create() {

FILE: takephoto_library/src/main/java/org/devio/takephoto/model/InvokeParam.java
  class InvokeParam (line 8) | public class InvokeParam {
    method InvokeParam (line 13) | public InvokeParam(Object proxy, Method method, Object[] args) {
    method getProxy (line 19) | public Object getProxy() {
    method setProxy (line 23) | public void setProxy(Object proxy) {
    method getMethod (line 27) | public Method getMethod() {
    method setMethod (line 31) | public void setMethod(Method method) {
    method getArgs (line 35) | public Object[] getArgs() {
    method setArgs (line 39) | public void setArgs(Object[] args) {

FILE: takephoto_library/src/main/java/org/devio/takephoto/model/LubanOptions.java
  class LubanOptions (line 14) | public class LubanOptions implements Serializable {
    method LubanOptions (line 22) | private LubanOptions() {
    method getMaxSize (line 25) | public int getMaxSize() {
    method setMaxSize (line 29) | public void setMaxSize(int maxSize) {
    method getMaxHeight (line 33) | public int getMaxHeight() {
    method setMaxHeight (line 37) | public void setMaxHeight(int maxHeight) {
    method getMaxWidth (line 41) | public int getMaxWidth() {
    method setMaxWidth (line 45) | public void setMaxWidth(int maxWidth) {
    class Builder (line 49) | public static class Builder {
      method Builder (line 52) | public Builder() {
      method setMaxSize (line 56) | public Builder setMaxSize(int maxSize) {
      method setMaxHeight (line 61) | public Builder setMaxHeight(int maxHeight) {
      method setMaxWidth (line 66) | public Builder setMaxWidth(int maxWidth) {
      method create (line 71) | public LubanOptions create() {

FILE: takephoto_library/src/main/java/org/devio/takephoto/model/MultipleCrop.java
  class MultipleCrop (line 17) | public class MultipleCrop {
    method of (line 24) | public static MultipleCrop of(ArrayList<Uri> uris, Activity activity, ...
    method of (line 28) | public static MultipleCrop of(ArrayList<Uri> uris, ArrayList<Uri> outU...
    method MultipleCrop (line 32) | private MultipleCrop(ArrayList<Uri> uris, Activity activity, TImage.Fr...
    method MultipleCrop (line 43) | private MultipleCrop(ArrayList<Uri> uris, ArrayList<Uri> outUris, TIma...
    method getUris (line 50) | public ArrayList<Uri> getUris() {
    method setUris (line 54) | public void setUris(ArrayList<Uri> uris) {
    method getOutUris (line 58) | public ArrayList<Uri> getOutUris() {
    method setOutUris (line 62) | public void setOutUris(ArrayList<Uri> outUris) {
    method gettImages (line 66) | public ArrayList<TImage> gettImages() {
    method settImages (line 70) | public void settImages(ArrayList<TImage> tImages) {
    method setCropWithUri (line 80) | public Map setCropWithUri(Uri uri, boolean cropped) {

FILE: takephoto_library/src/main/java/org/devio/takephoto/model/TContextWrap.java
  class TContextWrap (line 10) | public class TContextWrap {
    method of (line 14) | public static TContextWrap of(Activity activity) {
    method of (line 18) | public static TContextWrap of(Fragment fragment) {
    method TContextWrap (line 22) | private TContextWrap(Activity activity) {
    method TContextWrap (line 26) | private TContextWrap(Fragment fragment) {
    method getActivity (line 31) | public Activity getActivity() {
    method setActivity (line 35) | public void setActivity(Activity activity) {
    method getFragment (line 39) | public Fragment getFragment() {
    method setFragment (line 43) | public void setFragment(Fragment fragment) {

FILE: takephoto_library/src/main/java/org/devio/takephoto/model/TException.java
  class TException (line 7) | public class TException extends Exception {
    method TException (line 10) | public TException(TExceptionType exceptionType) {
    method getDetailMessage (line 15) | public String getDetailMessage() {

FILE: takephoto_library/src/main/java/org/devio/takephoto/model/TExceptionType.java
  type TExceptionType (line 7) | public enum TExceptionType {
    method TExceptionType (line 14) | TExceptionType(String stringValue) {
    method getStringValue (line 18) | public String getStringValue() {

FILE: takephoto_library/src/main/java/org/devio/takephoto/model/TImage.java
  class TImage (line 13) | public class TImage implements Serializable {
    method of (line 20) | public static TImage of(String path, FromType fromType) {
    method of (line 24) | public static TImage of(Uri uri, FromType fromType) {
    method TImage (line 28) | private TImage(String path, FromType fromType) {
    method TImage (line 33) | private TImage(Uri uri, FromType fromType) {
    method getOriginalPath (line 38) | public String getOriginalPath() {
    method setOriginalPath (line 42) | public void setOriginalPath(String originalPath) {
    method getCompressPath (line 46) | public String getCompressPath() {
    method setCompressPath (line 50) | public void setCompressPath(String compressPath) {
    method getFromType (line 54) | public FromType getFromType() {
    method setFromType (line 58) | public void setFromType(FromType fromType) {
    method isCropped (line 62) | public boolean isCropped() {
    method setCropped (line 66) | public void setCropped(boolean cropped) {
    method isCompressed (line 70) | public boolean isCompressed() {
    method setCompressed (line 74) | public void setCompressed(boolean compressed) {
    type FromType (line 78) | public enum FromType {

FILE: takephoto_library/src/main/java/org/devio/takephoto/model/TIntentWap.java
  class TIntentWap (line 9) | public class TIntentWap {
    method TIntentWap (line 13) | public TIntentWap() {
    method TIntentWap (line 16) | public TIntentWap(Intent intent, int requestCode) {
    method getIntent (line 21) | public Intent getIntent() {
    method setIntent (line 25) | public void setIntent(Intent intent) {
    method getRequestCode (line 29) | public int getRequestCode() {
    method setRequestCode (line 33) | public void setRequestCode(int requestCode) {

FILE: takephoto_library/src/main/java/org/devio/takephoto/model/TResult.java
  class TResult (line 10) | public class TResult {
    method of (line 14) | public static TResult of(TImage image) {
    method of (line 20) | public static TResult of(ArrayList<TImage> images) {
    method TResult (line 24) | private TResult(ArrayList<TImage> images) {
    method getImages (line 31) | public ArrayList<TImage> getImages() {
    method setImages (line 35) | public void setImages(ArrayList<TImage> images) {
    method getImage (line 39) | public TImage getImage() {
    method setImage (line 43) | public void setImage(TImage image) {

FILE: takephoto_library/src/main/java/org/devio/takephoto/model/TakePhotoOptions.java
  class TakePhotoOptions (line 13) | public class TakePhotoOptions implements Serializable {
    method TakePhotoOptions (line 23) | private TakePhotoOptions() {
    method isWithOwnGallery (line 26) | public boolean isWithOwnGallery() {
    method setWithOwnGallery (line 30) | public void setWithOwnGallery(boolean withOwnGallery) {
    method isCorrectImage (line 34) | public boolean isCorrectImage() {
    method setCorrectImage (line 38) | public void setCorrectImage(boolean correctImage) {
    class Builder (line 42) | public static class Builder {
      method Builder (line 45) | public Builder() {
      method setWithOwnGallery (line 49) | public Builder setWithOwnGallery(boolean withOwnGallery) {
      method setCorrectImage (line 54) | public Builder setCorrectImage(boolean isCorrectImage) {
      method create (line 59) | public TakePhotoOptions create() {

FILE: takephoto_library/src/main/java/org/devio/takephoto/permission/InvokeListener.java
  type InvokeListener (line 8) | public interface InvokeListener {
    method invoke (line 9) | PermissionManager.TPermissionType invoke(InvokeParam invokeParam);

FILE: takephoto_library/src/main/java/org/devio/takephoto/permission/PermissionManager.java
  class PermissionManager (line 23) | public class PermissionManager {
    type TPermission (line 24) | public enum TPermission {
      method TPermission (line 28) | TPermission(String stringValue) {
      method stringValue (line 32) | public String stringValue() {
    type TPermissionType (line 38) | public enum TPermissionType {
      method TPermissionType (line 42) | TPermissionType(String stringValue) {
      method stringValue (line 46) | public String stringValue() {
    method checkPermission (line 63) | public static TPermissionType checkPermission(@NonNull TContextWrap co...
    method requestPermission (line 99) | public static void requestPermission(@NonNull TContextWrap contextWrap...
    method onRequestPermissionsResult (line 107) | public static TPermissionType onRequestPermissionsResult(int requestCo...
    method handlePermissionsResult (line 135) | public static void handlePermissionsResult(Activity activity, TPermiss...

FILE: takephoto_library/src/main/java/org/devio/takephoto/permission/TakePhotoInvocationHandler.java
  class TakePhotoInvocationHandler (line 10) | public class TakePhotoInvocationHandler implements InvocationHandler {
    method of (line 14) | public static TakePhotoInvocationHandler of(InvokeListener listener) {
    method TakePhotoInvocationHandler (line 18) | private TakePhotoInvocationHandler(InvokeListener listener) {
    method bind (line 28) | public Object bind(TakePhoto delegate) {
    method invoke (line 33) | @Override

FILE: takephoto_library/src/main/java/org/devio/takephoto/uitl/ImageRotateUtil.java
  class ImageRotateUtil (line 24) | public class ImageRotateUtil {
    method of (line 26) | public static ImageRotateUtil of() {
    method ImageRotateUtil (line 30) | private ImageRotateUtil() {
    method correctImage (line 38) | public void correctImage(Context context, Uri path) {
    method getBitmapDegree (line 67) | private int getBitmapDegree(String path) {
    method rotateBitmapByDegree (line 98) | private Bitmap rotateBitmapByDegree(Bitmap bm, int degree) {

FILE: takephoto_library/src/main/java/org/devio/takephoto/uitl/IntentUtils.java
  class IntentUtils (line 20) | public class IntentUtils {
    method getPickMultipleIntent (line 28) | public static Intent getPickMultipleIntent(TContextWrap contextWrap, i...
    method getCropIntentWithOtherApp (line 42) | public static Intent getCropIntentWithOtherApp(Uri targetUri, Uri outP...
    method getCaptureIntent (line 70) | public static Intent getCaptureIntent(Uri outPutUri) {
    method getPickIntentWithGallery (line 83) | public static Intent getPickIntentWithGallery() {
    method getPickIntentWithDocuments (line 95) | public static Intent getPickIntentWithDocuments() {

FILE: takephoto_library/src/main/java/org/devio/takephoto/uitl/TConstant.java
  class TConstant (line 11) | public class TConstant {
    method getFileProviderName (line 53) | public final static String getFileProviderName(Context context) {

FILE: takephoto_library/src/main/java/org/devio/takephoto/uitl/TFileUtils.java
  class TFileUtils (line 16) | public class TFileUtils {
    method getPhotoCacheDir (line 20) | public static File getPhotoCacheDir(Context context, File file) {
    method delete (line 36) | public static void delete(String path) {

FILE: takephoto_library/src/main/java/org/devio/takephoto/uitl/TImageFiles.java
  class TImageFiles (line 30) | public class TImageFiles {
    method writeToFile (line 38) | public static void writeToFile(Bitmap bitmap, Uri imageUri) {
    method inputStreamToFile (line 70) | public static void inputStreamToFile(InputStream is, File file) throws...
    method getTempFile (line 104) | public static File getTempFile(Activity context, Uri photoUri) throws ...
    method checkMimeType (line 123) | public static boolean checkMimeType(Context context, String minType) {
    method getMimeType (line 136) | public static String getMimeType(Activity context, Uri uri) {
    method getMimeTypeByFileName (line 160) | public static String getMimeTypeByFileName(String fileName) {

FILE: takephoto_library/src/main/java/org/devio/takephoto/uitl/TUriParse.java
  class TUriParse (line 29) | public class TUriParse {
    method convertFileUriToFileProviderUri (line 39) | public static Uri convertFileUriToFileProviderUri(Context context, Uri...
    method getTempUri (line 56) | public static Uri getTempUri(Context context) {
    method getTempUri (line 72) | public static Uri getTempUri(Context context, String path) {
    method getTempUri (line 83) | public static Uri getTempUri(Context context, File file) {
    method getUriForFile (line 96) | public static Uri getUriForFile(Context context, File file) {
    method parseOwnUri (line 106) | public static String parseOwnUri(Context context, Uri uri) {
    method getFilePathWithUri (line 127) | public static String getFilePathWithUri(Uri uri, Activity activity) th...
    method getFileWithUri (line 151) | public static File getFileWithUri(Uri uri, Activity activity) {
    method getFilePathWithDocumentsUri (line 179) | public static String getFilePathWithDocumentsUri(Uri uri, Activity act...

FILE: takephoto_library/src/main/java/org/devio/takephoto/uitl/TUtils.java
  class TUtils (line 34) | public class TUtils {
    method convertImageToUri (line 44) | public static ArrayList<Uri> convertImageToUri(Context context, ArrayL...
    method getTImagesWithImages (line 58) | public static ArrayList<TImage> getTImagesWithImages(ArrayList<Image> ...
    method getTImagesWithUris (line 72) | public static ArrayList<TImage> getTImagesWithUris(ArrayList<Uri> uris...
    method startActivityForResult (line 84) | public static void startActivityForResult(TContextWrap contextWrap, TI...
    method sendIntentBySafely (line 101) | public static void sendIntentBySafely(TContextWrap contextWrap, List<T...
    method captureBySafely (line 118) | public static void captureBySafely(TContextWrap contextWrap, TIntentWa...
    method cropWithOtherAppBySafely (line 137) | public static void cropWithOtherAppBySafely(TContextWrap contextWrap, ...
    method cropWithOwnApp (line 161) | public static void cropWithOwnApp(TContextWrap contextWrap, Uri imageU...
    method isReturnData (line 190) | public static boolean isReturnData() {
    method showProgressDialog (line 215) | public static ProgressDialog showProgressDialog(final Activity activit...
Condensed preview — 74 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (214K chars).
[
  {
    "path": ".gitignore",
    "chars": 1430,
    "preview": "# Created by .ignore support plugin (hsz.mobi)\n### Android template\n# Built application files\n#*.apk\n*.ap_\n\n# Files for "
  },
  {
    "path": "LICENSE",
    "chars": 11358,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "README -V1.0+.md",
    "chars": 2862,
    "preview": "## [TakePhoto](https://github.com/crazycodeboy/TakePhoto) 简介    \n`TakePhoto`是一款用于Android设备获取照片(拍照或从相册、文件中选择)、裁剪图片、压缩图片的开"
  },
  {
    "path": "README.2+.md",
    "chars": 5915,
    "preview": "## [TakePhoto](https://github.com/crazycodeboy/TakePhoto) 简介  \n`TakePhoto`是一款用于在Android设备上获取照片(拍照或从相册、文件中选择)、裁剪图片、压缩图片的开"
  },
  {
    "path": "README.md",
    "chars": 13922,
    "preview": "## [TakePhoto](https://github.com/crazycodeboy/TakePhoto) 简介\n\n[![PRs Welcome](https://img.shields.io/badge/PRs-Welcome-b"
  },
  {
    "path": "build.gradle",
    "chars": 619,
    "preview": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    r"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "chars": 230,
    "preview": "#Mon Apr 02 19:53:50 CST 2018\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
  },
  {
    "path": "gradle.properties",
    "chars": 855,
    "preview": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will o"
  },
  {
    "path": "gradlew",
    "chars": 5080,
    "preview": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start "
  },
  {
    "path": "gradlew.bat",
    "chars": 2314,
    "preview": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem "
  },
  {
    "path": "settings.gradle",
    "chars": 40,
    "preview": "include ':takephoto_library', ':simple'\n"
  },
  {
    "path": "simple/.gitignore",
    "chars": 1411,
    "preview": "# Created by .ignore support plugin (hsz.mobi)\n### Android template\n# Built application files\n*.apk\n*.ap_\n\n# Files for t"
  },
  {
    "path": "simple/build.gradle",
    "chars": 570,
    "preview": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 26\n    buildToolsVersion '26.0.3'\n\n    defaultC"
  },
  {
    "path": "simple/proguard-rules.pro",
    "chars": 798,
    "preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in D:"
  },
  {
    "path": "simple/src/androidTest/java/org/devio/simple/ApplicationTest.java",
    "chars": 347,
    "preview": "package org.devio.simple;\n\nimport android.app.Application;\nimport android.test.ApplicationTestCase;\n\n/**\n * <a href=\"htt"
  },
  {
    "path": "simple/src/main/AndroidManifest.xml",
    "chars": 1240,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package="
  },
  {
    "path": "simple/src/main/java/org/devio/simple/CustomHelper.java",
    "chars": 7030,
    "preview": "package org.devio.simple;\n\nimport android.net.Uri;\nimport android.os.Environment;\nimport android.view.View;\nimport andro"
  },
  {
    "path": "simple/src/main/java/org/devio/simple/MainActivity.java",
    "chars": 1185,
    "preview": "package org.devio.simple;\n\nimport android.app.Activity;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport "
  },
  {
    "path": "simple/src/main/java/org/devio/simple/ResultActivity.java",
    "chars": 2122,
    "preview": "package org.devio.simple;\n\nimport android.app.Activity;\nimport android.os.Bundle;\nimport android.view.LayoutInflater;\nim"
  },
  {
    "path": "simple/src/main/java/org/devio/simple/SimpleActivity.java",
    "chars": 1722,
    "preview": "package org.devio.simple;\n\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.view.LayoutInflater;\n"
  },
  {
    "path": "simple/src/main/java/org/devio/simple/SimpleFragment.java",
    "chars": 1915,
    "preview": "package org.devio.simple;\n\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.support.annotation.Nu"
  },
  {
    "path": "simple/src/main/java/org/devio/simple/SimpleFragmentActivity.java",
    "chars": 1163,
    "preview": "package org.devio.simple;\n\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support."
  },
  {
    "path": "simple/src/main/res/layout/activity_main_layout.xml",
    "chars": 1121,
    "preview": "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:orientation=\"vertical\"\n    android:"
  },
  {
    "path": "simple/src/main/res/layout/activity_result_layout.xml",
    "chars": 537,
    "preview": "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:orientation=\"vertical\"\n    android:"
  },
  {
    "path": "simple/src/main/res/layout/common_layout.xml",
    "chars": 23023,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ScrollView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    androi"
  },
  {
    "path": "simple/src/main/res/layout/image_show.xml",
    "chars": 976,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    andr"
  },
  {
    "path": "simple/src/main/res/layout/simple_fragment_layout.xml",
    "chars": 460,
    "preview": "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:orientation=\"vertical\"\n    android:"
  },
  {
    "path": "simple/src/main/res/menu/menu_main.xml",
    "chars": 361,
    "preview": "<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\""
  },
  {
    "path": "simple/src/main/res/values/dimens.xml",
    "chars": 211,
    "preview": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal"
  },
  {
    "path": "simple/src/main/res/values/strings.xml",
    "chars": 179,
    "preview": "<resources>\n    <string name=\"app_name\">TakePhoto</string>\n\n    <string name=\"hello_world\">Hello world!</string>\n    <st"
  },
  {
    "path": "simple/src/main/res/values/styles.xml",
    "chars": 194,
    "preview": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar"
  },
  {
    "path": "simple/src/main/res/values-w820dp/dimens.xml",
    "chars": 358,
    "preview": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as s"
  },
  {
    "path": "takephoto_library/.gitignore",
    "chars": 1434,
    "preview": "# Created by .ignore support plugin (hsz.mobi)\n### Android template\n# Built application files\n*.apk\n*.ap_\n\n# Files for t"
  },
  {
    "path": "takephoto_library/build.gradle",
    "chars": 702,
    "preview": "apply plugin: 'com.android.library'\n\nandroid {\n    compileSdkVersion 27\n    buildToolsVersion '26.0.3'\n\n    defaultConfi"
  },
  {
    "path": "takephoto_library/proguard-rules.pro",
    "chars": 1063,
    "preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in D:"
  },
  {
    "path": "takephoto_library/src/androidTest/java/org/devio/takephoto/ApplicationTest.java",
    "chars": 350,
    "preview": "package org.devio.takephoto;\n\nimport android.app.Application;\nimport android.test.ApplicationTestCase;\n\n/**\n * <a href=\""
  },
  {
    "path": "takephoto_library/src/main/AndroidManifest.xml",
    "chars": 847,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package="
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/app/TakePhoto.java",
    "chars": 3232,
    "preview": "package org.devio.takephoto.app;\n\nimport android.content.Intent;\nimport android.net.Uri;\nimport android.os.Bundle;\n\nimpo"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/app/TakePhotoActivity.java",
    "chars": 3012,
    "preview": "package org.devio.takephoto.app;\n\nimport android.app.Activity;\nimport android.content.Intent;\nimport android.os.Bundle;\n"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/app/TakePhotoFragment.java",
    "chars": 3013,
    "preview": "package org.devio.takephoto.app;\n\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.support.v4.app"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/app/TakePhotoFragmentActivity.java",
    "chars": 3045,
    "preview": "package org.devio.takephoto.app;\n\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.support.v4.app"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/app/TakePhotoImpl.java",
    "chars": 20996,
    "preview": "package org.devio.takephoto.app;\n\nimport android.app.Activity;\nimport android.app.ProgressDialog;\nimport android.content"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/compress/CompressConfig.java",
    "chars": 3095,
    "preview": "package org.devio.takephoto.compress;\n\n\nimport org.devio.takephoto.model.LubanOptions;\n\nimport java.io.Serializable;\n\n/*"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/compress/CompressImage.java",
    "chars": 632,
    "preview": "package org.devio.takephoto.compress;\n\nimport org.devio.takephoto.model.TImage;\n\nimport java.util.ArrayList;\n\n/**\n * 压缩照"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/compress/CompressImageImpl.java",
    "chars": 3344,
    "preview": "package org.devio.takephoto.compress;\n\nimport android.content.Context;\nimport android.text.TextUtils;\n\nimport org.devio."
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/compress/CompressImageUtil.java",
    "chars": 6273,
    "preview": "package org.devio.takephoto.compress;\n\nimport android.content.Context;\nimport android.graphics.Bitmap;\nimport android.gr"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/compress/CompressWithLuBan.java",
    "chars": 3804,
    "preview": "package org.devio.takephoto.compress;\n\nimport android.content.Context;\n\nimport org.devio.takephoto.model.LubanOptions;\ni"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/model/CropOptions.java",
    "chars": 2015,
    "preview": "package org.devio.takephoto.model;\n\nimport java.io.Serializable;\n\n/**\n * 裁剪配置类\n * Author: JPH\n * Date: 2016/7/27 13:19\n "
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/model/InvokeParam.java",
    "chars": 790,
    "preview": "package org.devio.takephoto.model;\n\nimport java.lang.reflect.Method;\n\n/**\n * Created by penn on 16/9/22.\n */\npublic clas"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/model/LubanOptions.java",
    "chars": 1536,
    "preview": "package org.devio.takephoto.model;\n\nimport java.io.Serializable;\n\n/**\n * Luban配置类\n * Author: crazycodeboy\n * Date: 2016/"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/model/MultipleCrop.java",
    "chars": 2572,
    "preview": "package org.devio.takephoto.model;\n\nimport android.app.Activity;\nimport android.net.Uri;\n\nimport org.devio.takephoto.uit"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/model/TContextWrap.java",
    "chars": 994,
    "preview": "package org.devio.takephoto.model;\n\nimport android.app.Activity;\nimport android.support.v4.app.Fragment;\n\n/**\n * Author:"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/model/TException.java",
    "chars": 401,
    "preview": "package org.devio.takephoto.model;\n\n/**\n * Author: JPH\n * Date: 2016/7/26 10:53\n */\npublic class TException extends Exce"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/model/TExceptionType.java",
    "chars": 588,
    "preview": "package org.devio.takephoto.model;\n\n/**\n * Author: JPH\n * Date: 2016/7/26 11:01\n */\npublic enum TExceptionType {\n    TYP"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/model/TImage.java",
    "chars": 1743,
    "preview": "package org.devio.takephoto.model;\n\nimport android.net.Uri;\n\nimport java.io.Serializable;\n\n/**\n * TakePhoto 操作成功返回的处理结果\n"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/model/TIntentWap.java",
    "chars": 674,
    "preview": "package org.devio.takephoto.model;\n\nimport android.content.Intent;\n\n/**\n * Author: JPH\n * Date: 2016/7/26 14:23\n */\npubl"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/model/TResult.java",
    "chars": 983,
    "preview": "package org.devio.takephoto.model;\n\nimport java.util.ArrayList;\n\n/**\n * TakePhoto 操作成功返回的处理结果\n * Author: JPH\n * Date: 20"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/model/TakePhotoOptions.java",
    "chars": 1456,
    "preview": "package org.devio.takephoto.model;\n\nimport java.io.Serializable;\n\n/**\n * Author: crazycodeboy\n * Date: 2016/11/5 0007 20"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/permission/InvokeListener.java",
    "chars": 213,
    "preview": "package org.devio.takephoto.permission;\n\nimport org.devio.takephoto.model.InvokeParam;\n\n/**\n * 授权管理回调\n */\npublic interfa"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/permission/PermissionManager.java",
    "chars": 6451,
    "preview": "package org.devio.takephoto.permission;\n\nimport android.Manifest;\nimport android.app.Activity;\nimport android.content.pm"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/permission/TakePhotoInvocationHandler.java",
    "chars": 1377,
    "preview": "package org.devio.takephoto.permission;\n\nimport org.devio.takephoto.app.TakePhoto;\nimport org.devio.takephoto.model.Invo"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/uitl/ImageRotateUtil.java",
    "chars": 3213,
    "preview": "package org.devio.takephoto.uitl;\n\nimport android.content.Context;\nimport android.graphics.Bitmap;\nimport android.graphi"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/uitl/IntentUtils.java",
    "chars": 3267,
    "preview": "package org.devio.takephoto.uitl;\n\nimport android.content.Intent;\nimport android.graphics.Bitmap;\nimport android.net.Uri"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/uitl/TConstant.java",
    "chars": 1302,
    "preview": "package org.devio.takephoto.uitl;\n\nimport android.content.Context;\n\n/**\n * 常量类\n *\n * @author JPH\n *         Date 2016/6/"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/uitl/TFileUtils.java",
    "chars": 1374,
    "preview": "package org.devio.takephoto.uitl;\n\nimport android.content.Context;\nimport android.util.Log;\n\nimport java.io.File;\n\n/**\n "
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/uitl/TImageFiles.java",
    "chars": 5453,
    "preview": "package org.devio.takephoto.uitl;\n\nimport android.app.Activity;\nimport android.content.ContentResolver;\nimport android.c"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/uitl/TUriParse.java",
    "chars": 6054,
    "preview": "package org.devio.takephoto.uitl;\n\nimport android.app.Activity;\nimport android.content.ContentResolver;\nimport android.c"
  },
  {
    "path": "takephoto_library/src/main/java/org/devio/takephoto/uitl/TUtils.java",
    "chars": 8385,
    "preview": "package org.devio.takephoto.uitl;\n\nimport android.app.Activity;\nimport android.app.ProgressDialog;\nimport android.conten"
  },
  {
    "path": "takephoto_library/src/main/res/values/dimens.xml",
    "chars": 211,
    "preview": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal"
  },
  {
    "path": "takephoto_library/src/main/res/values/strings.xml",
    "chars": 1032,
    "preview": "<resources>\n    <!--TakePhoto-->\n    <string name=\"tip_type_not_image\">选择的不是图片</string>\n    <string name=\"tip_no_camera\""
  },
  {
    "path": "takephoto_library/src/main/res/values-en/strings.xml",
    "chars": 1036,
    "preview": "<resources>\n    <!--TakePhoto-->\n    <string name=\"tip_type_not_image\">Choose not pictures</string>\n    <string name=\"ti"
  },
  {
    "path": "takephoto_library/src/main/res/values-w820dp/dimens.xml",
    "chars": 358,
    "preview": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as s"
  },
  {
    "path": "takephoto_library/src/main/res/xml/file_paths.xml",
    "chars": 163,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <paths>\n        <root-path\n            path=\"\"\n            name=\""
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the crazycodeboy/TakePhoto GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 74 files (195.3 KB), approximately 50.8k tokens, and a symbol index with 339 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!