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: ``` ``` ## 在项目中使用 为方便大家使用,现已将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 com.jph.takephoto takephoto_library 1.0.1 pom ``` ## 最后 如果你对[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: ``` ``` ## 在项目中使用 为方便大家使用,现已将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 com.jph.takephoto takephoto_library 2.0.4 pom ``` ## 最后 如果你对[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 com.jph.takephoto takephoto_library 4.1.0 pom ``` ## 演示 运行效果图: ![预览图](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 ``` 在“toolbar.xml”文件中你可以指定TakePhoto自带相册的主题以及Toolbar的背景色。 #### 自定义状态栏 在“res/values”目录中创建一个名为“colors.xml”的资源文件,内容如下: ```xml #212121 ``` 通过上述方式便可以自定义状态栏的颜色。 #### 自定义提示文字 在“res/values”目录的“string.xml”文件冲添加如下代码: ```xml 选择图片 单击选择 确定 已选 最多能选 %d 张 ``` 重写上述代码,便可以自定义TakePhoto自带相册的提示文字。 ### 自定义裁切工具 在“res/layout”目录中创建一个名为“crop__activity_crop.xml”与“crop__layout_done_cancel.xml”的布局文件,内容如下: **crop__activity_crop.xml** ```xml ``` **crop__layout_done_cancel.xml** ```xml ``` 重写上述代码,便可以自定义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 images) { //图片压缩成功 } @Override public void onCompressFailed(ArrayList 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: ``` ``` ## 贡献 如果你在使用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; /** * Testing Fundamentals */ public class ApplicationTest extends ApplicationTestCase { public ApplicationTest() { super(Application.class); } } ================================================ FILE: simple/src/main/AndroidManifest.xml ================================================ ================================================ 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 images; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_result_layout); images = (ArrayList) 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 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 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 ================================================