Repository: wzx54321/LockDemo Branch: master Commit: 92dbd5f47881 Files: 161 Total size: 542.1 KB Directory structure: gitextract__z3swy7w/ ├── .gitignore ├── LICENSE ├── README.md ├── aliocrlib/ │ ├── .gitignore │ ├── README.MD │ ├── build.gradle │ ├── libs/ │ │ └── BASE64Encoder.jar │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── api14/ │ │ └── cameraview/ │ │ ├── Camera1.java │ │ └── TextureViewPreview.java │ ├── api21/ │ │ └── cameraview/ │ │ └── Camera2.java │ ├── api23/ │ │ └── cameraview/ │ │ └── Camera2Api23.java │ ├── api9/ │ │ └── cameraview/ │ │ └── SurfaceViewPreview.java │ ├── base/ │ │ └── cameraview/ │ │ ├── AspectRatio.java │ │ ├── CameraViewImpl.java │ │ ├── Constants.java │ │ ├── PreviewImpl.java │ │ ├── Size.java │ │ └── SizeMap.java │ ├── java/ │ │ ├── cameraview/ │ │ │ ├── CameraView.java │ │ │ └── DisplayOrientationDetector.java │ │ └── com/ │ │ └── lib/ │ │ └── aliocr/ │ │ ├── api/ │ │ │ ├── HttpCustomConfig.java │ │ │ └── MyApiManager.java │ │ ├── bean/ │ │ │ ├── RepOutput.java │ │ │ └── ReqInput.java │ │ ├── callback/ │ │ │ └── OcrCallback.java │ │ ├── common/ │ │ │ └── Api.java │ │ ├── contact/ │ │ │ └── OcrContact.java │ │ ├── http/ │ │ │ ├── config/ │ │ │ │ └── HttpConfig.java │ │ │ ├── helper/ │ │ │ │ └── HttpHelper.java │ │ │ ├── https/ │ │ │ │ └── HttpsUtils.java │ │ │ └── interceptor/ │ │ │ └── HttpLog.java │ │ ├── modle/ │ │ │ └── OCRModel.java │ │ ├── presenter/ │ │ │ └── OCRPresenter.java │ │ ├── utils/ │ │ │ ├── Base64.java │ │ │ ├── Ocr.java │ │ │ ├── OcrUtils.java │ │ │ ├── io/ │ │ │ │ ├── Charsets.java │ │ │ │ ├── FileUtil.java │ │ │ │ ├── IOUtils.java │ │ │ │ ├── SdCardUtil.java │ │ │ │ └── StringCodingUtils.java │ │ │ └── stream/ │ │ │ ├── ByteArrayOutputStream.java │ │ │ ├── ClosedInputStream.java │ │ │ └── StringBuilderWriter.java │ │ ├── view/ │ │ │ ├── OCRMainActivity.java │ │ │ └── OcrLaunchFragment.java │ │ └── widget/ │ │ ├── crop/ │ │ │ ├── Crop.java │ │ │ ├── CropImageActivity.java │ │ │ ├── CropImageView.java │ │ │ ├── CropUtil.java │ │ │ ├── HighlightView.java │ │ │ ├── ImageViewTouchBase.java │ │ │ ├── Log.java │ │ │ ├── MonitoredActivity.java │ │ │ └── RotateBitmap.java │ │ └── popup/ │ │ └── XinPopWindow.java │ └── res/ │ ├── anim/ │ │ ├── push_bottom_in.xml │ │ └── push_bottom_out.xml │ ├── drawable/ │ │ ├── common_btn_pop_choose_pic_down.xml │ │ ├── common_btn_pop_choose_pic_mid.xml │ │ ├── common_btn_pop_choose_pic_up.xml │ │ ├── crop__selectable_background.xml │ │ ├── crop__texture.xml │ │ └── ic_camera.xml │ ├── drawable-v21/ │ │ └── crop__selectable_background.xml │ ├── layout/ │ │ ├── activity_ocr_main.xml │ │ ├── common_item_popup.xml │ │ ├── common_popwindow.xml │ │ ├── crop__activity_crop.xml │ │ ├── crop__layout_done_cancel.xml │ │ ├── fragment_ocr_launch.xml │ │ └── surface_view.xml │ ├── layout-v14/ │ │ └── texture_view.xml │ └── values/ │ ├── attrs.xml │ ├── colors.xml │ ├── dimens.xml │ ├── public.xml │ ├── strings.xml │ └── styles.xml ├── app/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── java/ │ │ └── com/ │ │ └── xin/ │ │ └── lockdemo/ │ │ ├── App.java │ │ ├── GesturePswMainActivity.java │ │ ├── MainActivity.java │ │ └── dialog/ │ │ └── CustomDialog.java │ └── res/ │ ├── drawable/ │ │ ├── ic_launcher_background.xml │ │ └── login_shape_bg_finger_change_dialog.xml │ ├── layout/ │ │ ├── activity_gesture_psw_main.xml │ │ ├── activity_main.xml │ │ ├── common_dialog_custom_view_layout.xml │ │ └── login_finger_change_dialog.xml │ └── values/ │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── config.gradle ├── fingerprintlib/ │ ├── README.MD │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── java/ │ │ └── com/ │ │ └── lib/ │ │ └── lock/ │ │ └── fingerprint/ │ │ ├── activities/ │ │ │ └── FingerprintPswMainActivity.java │ │ ├── core/ │ │ │ ├── CryptoObjectCreator.java │ │ │ ├── FingerprintCore.java │ │ │ └── MyListener.java │ │ ├── dialog/ │ │ │ └── FingerDialog.java │ │ └── utils/ │ │ ├── FingerContext.java │ │ ├── FingerprintUtil.java │ │ └── KeyguardLockScreenManager.java │ └── res/ │ ├── anim/ │ │ ├── anim_shake.xml │ │ └── cycle.xml │ ├── drawable/ │ │ └── bg_finger_change_dialog.xml │ ├── layout/ │ │ ├── activity_fingerprint_psw_main.xml │ │ ├── finger_dialog_custom_view_layout.xml │ │ ├── finger_dialog_error.xml │ │ └── finger_dialog_icon_info.xml │ └── values/ │ ├── strings.xml │ └── style.xml ├── gesturepswlib/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── java/ │ │ └── com/ │ │ └── lib/ │ │ └── lock/ │ │ └── gesture/ │ │ ├── activities/ │ │ │ ├── GestureSettingsActivity.java │ │ │ └── GestureVerifyActivity.java │ │ ├── bean/ │ │ │ ├── CellBean.java │ │ │ └── CellFactory.java │ │ ├── config/ │ │ │ └── Config.java │ │ ├── content/ │ │ │ ├── DataKeeper.java │ │ │ ├── SPManager.java │ │ │ ├── SharedPreferencesKeys.java │ │ │ └── readme.txt │ │ ├── customView/ │ │ │ ├── DefaultIndicatorHitCellView.java │ │ │ ├── DefaultIndicatorLinkedLineView.java │ │ │ ├── DefaultIndicatorNormalCellView.java │ │ │ ├── DefaultLockerHitCellView.java │ │ │ ├── DefaultLockerLinkedLineView.java │ │ │ ├── DefaultLockerNormalCellView.java │ │ │ ├── DefaultLockerNormalCustomCellView.java │ │ │ ├── IHitCellView.java │ │ │ ├── IIndicatorLinkedLineView.java │ │ │ ├── ILockerLinkedLineView.java │ │ │ ├── INormalCellView.java │ │ │ ├── OnPatternChangeListener.java │ │ │ ├── PatternIndicatorView.java │ │ │ └── PatternLockerView.java │ │ └── utils/ │ │ ├── ContextUtils.java │ │ ├── PatternHelper.java │ │ └── SecurityUtil.java │ └── res/ │ ├── layout/ │ │ ├── activity_gesture_settings.xml │ │ └── activity_gesture_verify.xml │ └── values/ │ ├── attrs.xml │ └── strings.xml ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat └── settings.gradle ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # Built application files *.apk *.ap_ # Files for the ART/Dalvik VM *.dex # Java class files *.class # Generated files bin/ gen/ out/ # Gradle files .gradle/ build/ # Local configuration file (sdk path, etc) local.properties # Proguard folder generated by Eclipse proguard/ # Log Files *.log # Android Studio Navigation editor temp files .navigation/ # Android Studio captures folder captures/ # IntelliJ *.iml .idea/workspace.xml .idea/tasks.xml .idea/gradle.xml .idea/assetWizardSettings.xml .idea/dictionaries .idea/libraries .idea/caches .idea/ # Keystore files # Uncomment the following line if you do not want to check your keystore files in. #*.jks # External native build folder generated in Android Studio 2.2 and later .externalNativeBuild # Google Services (e.g. APIs or Firebase) google-services.json # Freeline freeline.py freeline/ freeline_project_description.json # fastlane fastlane/report.xml fastlane/Preview.html fastlane/screenshots fastlane/test_output fastlane/readme.md ================================================ 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.md ================================================ # LockDemo 封装了:指纹识别、图形密码手势密码识别、aliOCR识别 个人使用,可根据需求添加。
Chooses a camera ID by the specified camera facing ({@link #mFacing}).
*This rewrites {@link #mCameraId}, {@link #mCameraCharacteristics}, and optionally * {@link #mFacing}.
*/ private boolean chooseCameraIdByFacing() { try { int internalFacing = INTERNAL_FACINGS.get(mFacing); final String[] ids = mCameraManager.getCameraIdList(); if (ids.length == 0) { // No camera throw new RuntimeException("No camera available."); } for (String id : ids) { CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(id); Integer level = characteristics.get( CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL); if (level == null || level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) { continue; } Integer internal = characteristics.get(CameraCharacteristics.LENS_FACING); if (internal == null) { throw new NullPointerException("Unexpected state: LENS_FACING null"); } if (internal == internalFacing) { mCameraId = id; mCameraCharacteristics = characteristics; return true; } } // Not found mCameraId = ids[0]; mCameraCharacteristics = mCameraManager.getCameraCharacteristics(mCameraId); Integer level = mCameraCharacteristics.get( CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL); if (level == null || level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) { return false; } Integer internal = mCameraCharacteristics.get(CameraCharacteristics.LENS_FACING); if (internal == null) { throw new NullPointerException("Unexpected state: LENS_FACING null"); } for (int i = 0, count = INTERNAL_FACINGS.size(); i < count; i++) { if (INTERNAL_FACINGS.valueAt(i) == internal) { mFacing = INTERNAL_FACINGS.keyAt(i); return true; } } // The operation can reach here when the only camera device is an external one. // We treat it as facing back. mFacing = Constants.FACING_BACK; return true; } catch (CameraAccessException e) { throw new RuntimeException("Failed to get a list of camera devices", e); } } /** *Collects some information from {@link #mCameraCharacteristics}.
*This rewrites {@link #mPreviewSizes}, {@link #mPictureSizes}, and optionally, * {@link #mAspectRatio}.
*/ private void collectCameraInfo() { StreamConfigurationMap map = mCameraCharacteristics.get( CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); if (map == null) { throw new IllegalStateException("Failed to get configuration map: " + mCameraId); } mPreviewSizes.clear(); for (android.util.Size size : map.getOutputSizes(mPreview.getOutputClass())) { int width = size.getWidth(); int height = size.getHeight(); if (width <= MAX_PREVIEW_WIDTH && height <= MAX_PREVIEW_HEIGHT) { mPreviewSizes.add(new Size(width, height)); } } mPictureSizes.clear(); collectPictureSizes(mPictureSizes, map); for (AspectRatio ratio : mPreviewSizes.ratios()) { if (!mPictureSizes.ratios().contains(ratio)) { mPreviewSizes.remove(ratio); } } if (!mPreviewSizes.ratios().contains(mAspectRatio)) { mAspectRatio = mPreviewSizes.ratios().iterator().next(); } } protected void collectPictureSizes(SizeMap sizes, StreamConfigurationMap map) { for (android.util.Size size : map.getOutputSizes(ImageFormat.JPEG)) { mPictureSizes.add(new Size(size.getWidth(), size.getHeight())); } } private void prepareImageReader() { if (mImageReader != null) { mImageReader.close(); } Size largest = mPictureSizes.sizes(mAspectRatio).last(); mImageReader = ImageReader.newInstance(largest.getWidth(), largest.getHeight(), ImageFormat.JPEG, /* maxImages */ 2); mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, null); } /** *Starts opening a camera device.
*The result will be processed in {@link #mCameraDeviceCallback}.
*/ private void startOpeningCamera() { try { mCameraManager.openCamera(mCameraId, mCameraDeviceCallback, null); } catch (CameraAccessException e) { throw new RuntimeException("Failed to open camera: " + mCameraId, e); } } /** *Starts a capture session for camera preview.
*This rewrites {@link #mPreviewRequestBuilder}.
*The result will be continuously processed in {@link #mSessionCallback}.
*/ void startCaptureSession() { if (!isCameraOpened() || !mPreview.isReady() || mImageReader == null) { return; } Size previewSize = chooseOptimalSize(); mPreview.setBufferSize(previewSize.getWidth(), previewSize.getHeight()); Surface surface = mPreview.getSurface(); try { mPreviewRequestBuilder = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); mPreviewRequestBuilder.addTarget(surface); mCamera.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()), mSessionCallback, null); } catch (CameraAccessException e) { throw new RuntimeException("Failed to start camera session"); } } /** * Chooses the optimal preview size based on {@link #mPreviewSizes} and the surface size. * * @return The picked size for camera preview. */ private Size chooseOptimalSize() { int surfaceLonger, surfaceShorter; final int surfaceWidth = mPreview.getWidth(); final int surfaceHeight = mPreview.getHeight(); if (surfaceWidth < surfaceHeight) { surfaceLonger = surfaceHeight; surfaceShorter = surfaceWidth; } else { surfaceLonger = surfaceWidth; surfaceShorter = surfaceHeight; } SortedSet* 邮箱:ittfxin@126.com *
* https://github.com/wzx54321/XinFrameworkLib */ public class HttpCustomConfig extends HttpConfig { @Override public OkHttpClient.Builder getCustomBuilder() { // 根据个人需要配置 return null; } } ================================================ FILE: aliocrlib/src/main/java/com/lib/aliocr/api/MyApiManager.java ================================================ package com.lib.aliocr.api; import com.lib.aliocr.bean.RepOutput; import com.lib.aliocr.common.Api; import io.reactivex.Observable; import okhttp3.RequestBody; import retrofit2.http.Body; import retrofit2.http.Headers; import retrofit2.http.POST; import static com.lib.aliocr.common.Api.path; /** * 作者:xin on 2018/7/9 0009 15:03 *
* 邮箱:ittfxin@126.com *
* https://github.com/wzx54321/XinFrameworkLib
*/
public interface MyApiManager {
@POST(path)
@Headers({"Authorization: APPCODE " + Api.APPCODE})
Observable
* 邮箱:ittfxin@126.com
*
* https://github.com/wzx54321/XinFrameworkLib
*/
public class RepOutput implements Serializable {
private static final long serialVersionUID = 2694028643765036256L;
private String address;// 地址信息
private String config_str;// 配置信息,同输入configure
private faceRect face_rect;// 信息
private String name;// 姓名
private String nationality;// 民族
private String num;// 身份证号
private String sex;// 性别
private String birth;// 出生日期
private String start_date;// 有效期起始时间
private String end_date;// 有效期结束时间
private String issue;// 签发机关
private boolean success;// true表示成功,false表示失败
static class faceRect implements Serializable {
private static final long serialVersionUID = -7765350923476725941L;
private double angle;
private Center center;
private Size size;
public double getAngle() {
return angle;
}
public void setAngle(int angle) {
this.angle = angle;
}
public Center getCenter() {
return center;
}
public void setCenter(Center center) {
this.center = center;
}
public Size getSize() {
return size;
}
public void setSize(Size size) {
this.size = size;
}
static class Center implements Serializable {
private static final long serialVersionUID = 3232617470096971014L;
private double x;
private double y;
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
@Override
public String toString() {
return "Center{" +
"x=" + x +
", y=" + y +
'}';
}
}
static class Size implements Serializable {
private static final long serialVersionUID = -3276942859242710227L;
private double height;
private double width;
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
@Override
public String toString() {
return "Size{" +
"height=" + height +
", width=" + width +
'}';
}
}
@Override
public String toString() {
return "faceRect{" +
"angle=" + angle +
", center=" + center +
", size=" + size +
'}';
}
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getConfig_str() {
return config_str;
}
public void setConfig_str(String config_str) {
this.config_str = config_str;
}
public faceRect getFace_rect() {
return face_rect;
}
public void setFace_rect(faceRect face_rect) {
this.face_rect = face_rect;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNationality() {
return nationality;
}
public void setNationality(String nationality) {
this.nationality = nationality;
}
public String getNum() {
return num;
}
public void setNum(String num) {
this.num = num;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getBirth() {
return birth;
}
public void setBirth(String birth) {
this.birth = birth;
}
public String getStart_date() {
return start_date;
}
public void setStart_date(String start_date) {
this.start_date = start_date;
}
public String getEnd_date() {
return end_date;
}
public void setEnd_date(String end_date) {
this.end_date = end_date;
}
public String getIssue() {
return issue;
}
public void setIssue(String issue) {
this.issue = issue;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
@Override
public String toString() {
return "RepOutput{" +
"address='" + address + '\'' +
", config_str='" + config_str + '\'' +
", face_rect=" + face_rect +
", name='" + name + '\'' +
", nationality='" + nationality + '\'' +
", num='" + num + '\'' +
", sex='" + sex + '\'' +
", birth='" + birth + '\'' +
", start_date='" + start_date + '\'' +
", end_date='" + end_date + '\'' +
", issue='" + issue + '\'' +
", success=" + success +
'}';
}
}
================================================
FILE: aliocrlib/src/main/java/com/lib/aliocr/bean/ReqInput.java
================================================
package com.lib.aliocr.bean;
import java.io.Serializable;
/**
* 作者:xin on 2018/7/9 0009 15:03
*
* 邮箱:ittfxin@126.com
*
* https://github.com/wzx54321/XinFrameworkLib
*/
public class ReqInput implements Serializable {
private static final long serialVersionUID = 7540344538333996814L;
private String image;// 图片的 base64
private String configure;// "{\"side\":\"face\"}" 身份证正反面类型:face/back
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getConfigure() {
return configure;
}
public void setConfigure(String configure) {
this.configure = configure;
}
}
================================================
FILE: aliocrlib/src/main/java/com/lib/aliocr/callback/OcrCallback.java
================================================
package com.lib.aliocr.callback;
/**
* 作者:xin on 2018/7/9 0009 15:03
*
* 邮箱:ittfxin@126.com
*
* https://github.com/wzx54321/XinFrameworkLib
*/
public interface OcrCallback {
void onPicResult(String picPath);
void onPicError();
}
================================================
FILE: aliocrlib/src/main/java/com/lib/aliocr/common/Api.java
================================================
package com.lib.aliocr.common;
/**
* 作者:xin on 2018/7/9 0009 15:03
*
* 邮箱:ittfxin@126.com
*
* https://github.com/wzx54321/XinFrameworkLib
*/
public interface Api {
String host = "http://dm-51.data.aliyun.com";
String path = "/rest/160601/ocr/ocr_idcard.json";
// 注册的APP code
String APPCODE = "17b5e0d488564592868ed002e4e282c4";
}
================================================
FILE: aliocrlib/src/main/java/com/lib/aliocr/contact/OcrContact.java
================================================
package com.lib.aliocr.contact;
import android.app.Activity;
import com.lib.aliocr.bean.RepOutput;
import io.reactivex.Observable;
/**
* 作者:xin on 2018/7/12 0012 16:55
*
* 邮箱:ittfxin@126.com
*
* *
* https://github.com/wzx54321/XinFrameworkLib
*/
public interface OcrContact {
interface V {
Activity getActivity();
}
interface P {
void onPictureTaken(final byte[] data );
void request(boolean isFace, String imgPath);
}
interface M {
Observable
* 邮箱:ittfxin@126.com
*
* https://github.com/wzx54321/XinFrameworkLib
*/
public abstract class HttpConfig {
private OkHttpClient httpClient;
private static final long DEFAULT_MILLISECONDS = 60000; // 默认时间
/**
* 获取默认的{@link OkHttpClient.Builder}
*
*/
private OkHttpClient.Builder getDefaultBuilder() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
// log相关
HttpLog httpLog = new HttpLog();
httpLog.setPrintLevel(HttpLog.Level.BODY); // log打印级别,决定了log显示的详细程度
// httpLog.setPrintBinaryBody(true);// 打印二进制Log ,默认不打印
builder.addInterceptor(httpLog);
// 超时时间设置,默认60秒
builder.readTimeout(DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS); // 全局的读取超时时间
builder.writeTimeout(DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS); // 全局的写入超时时间
builder.connectTimeout(DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS); // 全局的连接超时时间
// builder.cookieJar(new CookieJarImpl(new SPCookieStore(app))); // 使用sp保持cookie,如果cookie不过期,则一直有效
// builder.cookieJar(new CookieJarImpl(new DBCookieStore(ContextUtils.getActivity()))); // 使用数据库保持cookie,如果cookie不过期,则一直有效
// https相关设置,以下几种方案根据需要自己设置
// 方法一:信任所有证书,不安全有风险
HttpsUtils.SSLParams sslParams1 = HttpsUtils.getSslSocketFactory();
// 方法二:自定义信任规则,校验服务端证书
// HttpsUtils.SSLParams sslParams2 = HttpsUtils.getSslSocketFactory(new SafeTrustManager());
// 方法三:使用预埋证书,校验服务端证书(自签名证书)
/* try {
HttpsUtils.SSLParams sslParams3 = HttpsUtils.getSslSocketFactory(app.getAssets().open("srca.cer"));
} catch (IOException e) {
e.printStackTrace();
}*/
// 方法四:使用bks证书和密码管理客户端证书(双向认证),使用预埋证书,校验服务端证书(自签名证书)
// HttpsUtils.SSLParams sslParams4 = HttpsUtils.getSslSocketFactory(getAssets().open("xxx.bks"), "123456", getAssets().open("yyy.cer"));
builder.sslSocketFactory(sslParams1.sSLSocketFactory, sslParams1.trustManager);
// 配置https的域名匹配规则,详细看demo的初始化介绍,不需要就不要加入,使用不当会导致https握手失败
builder.hostnameVerifier(new SafeHostnameVerifier());
return builder;
}
/**
* 获取默认的{@link OkHttpClient.Builder}
*
* 可以根据个人需要创建项目需求的Builder
*/
@SuppressWarnings("SameReturnValue")
protected abstract OkHttpClient.Builder getCustomBuilder();
/**
* 创建OkHttpClient
*/
public OkHttpClient build() {
OkHttpClient.Builder builder = getCustomBuilder();
if (builder == null) {
builder = getDefaultBuilder();
}
httpClient = builder.build();
return httpClient;
}
/**
* 获取OKHttp
*
* OkHttpClient
*/
public OkHttpClient getHttpClient() {
if (httpClient == null) {
throw new NullPointerException("OkHttpClient is null,you must call HttpConfig.build(); or set a OkHttpClient object first");
}
return httpClient;
}
public void setHttpClient(OkHttpClient httpClient) {
this.httpClient = httpClient;
}
/**
* 这里只是我谁便写的认证规则,具体每个业务是否需要验证,以及验证规则是什么,请与服务端或者leader确定
* 这里只是我谁便写的认证规则,具体每个业务是否需要验证,以及验证规则是什么,请与服务端或者leader确定
* 这里只是我谁便写的认证规则,具体每个业务是否需要验证,以及验证规则是什么,请与服务端或者leader确定
* 重要的事情说三遍,以下代码不要直接使用
*/
private static class SafeHostnameVerifier implements HostnameVerifier {
@SuppressLint("BadHostnameVerifier")
@Override
public boolean verify(String hostname, SSLSession session) {
// 验证主机名是否匹配
// return hostname.equals(RestApiPath.REST_URI_HOST);
return true;
}
}
}
================================================
FILE: aliocrlib/src/main/java/com/lib/aliocr/http/helper/HttpHelper.java
================================================
package com.lib.aliocr.http.helper;
import com.lib.aliocr.api.HttpCustomConfig;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
/**
* 作者:xin on 2018/7/9 0009 15:03
*
* 邮箱:ittfxin@126.com
*
* https://github.com/wzx54321/XinFrameworkLib
*/
public class HttpHelper {
private OkHttpClient mOkHttpClient;
private RxJava2CallAdapterFactory mAdapterFactory;
private GsonConverterFactory mGsonConverterFactory;
private HttpHelper() {
mGsonConverterFactory = GsonConverterFactory.create();
mAdapterFactory = RxJava2CallAdapterFactory.create();
//设置超时时间
mOkHttpClient = new HttpCustomConfig().build();
}
public static HttpHelper getInstance() {
return LazyHolder.INSTANCE;
}
public Retrofit getRetrofit(String url) {
return new Retrofit.Builder()
.baseUrl(url)
.addCallAdapterFactory(mAdapterFactory)
.addConverterFactory(mGsonConverterFactory)
.client(mOkHttpClient)
.build();
}
private static final class LazyHolder {
static final HttpHelper INSTANCE = new HttpHelper();
}
}
================================================
FILE: aliocrlib/src/main/java/com/lib/aliocr/http/https/HttpsUtils.java
================================================
package com.lib.aliocr.http.https;
import android.annotation.SuppressLint;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
/**
* 作者:xin on 2018/7/9 0009 15:03
*
* 邮箱:ittfxin@126.com
*
* https://github.com/wzx54321/XinFrameworkLib
*/
@SuppressWarnings("WeakerAccess")
public class HttpsUtils {
public static class SSLParams {
public SSLSocketFactory sSLSocketFactory;
public X509TrustManager trustManager;
}
public static SSLParams getSslSocketFactory() {
return getSslSocketFactoryBase(null, null, null);
}
/**
* https单向认证
* 可以额外配置信任服务端的证书策略,否则默认是按CA证书去验证的,若不是CA可信任的证书,则无法通过验证
*/
public static SSLParams getSslSocketFactory(X509TrustManager trustManager) {
return getSslSocketFactoryBase(trustManager, null, null);
}
/**
* https单向认证
* 用含有服务端公钥的证书校验服务端证书
*/
public static SSLParams getSslSocketFactory(InputStream... certificates) {
return getSslSocketFactoryBase(null, null, null, certificates);
}
/**
* https双向认证
* bksFile 和 password -> 客户端使用bks证书校验服务端证书
* certificates -> 用含有服务端公钥的证书校验服务端证书
*/
public static SSLParams getSslSocketFactory(InputStream bksFile, String password, InputStream... certificates) {
return getSslSocketFactoryBase(null, bksFile, password, certificates);
}
/**
* https双向认证
* bksFile 和 password -> 客户端使用bks证书校验服务端证书
* X509TrustManager -> 如果需要自己校验,那么可以自己实现相关校验,如果不需要自己校验,那么传null即可
*/
public static SSLParams getSslSocketFactory(InputStream bksFile, String password, X509TrustManager trustManager) {
return getSslSocketFactoryBase(trustManager, bksFile, password);
}
private static SSLParams getSslSocketFactoryBase(X509TrustManager trustManager, InputStream bksFile, String password, InputStream... certificates) {
SSLParams sslParams = new SSLParams();
try {
KeyManager[] keyManagers = prepareKeyManager(bksFile, password);
TrustManager[] trustManagers = prepareTrustManager(certificates);
X509TrustManager manager;
if (trustManager != null) {
//优先使用用户自定义的TrustManager
manager = trustManager;
} else if (trustManagers != null) {
//然后使用默认的TrustManager
manager = chooseTrustManager(trustManagers);
} else {
//否则使用不安全的TrustManager
manager = UnSafeTrustManager;
}
// 创建TLS类型的SSLContext对象, that uses our TrustManager
SSLContext sslContext = SSLContext.getInstance("TLS");
// 用上面得到的trustManagers初始化SSLContext,这样sslContext就会信任keyStore中的证书
// 第一个参数是授权的密钥管理器,用来授权验证,比如授权自签名的证书验证。第二个是被授权的证书管理器,用来验证服务器端的证书
sslContext.init(keyManagers, new TrustManager[]{manager}, null);
// 通过sslContext获取SSLSocketFactory对象
sslParams.sSLSocketFactory = sslContext.getSocketFactory();
sslParams.trustManager = manager;
return sslParams;
} catch (NoSuchAlgorithmException | KeyManagementException e) {
throw new AssertionError(e);
}
}
private static KeyManager[] prepareKeyManager(InputStream bksFile, String password) {
try {
if (bksFile == null || password == null) return null;
KeyStore clientKeyStore = KeyStore.getInstance("BKS");
clientKeyStore.load(bksFile, password.toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(clientKeyStore, password.toCharArray());
return kmf.getKeyManagers();
} catch (Exception e) {
Log.e("net","Https#prepareKeyManager error",e);
}
return null;
}
private static TrustManager[] prepareTrustManager(InputStream... certificates) {
if (certificates == null || certificates.length <= 0) return null;
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
// 创建一个默认类型的KeyStore,存储我们信任的证书
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
int index = 0;
for (InputStream certStream : certificates) {
String certificateAlias = Integer.toString(index++);
// 证书工厂根据证书文件的流生成证书 cert
Certificate cert = certificateFactory.generateCertificate(certStream);
// 将 cert 作为可信证书放入到keyStore中
keyStore.setCertificateEntry(certificateAlias, cert);
try {
if (certStream != null) certStream.close();
} catch (IOException e) {
Log.e("net","Https#prepareTrustManager error",e);
}
}
//我们创建一个默认类型的TrustManagerFactory
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
//用我们之前的keyStore实例初始化TrustManagerFactory,这样tmf就会信任keyStore中的证书
tmf.init(keyStore);
//通过tmf获取TrustManager数组,TrustManager也会信任keyStore中的证书
return tmf.getTrustManagers();
} catch (Exception e) {
Log.e("net","Https#prepareTrustManager error",e);
}
return null;
}
private static X509TrustManager chooseTrustManager(TrustManager[] trustManagers) {
for (TrustManager trustManager : trustManagers) {
if (trustManager instanceof X509TrustManager) {
return (X509TrustManager) trustManager;
}
}
return null;
}
/**
* 为了解决客户端不信任服务器数字证书的问题,网络上大部分的解决方案都是让客户端不对证书做任何检查,
* 这是一种有很大安全漏洞的办法
*/
public static X509TrustManager UnSafeTrustManager = new X509TrustManager() {
@SuppressLint("TrustAllX509TrustManager")
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@SuppressLint("TrustAllX509TrustManager")
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
};
/**
* 此类是用于主机名验证的基接口。 在握手期间,如果 URL 的主机名和服务器的标识主机名不匹配,
* 则验证机制可以回调此接口的实现程序来确定是否应该允许此连接。策略可以是基于证书的或依赖于其他验证方案。
* 当验证 URL 主机名使用的默认规则失败时使用这些回调。如果主机名是可接受的,则返回 true
*/
public static HostnameVerifier UnSafeHostnameVerifier = new HostnameVerifier() {
@SuppressLint("BadHostnameVerifier")
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
}
================================================
FILE: aliocrlib/src/main/java/com/lib/aliocr/http/interceptor/HttpLog.java
================================================
package com.lib.aliocr.http.interceptor;
import android.support.annotation.NonNull;
import android.util.Log;
import com.lib.aliocr.utils.io.IOUtils;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;
import okhttp3.Connection;
import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.internal.http.HttpHeaders;
import okio.Buffer;
/**
* 作者:xin on 2018/7/9 0009 15:03
*
* 邮箱:ittfxin@126.com
*
* https://github.com/wzx54321/XinFrameworkLib
*/
public class HttpLog implements Interceptor {
private boolean isPrintBinaryBody;
public enum Level {
NONE, //不打印log
BASIC, //只打印 请求首行 和 响应首行
HEADERS, //打印请求和响应的所有 Header
BODY //所有数据全部打印
}
private volatile Level printLevel = Level.NONE;
public void setPrintLevel(Level printLevel) {
this.printLevel = printLevel;
}
public void setPrintBinaryBody(boolean printBinaryBody) {
isPrintBinaryBody = printBinaryBody;
}
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
Request request = chain.request();
if (printLevel == Level.NONE) {
return chain.proceed(request);
}
//请求日志拦截
logForRequest(request, chain.connection());
// 执行请求,计算请求时间
long startNs = System.nanoTime();
Response response;
try {
response = chain.proceed(request);
} catch (Exception e) {
// Log.e(e, "<-- HTTP FAILED: ");
throw e;
}
long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);
//响应日志拦截
return logForResponse(response, tookMs);
}
private void logForRequest(Request request, Connection connection) {
boolean logBody = (printLevel == Level.BODY);
boolean logHeaders = (printLevel == Level.BODY || printLevel == Level.HEADERS);
RequestBody requestBody = request.body();
boolean hasRequestBody = requestBody != null;
Protocol protocol = connection != null ? connection.protocol() : Protocol.HTTP_1_1;
StringBuilder requestMessage = new StringBuilder();
try {
requestMessage.append("--> ").append(request.method()).append(' ').append(request.url()).append(' ').append(protocol).append("\n");
if (logHeaders) {
if (hasRequestBody) {
// Request body headers are only present when installed as a network interceptor. Force
// them to be included (when available) so there values are known.
if (requestBody.contentType() != null) {
requestMessage.append("\tContent-Type: ").append(requestBody.contentType()).append("\n");
}
if (requestBody.contentLength() != -1) {
requestMessage.append("\tContent-Length: ").append(requestBody.contentLength()).append("\n");
}
}
Headers headers = request.headers();
for (int i = 0, count = headers.size(); i < count; i++) {
String name = headers.name(i);
// Skip headers from the request body as they are explicitly logged above.
if (!"Content-Type".equalsIgnoreCase(name) && !"Content-Length".equalsIgnoreCase(name)) {
requestMessage.append("\t").append(name).append(": ").append(headers.value(i)).append("\n");
}
}
if (logBody && hasRequestBody) {
if (isPlaintext(requestBody.contentType())) {
requestMessage.append(bodyToString(request));
} else {
requestMessage.append("\tbody: maybe [binary body], omitted!\n");
}
}
}
} catch (Exception e) {
Log.e("orc", "intercept");
} finally {
requestMessage.append("--> END ").append(request.method());
Log.i("HTTPLOG", requestMessage.toString());
}
}
private Response logForResponse(Response response, long tookMs) {
StringBuilder responseMsg = new StringBuilder();
Response.Builder builder = response.newBuilder();
Response clone = builder.build();
ResponseBody responseBody = clone.body();
boolean logBody = (printLevel == Level.BODY);
boolean logHeaders = (printLevel == Level.BODY || printLevel == Level.HEADERS);
try {
responseMsg.append("<-- ").append(clone.code()).append(' ').append(clone.message()).append(' ').append(clone.request().url()).append(" (").append(tookMs).append("ms)" + "\n");
if (logHeaders) {
Headers headers = clone.headers();
for (int i = 0, count = headers.size(); i < count; i++) {
responseMsg.append("\t").append(headers.name(i)).append(": ").append(headers.value(i)).append("\n");
}
if (logBody && HttpHeaders.hasBody(clone)) {
if (responseBody == null) return response;
if (isPrintBinaryBody || isPlaintext(responseBody.contentType())) {
byte[] bytes = IOUtils.toByteArray(responseBody.byteStream());
MediaType contentType = responseBody.contentType();
String body = new String(bytes, getCharset(contentType));
responseMsg.append("\tbody:").append(body);
responseBody = ResponseBody.create(responseBody.contentType(), bytes);
return response.newBuilder().body(responseBody).build();
} else {
responseMsg.append("\tbody: maybe [binary body], omitted! \n if you want to log it please call set isPrintBinaryBody is true");
}
}
}
} catch (Exception e) {
Log.e("", "logForResponse error");
} finally {
responseMsg.append("<-- END HTTP");
Log.i("HTTPLOG", responseMsg.toString());
}
return response;
}
/**
* Returns true if the body in question probably contains human readable text. Uses a small sample
* of code points to detect unicode control characters commonly used in binary file signatures.
*/
private static boolean isPlaintext(MediaType mediaType) {
if (mediaType == null) return false;
if (mediaType.type() != null && mediaType.type().equals("text")) {
return true;
}
String subtype = mediaType.subtype();
if (subtype != null) {
subtype = subtype.toLowerCase();
if (subtype.contains("x-www-form-urlencoded") || subtype.contains("json") || subtype.contains("xml") || subtype.contains("html")) //
return true;
}
return false;
}
private String bodyToString(Request request) {
try {
Request copy = request.newBuilder().build();
RequestBody body = copy.body();
if (body == null) return "";
Buffer buffer = new Buffer();
body.writeTo(buffer);
Charset charset = getCharset(body.contentType());
return "\tbody:" + buffer.readString(charset) + "\n";
} catch (Exception e) {
Log.e("", "bodyToString error");
}
return "";
}
private static Charset getCharset(MediaType contentType) {
Charset charset = contentType != null ? contentType.charset(UTF8) : UTF8;
if (charset == null) charset = UTF8;
return charset;
}
private static final Charset UTF8 = Charset.forName("UTF-8");
}
================================================
FILE: aliocrlib/src/main/java/com/lib/aliocr/modle/OCRModel.java
================================================
package com.lib.aliocr.modle;
import com.google.gson.Gson;
import com.lib.aliocr.api.MyApiManager;
import com.lib.aliocr.bean.RepOutput;
import com.lib.aliocr.bean.ReqInput;
import com.lib.aliocr.common.Api;
import com.lib.aliocr.contact.OcrContact;
import com.lib.aliocr.http.helper.HttpHelper;
import com.lib.aliocr.utils.OcrUtils;
import org.json.JSONObject;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.functions.Function;
import okhttp3.RequestBody;
/**
* 作者:xin on 2018/7/9 0009 15:03
*
* 邮箱:ittfxin@126.com
*
* https://github.com/wzx54321/XinFrameworkLib
*/
public class OCRModel implements OcrContact.M{
public Observable
* 邮箱:ittfxin@126.com
*
* https://github.com/wzx54321/XinFrameworkLib
*/
public class OCRPresenter implements OcrContact.P {
private OcrContact.M model;
private OcrContact.V view;
private static final String TAG = OCRMainActivity.class.getSimpleName();
public OCRPresenter(OcrContact.V view) {
this.view = view;
model = new OCRModel();
}
public void onPictureTaken(final byte[] data) {
Disposable disposable= Observable .create(new ObservableOnSubscribe
* 邮箱:ittfxin@126.com
*
* https://github.com/wzx54321/XinFrameworkLib
*/
public class Base64 {
public static String getAuthor(String secretKey,String author) {
byte[] data = null;
String s = secretKey + author;
try {
data = s.getBytes();
} catch (Exception e) {
e.printStackTrace();
}
// 加密
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data != null ? data : new byte[0]);
}
}
================================================
FILE: aliocrlib/src/main/java/com/lib/aliocr/utils/Ocr.java
================================================
package com.lib.aliocr.utils;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.view.Gravity;
import android.view.View;
import android.widget.AdapterView;
import com.lib.aliocr.callback.OcrCallback;
import com.lib.aliocr.view.OCRMainActivity;
import com.lib.aliocr.widget.crop.Crop;
import com.lib.aliocr.widget.popup.XinPopWindow;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* 作者:xin on 2018/7/9 0009 15:03
*
* 邮箱:ittfxin@126.com
*
* https://github.com/wzx54321/XinFrameworkLib
*/
public class Ocr {
private static final int PICK_IMAGE_CHOOSER_REQUEST_CODE = 222;
private static final int PICK_IMAGE_PERMISSIONS_REQUEST_CODE = 222222;
private static final int IMAGE_CROP_CODE = 3333;
/**
* 发起验证
*
* @param activity
* @param rootView
*/
public static void doOcr(final Activity activity, final Fragment fragment, final View rootView, final boolean isFace) {
List
* 邮箱:ittfxin@126.com
*
* https://github.com/wzx54321/XinFrameworkLib
*/
@SuppressWarnings("ResultOfMethodCallIgnored")
public class OcrUtils {
public static String getImageStr(String imgFile) {
InputStream inputStream;
byte[] data = null;
try {
inputStream = new FileInputStream(imgFile);
data = new byte[inputStream.available()];
inputStream.read(data);
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
// 加密
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data);
}
public static Bitmap byte2bitmap(byte[] data) {
if (null == data) {
return null;
}
return BitmapFactory.decodeByteArray(data,
0,
data.length);
}
public static boolean saveBitmap(Bitmap bitmap,
String path) {
return saveBitmap(bitmap,
path,
100);
}
/**
* 将bitmap位图保存到path路径下,图片格式为Bitmap.CompressFormat.JPEG,质量为100
*
* @param bitmap
* @param path
* @param quality 压缩的比率(1-100)
*/
@SuppressWarnings("ResultOfMethodCallIgnored")
public static boolean saveBitmap(Bitmap bitmap,
String path,
int quality) {
try {
File file = new File(path);
File parent = file.getParentFile();
if (!parent.exists()) {
parent.mkdirs();
}
// if(file.exists()){
// FileUtil.deleteFile(file);
// }
FileOutputStream fos = new FileOutputStream(file);
boolean b = bitmap.compress(Bitmap.CompressFormat.JPEG,
quality,
fos);
fos.flush();
fos.close();
return b;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.isRecycled();
}
}
return false;
}
/**
* 图片压缩并保存到文件(是否压缩都保存)
*/
public static boolean compressSmallImage(Bitmap image,
File file,
int kb) {
return compressSmallImage(image,
file,
kb,
true);
}
/**
* 图片压缩并保存到文件
*
* @param image 源文件
* @param file 要保存到的file
* @param kb 限制的size
* @param iSsaveFile (可为false,如File已存在但无压缩的情况下可设置为false)
* @return 是否存储了文件
*/
@SuppressWarnings("ResultOfMethodCallIgnored")
public static boolean compressSmallImage(Bitmap image,
File file,
int kb,
boolean iSsaveFile) {
if (image == null)
return false;
Boolean isCompressed = false;
boolean isSaveFileSuccessed = false;// 是否存储成功了文件夹
File parent = file.getParentFile();
if (!parent.exists()) {
parent.mkdirs();
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream out = null;
image.compress(Bitmap.CompressFormat.JPEG,
100,
baos);
int options = 100;
Bitmap temp;
while ((baos.size() <= 0 ? baos.toByteArray().length : baos.size()) / 1024 > kb) {
isCompressed = true;
baos.reset();
options -= 10;// 每次都减少10
image.compress(Bitmap.CompressFormat.JPEG,
options,
baos);
}
byte[] byteArray = baos.toByteArray();
try {
// 不管有无压缩,都写入文件
if (iSsaveFile) {
out = new FileOutputStream(file);
out.write(byteArray,
0,
byteArray.length);
isSaveFileSuccessed = true;
} else {
// iSsaveFile==false 时,只有压缩后写入文件
if (isCompressed) {
out = new FileOutputStream(file);
out.write(byteArray,
0,
byteArray.length);
isSaveFileSuccessed = true;
}
}
} catch (Exception e) {
} finally {
try {
if (out != null) {
out.close();
}
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (isSaveFileSuccessed) {
}
return isSaveFileSuccessed;
}
public static String getPath(Context context,
Uri uri) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (DocumentsContract.isDocumentUri(context, uri)) {
String docId;
String[] split;
String type;
if (isExternalStorageDocument(uri)) {
docId = DocumentsContract.getDocumentId(uri);
split = docId.split(":");
type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
} else {
if (isDownloadsDocument(uri)) {
docId = DocumentsContract.getDocumentId(uri);
Uri split1 = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"),
Long.valueOf(docId));
return getDataColumn(context,
split1,
null,
null);
}
if (isMediaDocument(uri)) {
docId = DocumentsContract.getDocumentId(uri);
split = docId.split(":");
type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
String selection = "_id=?";
String[] selectionArgs = new String[]{split[1]};
return getDataColumn(context,
contentUri,
"_id=?",
selectionArgs);
}
}
}
}
if ("content".equalsIgnoreCase(uri.getScheme())) {
if (isGooglePhotosUri(uri)) {
return uri.getLastPathSegment();
}
return getDataColumn(context,
uri,
null,
null);
}
if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
public static String getDataColumn(Context context,
Uri uri,
String selection,
String[] selectionArgs) {
Cursor cursor = null;
String column = "_data";
String[] projection = new String[]{"_data"};
try {
cursor = context.getContentResolver()
.query(uri,
projection,
selection,
selectionArgs,
null);
if (cursor != null && cursor.moveToFirst()) {
int index = cursor.getColumnIndexOrThrow("_data");
String var9 = cursor.getString(index);
return var9;
}
} finally {
if (cursor != null) {
cursor.close();
}
}
return null;
}
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
public static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
private static Intent getGalleryIntent(Context context, boolean includeDocuments) {
PackageManager packageManager = context.getPackageManager();
List
* 邮箱:ittfxin@126.com
*
* https://github.com/wzx54321/XinFrameworkLib
*/
@SuppressWarnings("WeakerAccess")
public class FileUtil {
private static final String TAG = "FileUtil";
public static final int DEFAULT_BUFFER_SIZE = 8 * 1024;
/*
********************************************读写***************************
*/
/**
* Returns a human-readable version of the file size, where the input
* represents a specific number of bytes.
*
* @param size the number of bytes
* @return a human-readable display value (includes units)
*/
public static String formatSize(long size) {
float ONE_KB = 1024F;
float ONE_MB = ONE_KB * ONE_KB;
float ONE_GB = ONE_KB * ONE_MB;
String displaySize;
DecimalFormat df = new DecimalFormat("0.0");
if (size >= ONE_KB && size < ONE_MB) {
displaySize = String.valueOf(df.format(size / ONE_KB)) + " KB";
} else if (size >= ONE_MB && size < ONE_GB) {
displaySize = String.valueOf(df.format(size / ONE_MB)) + " MB";
} else if (size >= ONE_GB) {
displaySize = String.valueOf(df.format(size / ONE_GB)) + " GB";
} else if (size == 0) {
displaySize = " 0KB";
} else {
displaySize = "1KB";
Log.d("formatSize",
String.valueOf(df.format(size)) + " B");
}
/*
* else {
* displaySize = String.valueOf(df.format(size)) + " B";
* }
*/
return displaySize;
}
/**
* 递归删除文件目录
*
* @param dir 文件目录
*/
@SuppressWarnings("ResultOfMethodCallIgnored")
public static void deleteFileDir(File dir) {
Log.d(TAG,
"deleteFileDir.dir = " + dir);
try {
if (dir.exists() && dir.isDirectory()) {// 判断是文件还是目录
if (dir.listFiles().length == 0) {// 若目录下没有文件则直接删除
dir.delete();
} else {// 若有则把文件放进数组,并判断是否有下级目录
File delFile[] = dir.listFiles();
int len = dir.listFiles().length;
for (int j = 0; j < len; j++) {
if (delFile[j].isDirectory()) {
deleteFileDir(delFile[j]);// 递归调用deleteFileDir方法并取得子目录路径
} else {
boolean isDel = delFile[j].delete();// 删除文件
Log.d(TAG,
"deleteFileDir.delFile[" + j + "] = " + delFile[j] + ", isDelete = " + isDel);
}
}
}
deleteFileDir(dir);// 递归调用
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 删除单个文件
*
* @param file 文件目录
*/
@SuppressWarnings("ResultOfMethodCallIgnored")
public static void deleteFile(File file) {
try {
Log.d(TAG,
"deleteFile.file = " + file);
if (file != null && file.isFile() && file.exists()) {
file.delete();
Log.d(TAG,
"deleteFile.file = " + file + " Succeed");
}
} catch (Exception e) {
e.printStackTrace();
Log.d(TAG,
"deleteFile.file = " + file + " exception=" + e.toString());
}
}
/**
* 读取指定文件的输出
*/
public static byte[] getFileOutputBytes(String filePath) {
byte[] buffer = null;
try {
File file = new File(filePath);
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
byte[] b = new byte[1000];
int n;
while ((n = fis.read(b)) != -1) {
bos.write(b,
0,
n);
}
fis.close();
bos.close();
buffer = bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return buffer;
}
/**
* 读取文件内容到字节数组
*
* @param file
* @return
*/
public static byte[] getFileOutputBytes(File file) {
byte[] bytes = null;
if (file.exists()) {
byte[] buffer;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
ByteArrayOutputStream byteArrayOutputStream = null;
try {
bis = new BufferedInputStream(new FileInputStream(file),
DEFAULT_BUFFER_SIZE);
byteArrayOutputStream = new ByteArrayOutputStream();
bos = new BufferedOutputStream(byteArrayOutputStream,
DEFAULT_BUFFER_SIZE);
buffer = new byte[DEFAULT_BUFFER_SIZE];
int len;
while ((len = bis.read(buffer,
0,
DEFAULT_BUFFER_SIZE)) != -1) {
bos.write(buffer,
0,
len);
}
bos.flush();
bytes = byteArrayOutputStream.toByteArray();
} catch (Exception e) {
return null;
} finally {
try {
if (bos != null) {
bos.close();
}
if (byteArrayOutputStream != null) {
byteArrayOutputStream.close();
}
if (bis != null) {
bis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Log.d(TAG,
"getFileOutputBytes.file = " + file + ", bytes.length = " + (bytes == null ? 0 : bytes.length));
return bytes;
}
/**
* 读取文件内容到字节数组
*
* @param file
* @param offset
* @param len
* @return
*/
public static byte[] getFileOutputBytes(File file,
long offset,
long len) {
byte[] bytes = null;
if (file.exists() && offset >= 0 && len > offset && offset < file.length()) {
RandomAccessFile raf = null;
ByteArrayOutputStream bos = null;
try {
raf = new RandomAccessFile(file,
"r");
raf.seek(offset);
bos = new ByteArrayOutputStream();
int b;
long count = offset;
while ((b = raf.read()) != -1 && count < len) {
bos.write(b);
count++;
}
bos.flush();
bytes = bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (raf != null) {
raf.close();
}
if (bos != null) {
bos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
return bytes;
}
/**
* 读取指定文件的输出
*/
public static String getFileOutputString(String path) {
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader(path), 8192);
StringBuilder sb = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
sb.append("\n").append(line);
}
bufferedReader.close();
return sb.toString();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 读取指定文件的输出
*
* @param file
* @param encoding
* @return
*/
public static String getFileOutputString(File file,
String encoding) {
String result = null;
if (file.exists()) {
char[] buffer;
BufferedReader br = null;
InputStreamReader isr = null;
BufferedWriter bw = null;
StringWriter sw = new StringWriter();
try {
isr = encoding == null ? new InputStreamReader(new FileInputStream(file)) : new InputStreamReader(new FileInputStream(file),
encoding);
br = new BufferedReader(isr);
bw = new BufferedWriter(sw);
buffer = new char[DEFAULT_BUFFER_SIZE];
int len;
while ((len = br.read(buffer,
0,
DEFAULT_BUFFER_SIZE)) != -1) {
bw.write(buffer,
0,
len);
}
bw.flush();
result = sw.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bw != null) {
bw.close();
}
if (br != null) {
br.close();
}
if (isr != null) {
isr.close();
}
sw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Log.d(TAG,
"readFileToString.file = " + file + ", encoding = " + encoding + ", result = " + result);
return result;
}
/**
* 将字节写入到文件
*
* @param file
* @param bytes
* @param offset
* @return
*/
public static boolean writeBytesToFile(File file,
byte[] bytes,
long offset) {
boolean isOk = false;
if (!file.exists()) {
try {
// noinspection ResultOfMethodCallIgnored
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
if (file.exists() && bytes != null && offset >= 0) {
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile(file,
"rw");
raf.seek(offset);
raf.write(bytes);
isOk = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (raf != null) {
raf.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
return isOk;
}
/**
* 写字符串到文件,文件父目录如果不存在,会自动创建
*
* @param file
* @param content
* @return
*/
public static boolean writeStringToFile(File file,
String content) {
return writeStringToFile(file,
content,
false);
}
/**
* 写字符串到文件,文件父目录如果不存在,会自动创建
*
* @param file
* @param content
* @param isAppend
* @return
*/
public static boolean writeStringToFile(File file,
String content,
boolean isAppend) {
boolean isWriteOk = false;
if (TextUtils.isEmpty(content))
return false;
char[] buffer;
int count = 0;
BufferedReader br = null;
BufferedWriter bw = null;
try {
if (!file.exists()) {
createNewFileAndParentDir(file);
}
if (file.exists()) {
br = new BufferedReader(new StringReader(content));
bw = new BufferedWriter(new FileWriter(file,
isAppend));
buffer = new char[DEFAULT_BUFFER_SIZE];
int len;
while ((len = br.read(buffer,
0,
DEFAULT_BUFFER_SIZE)) != -1) {
bw.write(buffer,
0,
len);
count += len;
}
bw.flush();
}
isWriteOk = content.length() == count;
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bw != null) {
bw.close();
}
if (br != null) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return isWriteOk;
}
/**
* 写字节数组到文件,文件父目录如果不存在,会自动创建
*
* @param file
* @param bytes
* @return
*/
public static boolean writeBytesToFile(File file,
byte[] bytes) {
return writeBytesToFile(file,
bytes,
false);
}
/**
* 写字节数组到文件,文件父目录如果不存在,会自动创建
*
* @param file
* @param bytes
* @param isAppend
* @return
*/
public static boolean writeBytesToFile(File file,
byte[] bytes,
boolean isAppend) {
boolean isWriteOk = false;
byte[] buffer;
int count = 0;
ByteArrayInputStream byteArrayInputStream = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
if (!file.exists()) {
createNewFileAndParentDir(file);
}
if (file.exists()) {
bos = new BufferedOutputStream(new FileOutputStream(file,
isAppend),
DEFAULT_BUFFER_SIZE);
byteArrayInputStream = new ByteArrayInputStream(bytes);
bis = new BufferedInputStream(byteArrayInputStream,
DEFAULT_BUFFER_SIZE);
buffer = new byte[DEFAULT_BUFFER_SIZE];
int len;
while ((len = bis.read(buffer,
0,
DEFAULT_BUFFER_SIZE)) != -1) {
bos.write(buffer,
0,
len);
count += len;
}
bos.flush();
}
isWriteOk = bytes.length == count;
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bos != null) {
bos.close();
}
if (bis != null) {
bis.close();
}
if (byteArrayInputStream != null) {
byteArrayInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
Log.d(TAG,
"writeByteArrayToFile.file = " + file + ", bytes.length = " + (bytes == null ? 0 : bytes.length) + ", isAppend = " + isAppend + ", isWriteOk = " + isWriteOk);
return isWriteOk;
}
/**
* ********************************************创建***************************
* /**
* 创建目录
*
* @param dir
* @return
*/
public static boolean createDir(File dir) {
boolean isMkdirs = true;
if (!dir.exists()) {
isMkdirs = dir.mkdirs();
Log.d(TAG,
"createDir = " + dir + ", isMkdirs = " + isMkdirs);
}
return isMkdirs;
}
/**
* 创建文件父目录
*
* @param file
* @return
*/
public static boolean createParentDir(File file) {
boolean isMkdirs = true;
if (!file.exists()) {
File dir = file.getParentFile();
isMkdirs = createDir(dir);
}
return isMkdirs;
}
/**
* 创建文件及其父目录
*
* @param file
* @return
*/
@SuppressWarnings("UnusedReturnValue")
public static boolean createNewFileAndParentDir(File file) {
@SuppressWarnings("UnusedAssignment")
boolean isCreateNewFileOk = true;
isCreateNewFileOk = createParentDir(file);
// 创建父目录失败,直接返回false,不再创建子文件
if (isCreateNewFileOk) {
if (!file.exists()) {
try {
isCreateNewFileOk = file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
isCreateNewFileOk = false;
}
}
}
return isCreateNewFileOk;
}
/**
* 根据文件名称获取文件的后缀字符串
*
* @param filename 文件的名称,可能带路径
* @return 文件的后缀字符串
*/
public static String getFileExtensionFromUrl(String filename) {
if (!TextUtils.isEmpty(filename)) {
int dotPos = filename.lastIndexOf('.');
if (0 <= dotPos) {
return filename.substring(dotPos + 1);
}
}
return "";
}
/**
* 拷贝文件
*
* @param sourceFile 源文件
* @param destFile 目标文件
* @return 是否拷贝成功
*/
@SuppressWarnings("ResultOfMethodCallIgnored")
public static boolean copyFile(File sourceFile,
File destFile) {
boolean isCopyOk = false;
byte[] buffer;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
// 如果此时没有文件夹目录就创建
String canonicalPath = "";
try {
canonicalPath = destFile.getCanonicalPath();
} catch (IOException e) {
e.printStackTrace();
}
if (!destFile.exists()) {
if (canonicalPath.lastIndexOf(File.separator) >= 0) {
canonicalPath = canonicalPath.substring(0,
canonicalPath.lastIndexOf(File.separator));
File dir = new File(canonicalPath);
if (!dir.exists()) {
dir.mkdirs();
}
}
}
try {
bis = new BufferedInputStream(new FileInputStream(sourceFile),
DEFAULT_BUFFER_SIZE);
bos = new BufferedOutputStream(new FileOutputStream(destFile),
DEFAULT_BUFFER_SIZE);
buffer = new byte[DEFAULT_BUFFER_SIZE];
int len;
while ((len = bis.read(buffer,
0,
DEFAULT_BUFFER_SIZE)) != -1) {
bos.write(buffer,
0,
len);
}
bos.flush();
isCopyOk = sourceFile.length() == destFile.length();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bos != null) {
bos.close();
}
if (bis != null) {
bis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
Log.d(TAG,
"copyFile.sourceFile = " + sourceFile + ", destFile = " + destFile + ", isCopyOk = " + isCopyOk);
return isCopyOk;
}
/*** 获取文件夹大小 ***/
public static long getFileSize(File f) {
long size = 0;
try {
File fList[] = f.listFiles();
for (File file : fList) {
if (file.isDirectory()) {
size = size + getFileSize(file);
} else {
size = size + file.length();
}
}
return size;
} catch (Exception e) {
return size;
}
}
/**
* 获取内存设置
*
* @param context
* @return
*/
public static int getMemoryCacheSize(Context context) {
int memoryCacheSize = 0;
ActivityManager manager = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE));
int memClass;
if (manager != null){
memClass = manager.getMemoryClass();
memoryCacheSize = (memClass / 3) * 1024 * 1024; // 1/3 of app memory
}
// limit
return memoryCacheSize;
}
/* /**
* 保存APP资源文件到文件系统
*
* @param resID drawable 资源文件
* @param defineName 定义的文件名
* @return 文件路径
*/
/*public static String saveResImgToFile(int resID,
String defineName) {
String path = null;
try {
File Dir = FileConfig.getScreenShortCutDir();
path = Dir.getAbsolutePath() + File.separator + defineName;
File file = new File(path);
// 文件已存在
Bitmap bitmap = BitmapFactory.decodeResource(WithinApplication.getAppContext()
.getResources(),
resID);
boolean isCompressed = ImageUtil.compressSmallImage(bitmap,
file,
FileConfig.FEED_TEMP_PIC_MAX_SIZE);
if (!bitmap.isRecycled()) {
bitmap.recycle();
}
if (isCompressed) {
return file.getAbsolutePath();
}
} catch (Exception e) {
e.printStackTrace();
}
return path;
}
*/
/**
* 如果存在就文件名追加(count),如report(1)
*
* @param file
* @return
*/
public static File formatDownloadFileName(File file) {
if (file.getName()
.contains(".")) {
String postfix = file.getName()
.substring(file.getName()
.lastIndexOf("."));
if (file.exists() && file.getParentFile()
.exists()) {
int count = 0;
for (File child : file.getParentFile()
.listFiles()) {
if (child.getName()
.contains(file.getName()
.replace(postfix,
""))) {
count++;
}
}
String fileName = String.format(file.getName()
.replace(postfix,
"") +
"(%d)",
count) +
postfix;
file = new File(file.getParentFile(),
fileName);
}
}
return file;
}
public static Intent getFileIntent(File file) {
Uri uri = Uri.fromFile(file);
String type = getMIMEType(file);
Log.i("tag",
"type=" + type);
Intent intent = new Intent("android.intent.action.VIEW");
intent.addCategory("android.intent.category.DEFAULT");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(uri,
type);
return intent;
}
public static String getMIMEType(File f) {
@SuppressWarnings("UnusedAssignment")
String type = "";
String fName = f.getName();
/* 取得扩展名 */
String end = fName.substring(fName.lastIndexOf(".") + 1,
fName.length())
.toLowerCase();
/* 依扩展名的类型决定MimeType */
switch (end) {
case "pdf":
type = "application/pdf";//
break;
case "m4a":
case "mp3":
case "mid":
case "xmf":
case "ogg":
case "wav":
type = "audio/*";
break;
case "3gp":
case "mp4":
type = "video/*";
break;
case "jpg":
case "gif":
case "png":
case "jpeg":
case "bmp":
type = "image/*";
break;
case "apk":
/* android.permission.INSTALL_PACKAGES */
type = "application/vnd.android.package-archive";
break;
case "pptx":
case "ppt":
type = "application/vnd.ms-powerpoint";
break;
case "docx":
case "doc":
type = "application/vnd.ms-word";
break;
case "xlsx":
case "xls":
type = "application/vnd.ms-excel";
break;
case "txt":
type = "text/plain";
break;
default:
/* 如果无法直接打开,就跳出软件列表给用户选择 */
type = "*/*";
break;
}
return type;
}
public static int clearCacheFolder(final File dir,
final int numDays) {
int deletedFiles = 0;
if (dir != null && dir.isDirectory()) {
try {
for (File child : dir.listFiles()) {
// first delete subdirectories recursively
if (child.isDirectory()) {
deletedFiles += clearCacheFolder(child,
numDays);
}
// then delete the files and subdirectories in this dir
// only empty directories can be deleted, so subDirs have
// been done first
if (child.lastModified() < new Date().getTime() - numDays * DateUtils.DAY_IN_MILLIS) {
if (child.delete()) {
deletedFiles++;
}
}
}
} catch (Exception e) {
}
}
return deletedFiles;
}
@SuppressWarnings("ResultOfMethodCallIgnored")
public static String getDiskCacheDir(Context context,
String uniqueName) {
// 检查是否安装或存储媒体是内置的,如果是这样的话,试着使用外部缓存dir否则使用内部缓存目录
boolean isMounted = SdCardUtil.isSdCardAvailable();
File cacheFile;
if (isMounted) {
cacheFile = getExternalCacheDir(context);
if (!cacheFile.exists()) {
cacheFile.mkdirs();
}
if (!cacheFile.canWrite()) {
cacheFile = context.getCacheDir();
}
} else {
cacheFile = context.getCacheDir();
}
File file = new File(cacheFile.getPath() + File.separator + uniqueName);
if (!file.exists()) {
file.mkdirs();
}
return file.getAbsolutePath();
}
/**
* 获取外设的缓存目录:Android/data/cache....
* This method buffers the input internally, so there is no need to use a
*
* This method buffers the input internally, so there is no need to use a
*
* Due to the implementation of OutputStreamWriter, this method performs a
* flush.
*
* This method uses {@link OutputStreamWriter}.
*
* 邮箱:ittfxin@126.com
*
* https://github.com/wzx54321/XinFrameworkLib
*/
public class SdCardUtil {
private static final String TAG = SdCardUtil.class.getSimpleName();
/**
* is sd card available.
* @return true if available
*/
public static boolean isSdCardAvailable() {
return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
}
/**
* Get {@link StatFs}.
*/
public static StatFs getStatFs(String path) {
return new StatFs(path);
}
/**
* Get phone data path.
*/
public static String getDataPath() {
return Environment.getDataDirectory().getPath();
}
/**
* Get SD card path.
*/
public static String getNormalSDCardPath() {
return Environment.getExternalStorageDirectory().getPath();
}
/**
* Get SD card path by CMD.
*/
public static String getSDCardPath() {
String cmd = "cat /proc/mounts";
String sdcard;
Runtime run = Runtime.getRuntime();// 返回与当前 Java 应用程序相关的运行时对象
BufferedReader bufferedReader = null;
try {
Process p = run.exec(cmd);// 启动另一个进程来执行命令
bufferedReader = new BufferedReader(new InputStreamReader(new BufferedInputStream(p.getInputStream())));
String lineStr;
while ((lineStr = bufferedReader.readLine()) != null) {
if (lineStr.contains("sdcard")
&& lineStr.contains(".android_secure")) {
String[] strArray = lineStr.split(" ");
if (strArray.length >= 5) {
sdcard = strArray[1].replace("/.android_secure", "");
return sdcard;
}
}
if (p.waitFor() != 0 && p.exitValue() == 1) {
// p.exitValue()==0表示正常结束,1:非正常结束
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (bufferedReader != null) {
bufferedReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
sdcard = Environment.getExternalStorageDirectory().getPath();
return sdcard;
}
/**
* Get SD card path list.
*/
public static ArrayList
* 邮箱:ittfxin@126.com
*
* https://github.com/wzx54321/XinFrameworkLib
*/
public class StringCodingUtils {
public static byte[] getBytes(String src, Charset charSet) {
return src.getBytes(charSet);
}
}
================================================
FILE: aliocrlib/src/main/java/com/lib/aliocr/utils/stream/ByteArrayOutputStream.java
================================================
package com.lib.aliocr.utils.stream;
import android.support.annotation.NonNull;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.SequenceInputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* This class implements an output stream in which the data is
* written into a byte array. The buffer automatically grows as data
* is written to it.
*
* The data can be retrieved using
* Closing a ByteArrayOutputStream has no effect. The methods in
* this class can be called after the stream has been closed without
* generating an IOException.
*
* This is an alternative implementation of the {@link java.io.ByteArrayOutputStream}
* class. The original implementation only allocates 32 bytes at the beginning.
* As this class is designed for heavy duty it starts at 1024 bytes. In contrast
* to the original it doesn't reallocate the whole memory block but allocates
* additional buffers. This way no buffers need to be garbage collected and
* the contents don't have to be copied to the new buffer. This class is
* designed to behave exactly like the original. The only exception is the
* deprecated toString(int) method that has been ignored.
*
* @version $Id: ByteArrayOutputStream.java 1304052 2012-03-22 20:55:29Z ggregory $
*/
public class ByteArrayOutputStream extends OutputStream {
/** A singleton empty byte array. */
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
/** The list of buffers, which grows and never reduces. */
private final List
* This method is useful where,
*
* Typically uses of this class include testing for corner cases in methods
* that accept input streams and acting as a sentinel value instead of a
* {@code null} input stream.
*
* @version $Id: ClosedInputStream.java 1307459 2012-03-30 15:11:44Z ggregory $
* @since 1.4
*/
public class ClosedInputStream extends InputStream {
/**
* A singleton.
*/
public static final ClosedInputStream CLOSED_INPUT_STREAM = new ClosedInputStream();
/**
* Returns -1 to indicate that the stream is closed.
*
* @return always -1
*/
@Override
public int read() {
return -1;
}
}
================================================
FILE: aliocrlib/src/main/java/com/lib/aliocr/utils/stream/StringBuilderWriter.java
================================================
package com.lib.aliocr.utils.stream;
import android.support.annotation.NonNull;
import java.io.Serializable;
import java.io.Writer;
/**
* {@link Writer} implementation that outputs to a {@link StringBuilder}.
*
* NOTE: This implementation, as an alternative to
*
* 邮箱:ittfxin@126.com
*
* https://github.com/wzx54321/XinFrameworkLib
*/
@SuppressWarnings("StatementWithEmptyBody")
public class OCRMainActivity extends AppCompatActivity implements OcrContact.V {
private static final int REQUEST_CAMERA_PERMISSION = 1;
private static final String TAG = OCRMainActivity.class.getSimpleName();
private CameraView mCameraView;
private Handler mBackgroundHandler;
private OCRPresenter presenter;
private boolean mIsFace;
public static void Launcher(Context context, boolean isFace) {
Intent intent = new Intent(context, OCRMainActivity.class);
if (!(context instanceof Activity)) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
intent.putExtra("mIsFace", isFace);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mIsFace = getIntent().getBooleanExtra("mIsFace", true);
setContentView(R.layout.activity_ocr_main);
presenter = new OCRPresenter(this);
mCameraView = findViewById(R.id.my_camera);
if (mCameraView != null) {
mCameraView.addCallback(mCallback);
}
FloatingActionButton fab = findViewById(R.id.take_picture_);
if (fab != null) {
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mCameraView != null) {
mCameraView.takePicture();
}
}
});
}
}
@Override
protected void onResume() {
super.onResume();
if ((ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) &
ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) &
ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA))
== PackageManager.PERMISSION_GRANTED) {
mCameraView.start();
} /*else if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.CAMERA)) {
ConfirmationDialogFragment
.newInstance(R.string.camera_permission_confirmation,
new String[]{Manifest. .CAMERA},
REQUEST_CAMERA_PERMISSION,
R.string.camera_permission_not_granted)
.show(getSupportFragmentManager(), FRAGMENT_DIALOG);
}*/ else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA
, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE},
REQUEST_CAMERA_PERMISSION);
}
}
@Override
protected void onPause() {
mCameraView.stop();
super.onPause();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mBackgroundHandler != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
mBackgroundHandler.getLooper().quitSafely();
} else {
mBackgroundHandler.getLooper().quit();
}
mBackgroundHandler = null;
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_CAMERA_PERMISSION:
if (permissions.length != 1 || grantResults.length != 1) {
throw new RuntimeException("Error on requesting camera permission.");
}
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
}
// No need to start camera here; it is handled by onResume
break;
}
}
private Handler getBackgroundHandler() {
if (mBackgroundHandler == null) {
HandlerThread thread = new HandlerThread("background");
thread.start();
mBackgroundHandler = new Handler(thread.getLooper());
}
return mBackgroundHandler;
}
private CameraView.Callback mCallback
= new CameraView.Callback() {
@Override
public void onCameraOpened(CameraView cameraView) {
Log.d(TAG, "onCameraOpened");
}
@Override
public void onCameraClosed(CameraView cameraView) {
Log.d(TAG, "onCameraClosed");
}
@Override
public void onPictureTaken(CameraView cameraView, final byte[] data) {
Log.d(TAG, "onPictureTaken " + data.length);
presenter.onPictureTaken(data );
// mCameraView.stop();
}
};
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Ocr.onCropImgResult(this, null, requestCode, resultCode, data, new OcrCallback() {
@Override
public void onPicResult(String picPath) {
presenter.request(mIsFace, picPath);
}
@Override
public void onPicError() {
}
});
}
@Override
public Activity getActivity() {
return this;
}
}
================================================
FILE: aliocrlib/src/main/java/com/lib/aliocr/view/OcrLaunchFragment.java
================================================
package com.lib.aliocr.view;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.lib.aliocr.R;
import com.lib.aliocr.callback.OcrCallback;
import com.lib.aliocr.contact.OcrContact;
import com.lib.aliocr.presenter.OCRPresenter;
import com.lib.aliocr.utils.Ocr;
/**
* 作者:xin on 2018/7/9 0009 15:03
*
* 邮箱:ittfxin@126.com
*
* https://github.com/wzx54321/XinFrameworkLib
*/
public class OcrLaunchFragment extends Fragment implements View.OnClickListener, OcrContact.V {
boolean mIsFace;
private View rootView;
private OcrContact.P mPresenter;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPresenter = new OCRPresenter(this);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_ocr_launch, null);
rootView.findViewById(R.id.side_face).setOnClickListener(this);
rootView.findViewById(R.id.side_back).setOnClickListener(this);
return rootView;
}
@Override
public void onClick(View v) {
int i = v.getId();
if (i == R.id.side_face) {
mIsFace = true;
} else if (i == R.id.side_back) {
mIsFace = false;
}
Ocr.doOcr(getActivity(),this, rootView, mIsFace);
}
// ----------------------------------ocr使用-------------------------------------
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Ocr.onCropImgResult(getActivity(),this, requestCode, resultCode, data, new OcrCallback() {
@Override
public void onPicResult(String picPath) {
mPresenter.request(mIsFace, picPath);
}
@Override
public void onPicError() {
}
});
}
}
================================================
FILE: aliocrlib/src/main/java/com/lib/aliocr/widget/crop/Crop.java
================================================
package com.lib.aliocr.widget.crop;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Fragment;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import android.widget.Toast;
import com.lib.aliocr.R;
/**
* Builder for crop Intents and utils for handling result
*/
public class Crop {
public static final int REQUEST_CROP = 6709;
public static final int REQUEST_PICK = 9162;
public static final int RESULT_ERROR = 404;
interface Extra {
String ASPECT_X = "aspect_x";
String ASPECT_Y = "aspect_y";
String MAX_X = "max_x";
String MAX_Y = "max_y";
String AS_PNG = "as_png";
String ERROR = "error";
}
private Intent cropIntent;
/**
* Create a crop Intent builder with source and destination image Uris
*
* @param source Uri for image to crop
* @param destination Uri for saving the cropped image
*/
public static Crop of(Uri source, Uri destination) {
return new Crop(source, destination);
}
private Crop(Uri source, Uri destination) {
cropIntent = new Intent();
cropIntent.setData(source);
cropIntent.putExtra(MediaStore.EXTRA_OUTPUT, destination);
}
/**
* Set fixed aspect ratio for crop area
*
* @param x Aspect X
* @param y Aspect Y
*/
public Crop withAspect(float x, float y) {
cropIntent.putExtra(Extra.ASPECT_X, x);
cropIntent.putExtra(Extra.ASPECT_Y, y);
return this;
}
/**
* Crop area with fixed 1:1 aspect ratio
*/
public Crop asSquare() {
cropIntent.putExtra(Extra.ASPECT_X, 1);
cropIntent.putExtra(Extra.ASPECT_Y, 1);
return this;
}
/**
* Set maximum crop size
*
* @param width Max width
* @param height Max height
*/
public Crop withMaxSize(int width, int height) {
cropIntent.putExtra(Extra.MAX_X, width);
cropIntent.putExtra(Extra.MAX_Y, height);
return this;
}
/**
* Set whether to save the result as a PNG or not. Helpful to preserve alpha.
* @param asPng whether to save the result as a PNG or not
*/
public Crop asPng(boolean asPng) {
cropIntent.putExtra(Extra.AS_PNG, asPng);
return this;
}
/**
* Send the crop Intent from an Activity
*
* @param activity Activity to receive result
*/
public void start(Activity activity) {
start(activity, REQUEST_CROP);
}
/**
* Send the crop Intent from an Activity with a custom request code
*
* @param activity Activity to receive result
* @param requestCode requestCode for result
*/
public void start(Activity activity, int requestCode) {
activity.startActivityForResult(getIntent(activity), requestCode);
}
/**
* Send the crop Intent from a Fragment
*
* @param context Context
* @param fragment Fragment to receive result
*/
public void start(Context context, Fragment fragment) {
start(context, fragment, REQUEST_CROP);
}
/**
* Send the crop Intent from a support library Fragment
*
* @param context Context
* @param fragment Fragment to receive result
*/
public void start(Context context, android.support.v4.app.Fragment fragment) {
start(context, fragment, REQUEST_CROP);
}
/**
* Send the crop Intent with a custom request code
*
* @param context Context
* @param fragment Fragment to receive result
* @param requestCode requestCode for result
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void start(Context context, Fragment fragment, int requestCode) {
fragment.startActivityForResult(getIntent(context), requestCode);
}
/**
* Send the crop Intent with a custom request code
*
* @param context Context
* @param fragment Fragment to receive result
* @param requestCode requestCode for result
*/
public void start(Context context, android.support.v4.app.Fragment fragment, int requestCode) {
fragment.startActivityForResult(getIntent(context), requestCode);
}
/**
* Get Intent to start crop Activity
*
* @param context Context
* @return Intent for CropImageActivity
*/
public Intent getIntent(Context context) {
cropIntent.setClass(context, CropImageActivity.class);
return cropIntent;
}
/**
* Retrieve URI for cropped image, as set in the Intent builder
*
* @param result Output Image URI
*/
public static Uri getOutput(Intent result) {
return result.getParcelableExtra(MediaStore.EXTRA_OUTPUT);
}
/**
* Retrieve error that caused crop to fail
*
* @param result Result Intent
* @return Throwable handled in CropImageActivity
*/
public static Throwable getError(Intent result) {
return (Throwable) result.getSerializableExtra(Extra.ERROR);
}
/**
* Pick image from an Activity
*
* @param activity Activity to receive result
*/
public static void pickImage(Activity activity ) {
pickImage(activity, REQUEST_PICK);
}
/**
* Pick image from a Fragment
*
* @param context Context
* @param fragment Fragment to receive result
*/
public static void pickImage(Context context, Fragment fragment) {
pickImage(context, fragment, REQUEST_PICK);
}
/**
* Pick image from a support library Fragment
*
* @param context Context
* @param fragment Fragment to receive result
*/
public static void pickImage(Context context, android.support.v4.app.Fragment fragment) {
pickImage(context, fragment, REQUEST_PICK);
}
/**
* Pick image from an Activity with a custom request code
*
* @param activity Activity to receive result
* @param requestCode requestCode for result
*/
public static void pickImage(Activity activity , int requestCode) {
try {
activity.startActivityForResult(getImagePicker(), requestCode);
} catch (ActivityNotFoundException e) {
showImagePickerError(activity);
}
}
/**
* Pick image from a Fragment with a custom request code
*
* @param context Context
* @param fragment Fragment to receive result
* @param requestCode requestCode for result
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static void pickImage(Context context, Fragment fragment, int requestCode) {
try {
fragment.startActivityForResult(getImagePicker(), requestCode);
} catch (ActivityNotFoundException e) {
showImagePickerError(context);
}
}
/**
* Pick image from a support library Fragment with a custom request code
*
* @param context Context
* @param fragment Fragment to receive result
* @param requestCode requestCode for result
*/
public static void pickImage(Context context, android.support.v4.app.Fragment fragment, int requestCode) {
try {
fragment.startActivityForResult(getImagePicker(), requestCode);
} catch (ActivityNotFoundException e) {
showImagePickerError(context);
}
}
private static Intent getImagePicker() {
return new Intent(Intent.ACTION_GET_CONTENT).setType("image/*");
}
private static void showImagePickerError(Context context) {
Toast.makeText(context.getApplicationContext(), R.string.crop__pick_error, Toast.LENGTH_SHORT).show();
}
}
================================================
FILE: aliocrlib/src/main/java/com/lib/aliocr/widget/crop/CropImageActivity.java
================================================
/*
* Copyright (C) 2007 The Android Open Source Project
*
* 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.
*/
package com.lib.aliocr.widget.crop;
import android.annotation.TargetApi;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.net.Uri;
import android.opengl.GLES10;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.provider.MediaStore;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import com.lib.aliocr.R;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.CountDownLatch;
/*
* Modified from original in AOSP.
*/
public class CropImageActivity extends MonitoredActivity {
private static final int SIZE_DEFAULT = 2048;
private static final int SIZE_LIMIT = 4096;
private final Handler handler = new Handler();
private int aspectX;
private int aspectY;
// Output image
private int maxX;
private int maxY;
private int exifRotation;
private boolean saveAsPng;
private Uri sourceUri;
private Uri saveUri;
private boolean isSaving;
private int sampleSize;
private RotateBitmap rotateBitmap;
private CropImageView imageView;
private HighlightView cropView;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setupWindowFlags();
setupViews();
loadInput();
if (rotateBitmap == null) {
finish();
return;
}
startCrop();
}
@TargetApi(Build.VERSION_CODES.KITKAT)
private void setupWindowFlags() {
requestWindowFeature(Window.FEATURE_NO_TITLE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
private void setupViews() {
setContentView(R.layout.crop__activity_crop);
imageView = findViewById(R.id.crop_image);
imageView.context = this;
imageView.setRecycler(new ImageViewTouchBase.Recycler() {
@Override
public void recycle(Bitmap b) {
b.recycle();
System.gc();
}
});
findViewById(R.id.btn_cancel).setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
setResult(RESULT_CANCELED);
finish();
}
});
findViewById(R.id.btn_done).setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
onSaveClicked();
}
});
}
private void loadInput() {
Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {
aspectX = extras.getInt(Crop.Extra.ASPECT_X);
aspectY = extras.getInt(Crop.Extra.ASPECT_Y);
maxX = extras.getInt(Crop.Extra.MAX_X);
maxY = extras.getInt(Crop.Extra.MAX_Y);
saveAsPng = extras.getBoolean(Crop.Extra.AS_PNG, false);
saveUri = extras.getParcelable(MediaStore.EXTRA_OUTPUT);
}
sourceUri = intent.getData();
if (sourceUri != null) {
exifRotation = CropUtil.getExifRotation(CropUtil.getFromMediaUri(this, getContentResolver(), sourceUri));
InputStream is = null;
try {
sampleSize = calculateBitmapSampleSize(sourceUri);
is = getContentResolver().openInputStream(sourceUri);
BitmapFactory.Options option = new BitmapFactory.Options();
option.inSampleSize = sampleSize;
rotateBitmap = new RotateBitmap(BitmapFactory.decodeStream(is, null, option), exifRotation);
} catch (IOException e) {
Log.e("Error reading image: " + e.getMessage(), e);
setResultException(e);
} catch (OutOfMemoryError e) {
Log.e("OOM reading image: " + e.getMessage(), e);
setResultException(e);
} finally {
CropUtil.closeSilently(is);
}
}
}
private int calculateBitmapSampleSize(Uri bitmapUri) throws IOException {
InputStream is = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
try {
is = getContentResolver().openInputStream(bitmapUri);
BitmapFactory.decodeStream(is, null, options); // Just get image size
} finally {
CropUtil.closeSilently(is);
}
int maxSize = getMaxImageSize();
int sampleSize = 1;
while (options.outHeight / sampleSize > maxSize || options.outWidth / sampleSize > maxSize) {
sampleSize = sampleSize << 1;
}
return sampleSize;
}
private int getMaxImageSize() {
int textureLimit = getMaxTextureSize();
if (textureLimit == 0) {
return SIZE_DEFAULT;
} else {
return Math.min(textureLimit, SIZE_LIMIT);
}
}
private int getMaxTextureSize() {
// The OpenGL texture size is the maximum size that can be drawn in an ImageView
int[] maxSize = new int[1];
GLES10.glGetIntegerv(GLES10.GL_MAX_TEXTURE_SIZE, maxSize, 0);
return maxSize[0];
}
private void startCrop() {
if (isFinishing()) {
return;
}
imageView.setImageRotateBitmapResetBase(rotateBitmap, true);
CropUtil.startBackgroundJob(this, null, getResources().getString(R.string.crop__wait),
new Runnable() {
public void run() {
final CountDownLatch latch = new CountDownLatch(1);
handler.post(new Runnable() {
public void run() {
if (imageView.getScale() == 1F) {
imageView.center();
}
latch.countDown();
}
});
try {
latch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
new Cropper().crop();
}
}, handler
);
}
private class Cropper {
private void makeDefault() {
if (rotateBitmap == null) {
return;
}
HighlightView hv = new HighlightView(imageView);
final int width = rotateBitmap.getWidth();
final int height = rotateBitmap.getHeight();
Rect imageRect = new Rect(0, 0, width, height);
// Make the default size about 4/5 of the width or height
int cropWidth = Math.min(width, height) * 4 / 5;
@SuppressWarnings("SuspiciousNameCombination")
int cropHeight = cropWidth;
if (aspectX != 0 && aspectY != 0) {
if (aspectX > aspectY) {
cropHeight = cropWidth * aspectY / aspectX;
} else {
cropWidth = cropHeight * aspectX / aspectY;
}
}
int x = (width - cropWidth) / 2;
int y = (height - cropHeight) / 2;
RectF cropRect = new RectF(x, y, x + cropWidth, y + cropHeight);
hv.setup(imageView.getUnrotatedMatrix(), imageRect, cropRect, aspectX != 0 && aspectY != 0);
imageView.add(hv);
}
public void crop() {
handler.post(new Runnable() {
public void run() {
makeDefault();
imageView.invalidate();
if (imageView.highlightViews.size() == 1) {
cropView = imageView.highlightViews.get(0);
cropView.setFocus(true);
}
}
});
}
}
private void onSaveClicked() {
if (cropView == null || isSaving) {
return;
}
isSaving = true;
Bitmap croppedImage;
Rect r = cropView.getScaledCropRect(sampleSize);
int width = r.width();
int height = r.height();
int outWidth = width;
int outHeight = height;
if (maxX > 0 && maxY > 0 && (width > maxX || height > maxY)) {
float ratio = (float) width / (float) height;
if ((float) maxX / (float) maxY > ratio) {
outHeight = maxY;
outWidth = (int) ((float) maxY * ratio + .5f);
} else {
outWidth = maxX;
outHeight = (int) ((float) maxX / ratio + .5f);
}
}
try {
croppedImage = decodeRegionCrop(r, outWidth, outHeight);
} catch (IllegalArgumentException e) {
setResultException(e);
finish();
return;
}
if (croppedImage != null) {
imageView.setImageRotateBitmapResetBase(new RotateBitmap(croppedImage, exifRotation), true);
imageView.center();
imageView.highlightViews.clear();
}
saveImage(croppedImage);
}
private void saveImage(Bitmap croppedImage) {
if (croppedImage != null) {
final Bitmap b = croppedImage;
CropUtil.startBackgroundJob(this, null, getResources().getString(R.string.crop__saving),
new Runnable() {
public void run() {
saveOutput(b);
}
}, handler
);
} else {
finish();
}
}
private Bitmap decodeRegionCrop(Rect rect, int outWidth, int outHeight) {
// Release memory now
clearImageView();
InputStream is = null;
Bitmap croppedImage = null;
try {
is = getContentResolver().openInputStream(sourceUri);
BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false);
final int width = decoder.getWidth();
final int height = decoder.getHeight();
if (exifRotation != 0) {
// Adjust crop area to account for image rotation
Matrix matrix = new Matrix();
matrix.setRotate(-exifRotation);
RectF adjusted = new RectF();
matrix.mapRect(adjusted, new RectF(rect));
// Adjust to account for origin at 0,0
adjusted.offset(adjusted.left < 0 ? width : 0, adjusted.top < 0 ? height : 0);
rect = new Rect((int) adjusted.left, (int) adjusted.top, (int) adjusted.right, (int) adjusted.bottom);
}
try {
croppedImage = decoder.decodeRegion(rect, new BitmapFactory.Options());
if (croppedImage != null && (rect.width() > outWidth || rect.height() > outHeight)) {
Matrix matrix = new Matrix();
matrix.postScale((float) outWidth / rect.width(), (float) outHeight / rect.height());
croppedImage = Bitmap.createBitmap(croppedImage, 0, 0, croppedImage.getWidth(), croppedImage.getHeight(), matrix, true);
}
} catch (IllegalArgumentException e) {
// Rethrow with some extra information
throw new IllegalArgumentException("Rectangle " + rect + " is outside of the image ("
+ width + "," + height + "," + exifRotation + ")", e);
}
} catch (IOException e) {
Log.e("Error cropping image: " + e.getMessage(), e);
setResultException(e);
} catch (OutOfMemoryError e) {
Log.e("OOM cropping image: " + e.getMessage(), e);
setResultException(e);
} finally {
CropUtil.closeSilently(is);
}
return croppedImage;
}
private void clearImageView() {
imageView.clear();
if (rotateBitmap != null) {
rotateBitmap.recycle();
}
System.gc();
}
private void saveOutput(Bitmap croppedImage) {
if (saveUri != null) {
OutputStream outputStream = null;
try {
outputStream = getContentResolver().openOutputStream(saveUri);
if (outputStream != null) {
croppedImage.compress(saveAsPng ? Bitmap.CompressFormat.PNG : Bitmap.CompressFormat.JPEG,
90, // note: quality is ignored when using PNG
outputStream);
}
} catch (IOException e) {
setResultException(e);
Log.e("Cannot open file: " + saveUri, e);
} finally {
CropUtil.closeSilently(outputStream);
}
CropUtil.copyExifRotation(
CropUtil.getFromMediaUri(this, getContentResolver(), sourceUri),
CropUtil.getFromMediaUri(this, getContentResolver(), saveUri)
);
setResultUri(saveUri);
}
final Bitmap b = croppedImage;
handler.post(new Runnable() {
public void run() {
imageView.clear();
b.recycle();
}
});
finish();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (rotateBitmap != null) {
rotateBitmap.recycle();
}
}
@Override
public boolean onSearchRequested() {
return false;
}
public boolean isSaving() {
return isSaving;
}
private void setResultUri(Uri uri) {
setResult(RESULT_OK, new Intent().putExtra(MediaStore.EXTRA_OUTPUT, uri));
}
private void setResultException(Throwable throwable) {
setResult(Crop.RESULT_ERROR, new Intent().putExtra(Crop.Extra.ERROR, throwable));
}
}
================================================
FILE: aliocrlib/src/main/java/com/lib/aliocr/widget/crop/CropImageView.java
================================================
package com.lib.aliocr.widget.crop;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.MotionEvent;
import java.util.ArrayList;
public class CropImageView extends ImageViewTouchBase {
ArrayList
*
* List
* XinPopWindow myPopWindow = new XinPopWindow(MainActivity.this);
* myPopWindow.setData(menuItems);
* myPopWindow.showAtLocation(root, Gravity.BOTTOM, 0, 0);
*
*
* 作者:xin on 2018/7/9 0009 15:03
*
* 邮箱:ittfxin@126.com
*
* https://github.com/wzx54321/XinFrameworkLib
*/
public class XinPopWindow extends PopupWindow {
OnItemClickListener mOnItemClickListener;
Activity mContext;
private Window mWindow;
private ListView mItems;
private MenuAdapter menuAdapter;
public XinPopWindow(Activity context) {
mContext = context;
mWindow = mContext.getWindow();
backgroundAlpha(1);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//noinspection ConstantConditions
View mMenuView = inflater.inflate(R.layout.common_popwindow, null, false);
View btnCancel = mMenuView.findViewById(R.id.btn_cancel);
btnCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
mItems = mMenuView.findViewById(R.id.itemList);
menuAdapter = new MenuAdapter();
mItems.setAdapter(menuAdapter);
mItems.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
if (mOnItemClickListener != null)
mOnItemClickListener.onItemClick(parent, view, position, id, menuAdapter.getMenuItems().get(position).type);
}
}
);
mMenuView.setOnTouchListener(new View.OnTouchListener() {
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP || event.getY() < mItems.getTop())
XinPopWindow.this.dismiss();
return true;
}
});
setOutsideTouchable(true);
this.setFocusable(true);
this.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
this.setWidth(WindowManager.LayoutParams.MATCH_PARENT);
this.setHeight(WindowManager.LayoutParams.MATCH_PARENT);
this.setContentView(mMenuView);
setBackgroundDrawable(ContextCompat.getDrawable(mContext.getApplication(), android.R.color.transparent));
this.setAnimationStyle(R.style.common_PopupAnimation);
setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss() {
backgroundAlpha(1);
}
});
}
public void backgroundAlpha(float bgAlpha) {
if (mWindow == null) {
mWindow = mContext.getWindow();
}
if (mWindow == null)
return;
WindowManager.LayoutParams lp = mWindow.getAttributes();
mWindow.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
lp.alpha = bgAlpha; //0.0-1.0
mWindow.setAttributes(lp);
}
@Override
public void showAtLocation(View parent, int gravity, int x, int y) {
super.showAtLocation(parent, gravity, x, y);
backgroundAlpha(0.6f);
}
public void setData(List
* Only relevant for API version 23 and above.
*
* @param context used to access Android APIs, like content resolve, it is your activity/fragment/widget.
* @param uri the result URI of image pick.
*/
public static boolean isUriRequiresPermissions(@NonNull Context context, @NonNull Uri uri) {
try {
ContentResolver resolver = context.getContentResolver();
InputStream stream = resolver.openInputStream(uri);
stream.close();
return false;
} catch (Exception e) {
return true;
}
}
public static void beginCrop(Uri source, Activity activity, Fragment fragment) {
Uri destination = Uri.fromFile(new File(activity.getCacheDir(), "cropped"));
Crop crop = Crop.of(source, destination).withAspect(1, 1.3f);
if (fragment == null)
crop.start(activity);
else
crop.start(activity, fragment);
}
}
================================================
FILE: aliocrlib/src/main/java/com/lib/aliocr/utils/io/Charsets.java
================================================
package com.lib.aliocr.utils.io;
import java.nio.charset.Charset;
/**
* Charsets
*/
@SuppressWarnings("WeakerAccess")
public class Charsets {
public static Charset toCharset(Charset charset) {
return charset == null ? Charset.defaultCharset() : charset;
}
public static Charset toCharset(String charset) {
return charset == null ? Charset.defaultCharset() : Charset.forName(charset);
}
public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
public static final Charset US_ASCII = Charset.forName("US-ASCII");
public static final Charset UTF_16 = Charset.forName("UTF-16");
public static final Charset UTF_16BE = Charset.forName("UTF-16BE");
public static final Charset UTF_16LE = Charset.forName("UTF-16LE");
public static final Charset UTF_8 = Charset.forName("UTF-8");
}
================================================
FILE: aliocrlib/src/main/java/com/lib/aliocr/utils/io/FileUtil.java
================================================
package com.lib.aliocr.utils.io;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.io.StringReader;
import java.io.StringWriter;
import java.text.DecimalFormat;
import java.util.Date;
/**
* 作者:xin on 2018/7/9 0009 15:03
*
* 在Froyo之前需要自己建立缓存目录
*/
public static File getExternalCacheDir(Context context) {
if (SdCardUtil.isSdCardAvailable()) {
return context.getExternalCacheDir();
} else {
// 使用data/data文件夹
return context.getCacheDir();
}
}
}
================================================
FILE: aliocrlib/src/main/java/com/lib/aliocr/utils/io/IOUtils.java
================================================
package com.lib.aliocr.utils.io;
import android.annotation.SuppressLint;
import android.os.Build;
import android.util.Log;
import com.lib.aliocr.utils.stream.ByteArrayOutputStream;
import com.lib.aliocr.utils.stream.StringBuilderWriter;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.CharArrayWriter;
import java.io.Closeable;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.Selector;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* General IO stream manipulation utilities.
*
*
*
* The byte-to-char methods and char-to-byte methods involve a conversion step.
* Two methods are provided in each case, one that uses the platform default
* encoding and the other which allows you to specify an encoding. You are
* encouraged to always specify an encoding because relying on the platform
* default can lead to unexpected results, for example when moving from
* development to production.
*
* All the methods in this class that read a stream are buffered internally.
* This means that there is no cause to use a BufferedInputStream
* or BufferedReader. The default buffer size of 4K has been shown
* to be efficient in tests.
*
* Wherever possible, the methods in this class do not flush or close
* the stream. This is to avoid making non-portable assumptions about the
* streams' origin and further use. Thus the caller is still responsible for
* closing streams after use.
*
* Origin of code: Excalibur.
*
* @version $Id: IOUtils.java 1326636 2012-04-16 14:54:53Z ggregory $
*/
@SuppressWarnings("WeakerAccess")
public class IOUtils {
// NOTE: This class is focussed on InputStream, OutputStream, Reader and
// Writer. Each method should take at least one of these as a parameter,
// or return one of them.
private static final int EOF = -1;
/**
* The Unix directory separator character.
*/
public static final char DIR_SEPARATOR_UNIX = '/';
/**
* The Windows directory separator character.
*/
public static final char DIR_SEPARATOR_WINDOWS = '\\';
/**
* The system directory separator character.
*/
public static final char DIR_SEPARATOR = File.separatorChar;
/**
* The Unix line separator string.
*/
public static final String LINE_SEPARATOR_UNIX = "\n";
/**
* The Windows line separator string.
*/
public static final String LINE_SEPARATOR_WINDOWS = "\r\n";
/**
* The system line separator string.
*/
public static final String LINE_SEPARATOR;
static {
// avoid security issues
StringBuilderWriter buf = new StringBuilderWriter(4);
PrintWriter out = new PrintWriter(buf);
out.println();
LINE_SEPARATOR = buf.toString();
out.close();
}
/**
* The default buffer size ({@value}) to use for
* {@link #copyLarge(InputStream, OutputStream)}
* and
* {@link #copyLarge(Reader, Writer)}
*/
private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
/**
* The default buffer size to use for the skip() methods.
*/
private static final int SKIP_BUFFER_SIZE = 2048;
// Allocated in the relevant skip method if necessary.
/*
* N.B. no need to synchronize these because:
* - we don't care if the buffer is created multiple times (the data is ignored)
* - we always use the same size buffer, so if it it is recreated it will still be OK
* (if the buffer size were variable, we would need to sync. to ensure some other thread
* did not create a smaller one)
*/
private static char[] SKIP_CHAR_BUFFER;
private static byte[] SKIP_BYTE_BUFFER;
/**
* Instances should NOT be constructed in standard programming.
*/
public IOUtils() {
super();
}
//-----------------------------------------------------------------------
/**
* Closes a URLConnection.
*
* @param conn the connection to close.
* @since 2.4
*/
public static void close(URLConnection conn) {
if (conn instanceof HttpURLConnection) {
((HttpURLConnection) conn).disconnect();
}
}
/**
* Unconditionally close an Reader.
*
* Equivalent to {@link Reader#close()}, except any exceptions will be ignored.
* This is typically used in finally blocks.
*
* Example code:
*
* char[] data = new char[1024];
* Reader in = null;
* try {
* in = new FileReader("foo.txt");
* in.read(data);
* in.close(); //close errors are handled
* } catch (Exception e) {
* // error handling
* } finally {
* IOUtils.closeQuietly(in);
* }
*
*
* @param input the Reader to close, may be null or already closed
*/
public static void closeQuietly(Reader input) {
closeQuietly((Closeable) input);
}
/**
* Unconditionally close a Writer.
*
* Equivalent to {@link Writer#close()}, except any exceptions will be ignored.
* This is typically used in finally blocks.
*
* Example code:
*
* Writer out = null;
* try {
* out = new StringWriter();
* out.write("Hello World");
* out.close(); //close errors are handled
* } catch (Exception e) {
* // error handling
* } finally {
* IOUtils.closeQuietly(out);
* }
*
*
* @param output the Writer to close, may be null or already closed
*/
public static void closeQuietly(Writer output) {
closeQuietly((Closeable) output);
}
/**
* Unconditionally close an InputStream.
*
* Equivalent to {@link InputStream#close()}, except any exceptions will be ignored.
* This is typically used in finally blocks.
*
* Example code:
*
* byte[] data = new byte[1024];
* InputStream in = null;
* try {
* in = new FileInputStream("foo.txt");
* in.read(data);
* in.close(); //close errors are handled
* } catch (Exception e) {
* // error handling
* } finally {
* IOUtils.closeQuietly(in);
* }
*
*
* @param input the InputStream to close, may be null or already closed
*/
public static void closeQuietly(InputStream input) {
closeQuietly((Closeable) input);
}
/**
* Unconditionally close an OutputStream.
*
* Equivalent to {@link OutputStream#close()}, except any exceptions will be ignored.
* This is typically used in finally blocks.
*
* Example code:
*
* byte[] data = "Hello, World".getBytes();
*
* OutputStream out = null;
* try {
* out = new FileOutputStream("foo.txt");
* out.write(data);
* out.close(); //close errors are handled
* } catch (IOException e) {
* // error handling
* } finally {
* IOUtils.closeQuietly(out);
* }
*
*
* @param output the OutputStream to close, may be null or already closed
*/
public static void closeQuietly(OutputStream output) {
closeQuietly((Closeable) output);
}
/**
* Unconditionally close a Closeable.
*
* Equivalent to {@link Closeable#close()}, except any exceptions will be ignored.
* This is typically used in finally blocks.
*
* Example code:
*
* Closeable closeable = null;
* try {
* closeable = new FileReader("foo.txt");
* // process closeable
* closeable.close();
* } catch (Exception e) {
* // error handling
* } finally {
* IOUtils.closeQuietly(closeable);
* }
*
*
* @param closeable the object to close, may be null or already closed
* @since 2.0
*/
public static void closeQuietly(Closeable closeable) {
try {
if (closeable != null) {
closeable.close();
}
} catch (IOException ioe) {
// ignore
}
}
/**
* Unconditionally close a Socket.
*
* Equivalent to {@link Socket#close()}, except any exceptions will be ignored.
* This is typically used in finally blocks.
*
* Example code:
*
* Socket socket = null;
* try {
* socket = new Socket("http://www.foo.com/", 80);
* // process socket
* socket.close();
* } catch (Exception e) {
* // error handling
* } finally {
* IOUtils.closeQuietly(socket);
* }
*
*
* @param sock the Socket to close, may be null or already closed
* @since 2.0
*/
public static void closeQuietly(Socket sock) {
if (sock != null) {
try {
sock.close();
} catch (IOException ioe) {
// ignored
}
}
}
/**
* Unconditionally close a Selector.
*
* Equivalent to {@link Selector#close()}, except any exceptions will be ignored.
* This is typically used in finally blocks.
*
* Example code:
*
* Selector selector = null;
* try {
* selector = Selector.open();
* // process socket
*
* } catch (Exception e) {
* // error handling
* } finally {
* IOUtils.closeQuietly(selector);
* }
*
*
* @param selector the Selector to close, may be null or already closed
* @since 2.2
*/
public static void closeQuietly(Selector selector) {
if (selector != null) {
try {
selector.close();
} catch (IOException ioe) {
// ignored
}
}
}
/**
* Unconditionally close a ServerSocket.
*
* Equivalent to {@link ServerSocket#close()}, except any exceptions will be ignored.
* This is typically used in finally blocks.
*
* Example code:
*
* ServerSocket socket = null;
* try {
* socket = new ServerSocket();
* // process socket
* socket.close();
* } catch (Exception e) {
* // error handling
* } finally {
* IOUtils.closeQuietly(socket);
* }
*
*
* @param sock the ServerSocket to close, may be null or already closed
* @since 2.2
*/
public static void closeQuietly(ServerSocket sock) {
if (sock != null) {
try {
sock.close();
} catch (IOException ioe) {
// ignored
}
}
}
/**
* Fetches entire contents of an InputStream and represent
* same data as result InputStream.
*
* This method is useful where,
*
*
* It can be used in favor of {@link #toByteArray(InputStream)}, since it
* avoids unnecessary allocation and copy of byte[].
* This method buffers the input internally, so there is no need to use a
* BufferedInputStream.
*
* @param input Stream to be fully buffered.
* @return A fully buffered stream.
* @throws IOException if an I/O error occurs
* @since 2.0
*/
public static InputStream toBufferedInputStream(InputStream input) throws IOException {
return ByteArrayOutputStream.toBufferedInputStream(input);
}
/**
* Returns the given reader if it is a {@link BufferedReader}, otherwise creates a toBufferedReader for the given
* reader.
*
* @param reader the reader to wrap or return
* @return the given reader or a new {@link BufferedReader} for the given reader
* @since 2.2
*/
public static BufferedReader toBufferedReader(Reader reader) {
return reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader);
}
// read toByteArray
//-----------------------------------------------------------------------
/**
* Get the contents of an InputStream as a byte[].
*
* This method buffers the input internally, so there is no need to use a
* BufferedInputStream.
*
* @param input the InputStream to read from
* @return the requested byte array
* @throws NullPointerException if the input is null
* @throws IOException if an I/O error occurs
*/
public static byte[] toByteArray(InputStream input) throws IOException {
ByteArrayOutputStream output =
new ByteArrayOutputStream();
copy(input, output);
return output.toByteArray();
}
public static byte[] toByteArray(Object input) {
ByteArrayOutputStream byteArrayOutputStream = null;
ObjectOutputStream oos = null;
try {
byteArrayOutputStream = new ByteArrayOutputStream();
oos = new ObjectOutputStream(byteArrayOutputStream);
oos.writeObject(input);
oos.flush();
return byteArrayOutputStream.toByteArray();
} catch (IOException e) {
Log.e("", "toByteArray");
} finally {
IOUtils.closeQuietly(oos);
IOUtils.closeQuietly(byteArrayOutputStream);
}
return null;
}
/**
* Get contents of an InputStream as a byte[].
* Use this method instead of toByteArray(InputStream)
* when InputStream size is known.
* NOTE: the method checks that the length can safely be cast to an int without truncation
* before using {@link IOUtils#toByteArray(InputStream, int)} to read into the byte array.
* (Arrays can have no more than Integer.MAX_VALUE entries anyway)
*
* @param input the InputStream to read from
* @param size the size of InputStream
* @return the requested byte array
* @throws IOException if an I/O error occurs or InputStream size differ from parameter size
* @throws IllegalArgumentException if size is less than zero or size is greater than Integer.MAX_VALUE
* @see IOUtils#toByteArray(InputStream, int)
* @since 2.1
*/
public static byte[] toByteArray(InputStream input, long size) throws IOException {
if (size > Integer.MAX_VALUE) {
throw new IllegalArgumentException("Size cannot be greater than Integer max value: " + size);
}
return toByteArray(input, (int) size);
}
/**
* Get the contents of an InputStream as a byte[].
* Use this method instead of toByteArray(InputStream)
* when InputStream size is known
*
* @param input the InputStream to read from
* @param size the size of InputStream
* @return the requested byte array
* @throws IOException if an I/O error occurs or InputStream size differ from parameter size
* @throws IllegalArgumentException if size is less than zero
* @since 2.1
*/
public static byte[] toByteArray(InputStream input, int size) throws IOException {
if (size < 0) {
throw new IllegalArgumentException("Size must be equal or greater than zero: " + size);
}
if (size == 0) {
return new byte[0];
}
byte[] data = new byte[size];
int offset = 0;
int read;
while (offset < size && (read = input.read(data, offset, size - offset)) != EOF) {
offset += read;
}
if (offset != size) {
throw new IOException("Unexpected read size. current: " + offset + ", excepted: " + size);
}
return data;
}
/**
* Get the contents of a Reader as a byte[]
* using the default character encoding of the platform.
*
* This method buffers the input internally, so there is no need to use a
* BufferedReader.
*
* @param input the Reader to read from
* @return the requested byte array
* @throws NullPointerException if the input is null
* @throws IOException if an I/O error occurs
*/
public static byte[] toByteArray(Reader input) throws IOException {
return toByteArray(input, Charset.defaultCharset());
}
/**
* Get the contents of a Reader as a byte[]
* using the specified character encoding.
*
* This method buffers the input internally, so there is no need to use a
* BufferedReader.
*
* @param input the Reader to read from
* @param encoding the encoding to use, null means platform default
* @return the requested byte array
* @throws NullPointerException if the input is null
* @throws IOException if an I/O error occurs
* @since 2.3
*/
public static byte[] toByteArray(Reader input, Charset encoding) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
copy(input, output, encoding);
return output.toByteArray();
}
/**
* Get the contents of a Reader as a byte[]
* using the specified character encoding.
*
* Character encoding names can be found at
* iaNa.org.
*
* This method buffers the input internally, so there is no need to use a
* BufferedReader.
*
* @param input the Reader to read from
* @param encoding the encoding to use, null means platform default
* @return the requested byte array
* @throws NullPointerException if the input is null
* @throws IOException if an I/O error occurs
* @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link UnsupportedEncodingException} in version 2.2 if the encoding is not
* supported.
* @since 1.1
*/
public static byte[] toByteArray(Reader input, String encoding) throws IOException {
return toByteArray(input, Charsets.toCharset(encoding));
}
/**
* Get the contents of a String as a byte[]
* using the default character encoding of the platform.
*
* This is the same as {@link String#getBytes()}.
*
* @param input the String to convert
* @return the requested byte array
* @throws NullPointerException if the input is null
* @throws IOException if an I/O error occurs (never occurs)
* @deprecated Use {@link String#getBytes()}
*/
@Deprecated
public static byte[] toByteArray(String input) throws IOException {
return input.getBytes();
}
/**
* Get the contents of a URI as a byte[].
*
* @param uri the URI to read
* @return the requested byte array
* @throws NullPointerException if the uri is null
* @throws IOException if an I/O exception occurs
* @since 2.4
*/
public static byte[] toByteArray(URI uri) throws IOException {
return IOUtils.toByteArray(uri.toURL());
}
/**
* Get the contents of a URL as a byte[].
*
* @param url the URL to read
* @return the requested byte array
* @throws NullPointerException if the input is null
* @throws IOException if an I/O exception occurs
* @since 2.4
*/
public static byte[] toByteArray(URL url) throws IOException {
URLConnection conn = url.openConnection();
try {
return IOUtils.toByteArray(conn);
} finally {
close(conn);
}
}
/**
* Get the contents of a URLConnection as a byte[].
*
* @param urlConn the URLConnection to read
* @return the requested byte array
* @throws NullPointerException if the urlConn is null
* @throws IOException if an I/O exception occurs
* @since 2.4
*/
public static byte[] toByteArray(URLConnection urlConn) throws IOException {
InputStream inputStream = urlConn.getInputStream();
try {
return IOUtils.toByteArray(inputStream);
} catch (Exception e) {
Log.e("", "");
} finally {
inputStream.close();
}
return new byte[0];
}
// read char[]
//-----------------------------------------------------------------------
/**
* Get the contents of an InputStream as a character array
* using the default character encoding of the platform.
*
* This method buffers the input internally, so there is no need to use a
* BufferedInputStream.
*
* @param is the InputStream to read from
* @return the requested character array
* @throws NullPointerException if the input is null
* @throws IOException if an I/O error occurs
* @since 1.1
*/
public static char[] toCharArray(InputStream is) throws IOException {
return toCharArray(is, Charset.defaultCharset());
}
/**
* Get the contents of an InputStream as a character array
* using the specified character encoding.
*
* This method buffers the input internally, so there is no need to use a
* BufferedInputStream.
*
* @param is the InputStream to read from
* @param encoding the encoding to use, null means platform default
* @return the requested character array
* @throws NullPointerException if the input is null
* @throws IOException if an I/O error occurs
* @since 2.3
*/
public static char[] toCharArray(InputStream is, Charset encoding)
throws IOException {
CharArrayWriter output = new CharArrayWriter();
copy(is, output, encoding);
return output.toCharArray();
}
/**
* Get the contents of an InputStream as a character array
* using the specified character encoding.
*
* Character encoding names can be found at
* iaNa.
*
* This method buffers the input internally, so there is no need to use a
* BufferedInputStream.
*
* @param is the InputStream to read from
* @param encoding the encoding to use, null means platform default
* @return the requested character array
* @throws NullPointerException if the input is null
* @throws IOException if an I/O error occurs
* @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link UnsupportedEncodingException} in version 2.2 if the encoding is not
* supported.
* @since 1.1
*/
public static char[] toCharArray(InputStream is, String encoding) throws IOException {
return toCharArray(is, Charsets.toCharset(encoding));
}
/**
* Get the contents of a Reader as a character array.
*
* This method buffers the input internally, so there is no need to use a
* BufferedReader.
*
* @param input the Reader to read from
* @return the requested character array
* @throws NullPointerException if the input is null
* @throws IOException if an I/O error occurs
* @since 1.1
*/
public static char[] toCharArray(Reader input) throws IOException {
CharArrayWriter sw = new CharArrayWriter();
copy(input, sw);
return sw.toCharArray();
}
// read toString
//-----------------------------------------------------------------------
/**
* Get the contents of an InputStream as a String
* using the default character encoding of the platform.
*
* This method buffers the input internally, so there is no need to use a
* BufferedInputStream.
*
* @param input the InputStream to read from
* @return the requested String
* @throws NullPointerException if the input is null
* @throws IOException if an I/O error occurs
*/
public static String toString(InputStream input) throws IOException {
return toString(input, Charset.defaultCharset());
}
/**
* Get the contents of an InputStream as a String
* using the specified character encoding.
* BufferedInputStream.
* InputStream to read from
* @param encoding the encoding to use, null means platform default
* @return the requested String
* @throws NullPointerException if the input is null
* @throws IOException if an I/O error occurs
* @since 2.3
*/
public static String toString(InputStream input, Charset encoding) throws IOException {
StringBuilderWriter sw = new StringBuilderWriter();
copy(input, sw, encoding);
return sw.toString();
}
/**
* Get the contents of an InputStream as a String
* using the specified character encoding.
*
* Character encoding names can be found at
* iaNa.
*
* This method buffers the input internally, so there is no need to use a
* BufferedInputStream.
*
* @param input the InputStream to read from
* @param encoding the encoding to use, null means platform default
* @return the requested String
* @throws NullPointerException if the input is null
* @throws IOException if an I/O error occurs
* @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link UnsupportedEncodingException} in version 2.2 if the encoding is not
* supported.
*/
public static String toString(InputStream input, String encoding)
throws IOException {
return toString(input, Charsets.toCharset(encoding));
}
/**
* Get the contents of a Reader as a String.
*
* This method buffers the input internally, so there is no need to use a
* BufferedReader.
*
* @param input the Reader to read from
* @return the requested String
* @throws NullPointerException if the input is null
* @throws IOException if an I/O error occurs
*/
public static String toString(Reader input) throws IOException {
StringBuilderWriter sw = new StringBuilderWriter();
copy(input, sw);
return sw.toString();
}
/**
* Gets the contents at the given URI.
*
* @param uri The URI source.
* @return The contents of the URL as a String.
* @throws IOException if an I/O exception occurs.
* @since 2.1
*/
public static String toString(URI uri) throws IOException {
return toString(uri, Charset.defaultCharset());
}
/**
* Gets the contents at the given URI.
*
* @param uri The URI source.
* @param encoding The encoding name for the URL contents.
* @return The contents of the URL as a String.
* @throws IOException if an I/O exception occurs.
* @since 2.3.
*/
public static String toString(URI uri, Charset encoding) throws IOException {
return toString(uri.toURL(), Charsets.toCharset(encoding));
}
/**
* Gets the contents at the given URI.
*
* @param uri The URI source.
* @param encoding The encoding name for the URL contents.
* @return The contents of the URL as a String.
* @throws IOException if an I/O exception occurs.
* @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link UnsupportedEncodingException} in version 2.2 if the encoding is not
* supported.
* @since 2.1
*/
public static String toString(URI uri, String encoding) throws IOException {
return toString(uri, Charsets.toCharset(encoding));
}
/**
* Gets the contents at the given URL.
*
* @param url The URL source.
* @return The contents of the URL as a String.
* @throws IOException if an I/O exception occurs.
* @since 2.1
*/
public static String toString(URL url) throws IOException {
return toString(url, Charset.defaultCharset());
}
/**
* Gets the contents at the given URL.
*
* @param url The URL source.
* @param encoding The encoding name for the URL contents.
* @return The contents of the URL as a String.
* @throws IOException if an I/O exception occurs.
* @since 2.3
*/
public static String toString(URL url, Charset encoding) throws IOException {
InputStream inputStream = url.openStream();
try {
return toString(inputStream, encoding);
} catch (Exception e) {
Log.e("", "");
} finally {
inputStream.close();
}
return null;
}
/**
* Gets the contents at the given URL.
*
* @param url The URL source.
* @param encoding The encoding name for the URL contents.
* @return The contents of the URL as a String.
* @throws IOException if an I/O exception occurs.
* @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link UnsupportedEncodingException} in version 2.2 if the encoding is not
* supported.
* @since 2.1
*/
public static String toString(URL url, String encoding) throws IOException {
return toString(url, Charsets.toCharset(encoding));
}
/**
* Get the contents of a byte[] as a String
* using the default character encoding of the platform.
*
* @param input the byte array to read from
* @return the requested String
* @throws NullPointerException if the input is null
* @throws IOException if an I/O error occurs (never occurs)
* @deprecated Use {@link String#String(byte[])}
*/
@Deprecated
public static String toString(byte[] input) throws IOException {
return new String(input);
}
/**
* Get the contents of a byte[] as a String
* using the specified character encoding.
*
* Character encoding names can be found at
* iaNa.
*
* @param input the byte array to read from
* @param encoding the encoding to use, null means platform default
* @return the requested String
* @throws NullPointerException if the input is null
* @throws IOException if an I/O error occurs (never occurs)
*/
public static String toString(byte[] input, String encoding) throws IOException {
return new String(input, encoding);
}
public static Reader toReader(String str){
return new StringReader(str);
}
// readLines
//-----------------------------------------------------------------------
/**
* Get the contents of an InputStream as a list of Strings,
* one entry per line, using the default character encoding of the platform.
*
* This method buffers the input internally, so there is no need to use a
* BufferedInputStream.
*
* @param input the InputStream to read from, not null
* @return the list of Strings, never null
* @throws NullPointerException if the input is null
* @throws IOException if an I/O error occurs
* @since 1.1
*/
public static ListInputStream as a list of Strings,
* one entry per line, using the specified character encoding.
*
* This method buffers the input internally, so there is no need to use a
* BufferedInputStream.
*
* @param input the InputStream to read from, not null
* @param encoding the encoding to use, null means platform default
* @return the list of Strings, never null
* @throws NullPointerException if the input is null
* @throws IOException if an I/O error occurs
* @since 2.3
*/
public static ListInputStream as a list of Strings,
* one entry per line, using the specified character encoding.
*
* Character encoding names can be found at
* iaNa.
*
* This method buffers the input internally, so there is no need to use a
* BufferedInputStream.
*
* @param input the InputStream to read from, not null
* @param encoding the encoding to use, null means platform default
* @return the list of Strings, never null
* @throws NullPointerException if the input is null
* @throws IOException if an I/O error occurs
* @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link UnsupportedEncodingException} in version 2.2 if the encoding is not
* supported.
* @since 1.1
*/
public static ListReader as a list of Strings,
* one entry per line.
*
* This method buffers the input internally, so there is no need to use a
* BufferedReader.
*
* @param input the Reader to read from, not null
* @return the list of Strings, never null
* @throws NullPointerException if the input is null
* @throws IOException if an I/O error occurs
* @since 1.1
*/
public static Listbyte[] to an OutputStream.
*
* @param data the byte array to write, do not modify during output,
* null ignored
* @param output the OutputStream to write to
* @throws NullPointerException if output is null
* @throws IOException if an I/O error occurs
* @since 1.1
*/
public static void write(byte[] data, OutputStream output)
throws IOException {
if (data != null) {
output.write(data);
}
}
/**
* Writes bytes from a byte[] to chars on a Writer
* using the default character encoding of the platform.
*
* This method uses {@link String#String(byte[])}.
*
* @param data the byte array to write, do not modify during output,
* null ignored
* @param output the Writer to write to
* @throws NullPointerException if output is null
* @throws IOException if an I/O error occurs
* @since 1.1
*/
public static void write(byte[] data, Writer output) throws IOException {
write(data, output, Charset.defaultCharset());
}
/**
* Writes bytes from a byte[] to chars on a Writer
* using the specified character encoding.
*
* This method uses {@link String#String(byte[], String)}.
*
* @param data the byte array to write, do not modify during output,
* null ignored
* @param output the Writer to write to
* @param encoding the encoding to use, null means platform default
* @throws NullPointerException if output is null
* @throws IOException if an I/O error occurs
* @since 2.3
*/
@SuppressLint("ObsoleteSdkInt")
public static void write(byte[] data, Writer output, Charset encoding) throws IOException {
if (data != null) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) {
output.write(new String(data, Charsets.toCharset(encoding).name()));
} else {
output.write(new String(data, Charsets.toCharset(encoding)));
}
}
}
/**
* Writes bytes from a byte[] to chars on a Writer
* using the specified character encoding.
*
* Character encoding names can be found at
* iaNa.
*
* This method uses {@link String#String(byte[], String)}.
*
* @param data the byte array to write, do not modify during output,
* null ignored
* @param output the Writer to write to
* @param encoding the encoding to use, null means platform default
* @throws NullPointerException if output is null
* @throws IOException if an I/O error occurs
* @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link UnsupportedEncodingException} in version 2.2 if the encoding is not
* supported.
* @since 1.1
*/
public static void write(byte[] data, Writer output, String encoding) throws IOException {
write(data, output, Charsets.toCharset(encoding));
}
// write char[]
//-----------------------------------------------------------------------
/**
* Writes chars from a char[] to a Writer
* using the default character encoding of the platform.
*
* @param data the char array to write, do not modify during output,
* null ignored
* @param output the Writer to write to
* @throws NullPointerException if output is null
* @throws IOException if an I/O error occurs
* @since 1.1
*/
public static void write(char[] data, Writer output) throws IOException {
if (data != null) {
output.write(data);
}
}
/**
* Writes chars from a char[] to bytes on an
* OutputStream.
*
* This method uses {@link String#String(char[])} and
* {@link String#getBytes()}.
*
* @param data the char array to write, do not modify during output,
* null ignored
* @param output the OutputStream to write to
* @throws NullPointerException if output is null
* @throws IOException if an I/O error occurs
* @since 1.1
*/
public static void write(char[] data, OutputStream output)
throws IOException {
write(data, output, Charset.defaultCharset());
}
/**
* Writes chars from a char[] to bytes on an
* OutputStream using the specified character encoding.
*
* This method uses {@link String#String(char[])} and
* {@link String#getBytes(String)}.
*
* @param data the char array to write, do not modify during output,
* null ignored
* @param output the OutputStream to write to
* @param encoding the encoding to use, null means platform default
* @throws NullPointerException if output is null
* @throws IOException if an I/O error occurs
* @since 2.3
*/
public static void write(char[] data, OutputStream output, Charset encoding) throws IOException {
if (data != null) {
output.write(StringCodingUtils.getBytes(new String(data), Charsets.toCharset(encoding)));
}
}
/**
* Writes chars from a char[] to bytes on an
* OutputStream using the specified character encoding.
*
* Character encoding names can be found at
* iaNa.
*
* This method uses {@link String#String(char[])} and
* {@link String#getBytes(String)}.
*
* @param data the char array to write, do not modify during output,
* null ignored
* @param output the OutputStream to write to
* @param encoding the encoding to use, null means platform default
* @throws NullPointerException if output is null
* @throws IOException if an I/O error occurs
* @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link UnsupportedEncodingException} in version 2.2 if the encoding is not
* supported.
* @since 1.1
*/
public static void write(char[] data, OutputStream output, String encoding)
throws IOException {
write(data, output, Charsets.toCharset(encoding));
}
// write CharSequence
//-----------------------------------------------------------------------
/**
* Writes chars from a CharSequence to a Writer.
*
* @param data the CharSequence to write, null ignored
* @param output the Writer to write to
* @throws NullPointerException if output is null
* @throws IOException if an I/O error occurs
* @since 2.0
*/
public static void write(CharSequence data, Writer output) throws IOException {
if (data != null) {
write(data.toString(), output);
}
}
/**
* Writes chars from a CharSequence to bytes on an
* OutputStream using the default character encoding of the
* platform.
*
* This method uses {@link String#getBytes()}.
*
* @param data the CharSequence to write, null ignored
* @param output the OutputStream to write to
* @throws NullPointerException if output is null
* @throws IOException if an I/O error occurs
* @since 2.0
*/
public static void write(CharSequence data, OutputStream output)
throws IOException {
write(data, output, Charset.defaultCharset());
}
/**
* Writes chars from a CharSequence to bytes on an
* OutputStream using the specified character encoding.
*
* This method uses {@link String#getBytes(String)}.
*
* @param data the CharSequence to write, null ignored
* @param output the OutputStream to write to
* @param encoding the encoding to use, null means platform default
* @throws NullPointerException if output is null
* @throws IOException if an I/O error occurs
* @since 2.3
*/
public static void write(CharSequence data, OutputStream output, Charset encoding) throws IOException {
if (data != null) {
write(data.toString(), output, encoding);
}
}
/**
* Writes chars from a CharSequence to bytes on an
* OutputStream using the specified character encoding.
*
* Character encoding names can be found at
* iaNa.
*
* This method uses {@link String#getBytes(String)}.
*
* @param data the CharSequence to write, null ignored
* @param output the OutputStream to write to
* @param encoding the encoding to use, null means platform default
* @throws NullPointerException if output is null
* @throws IOException if an I/O error occurs
* @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link UnsupportedEncodingException} in version 2.2 if the encoding is not
* supported.
* @since 2.0
*/
public static void write(CharSequence data, OutputStream output, String encoding) throws IOException {
write(data, output, Charsets.toCharset(encoding));
}
// write String
//-----------------------------------------------------------------------
/**
* Writes chars from a String to a Writer.
*
* @param data the String to write, null ignored
* @param output the Writer to write to
* @throws NullPointerException if output is null
* @throws IOException if an I/O error occurs
* @since 1.1
*/
public static void write(String data, Writer output) throws IOException {
if (data != null) {
output.write(data);
}
}
/**
* Writes chars from a String to bytes on an
* OutputStream using the default character encoding of the
* platform.
*
* This method uses {@link String#getBytes()}.
*
* @param data the String to write, null ignored
* @param output the OutputStream to write to
* @throws NullPointerException if output is null
* @throws IOException if an I/O error occurs
* @since 1.1
*/
public static void write(String data, OutputStream output)
throws IOException {
write(data, output, Charset.defaultCharset());
}
/**
* Writes chars from a String to bytes on an
* OutputStream using the specified character encoding.
*
* This method uses {@link String#getBytes(String)}.
*
* @param data the String to write, null ignored
* @param output the OutputStream to write to
* @param encoding the encoding to use, null means platform default
* @throws NullPointerException if output is null
* @throws IOException if an I/O error occurs
* @since 2.3
*/
public static void write(String data, OutputStream output, Charset encoding) throws IOException {
if (data != null) {
output.write(StringCodingUtils.getBytes(data, Charsets.toCharset(encoding)));
}
}
/**
* Writes chars from a String to bytes on an
* OutputStream using the specified character encoding.
*
* Character encoding names can be found at
* iaNa.
*
* This method uses {@link String#getBytes(String)}.
*
* @param data the String to write, null ignored
* @param output the OutputStream to write to
* @param encoding the encoding to use, null means platform default
* @throws NullPointerException if output is null
* @throws IOException if an I/O error occurs
* @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link UnsupportedEncodingException} in version 2.2 if the encoding is not
* supported.
* @since 1.1
*/
public static void write(String data, OutputStream output, String encoding)
throws IOException {
write(data, output, Charsets.toCharset(encoding));
}
// write StringBuffer
//-----------------------------------------------------------------------
/**
* Writes chars from a StringBuffer to a Writer.
*
* @param data the StringBuffer to write, null ignored
* @param output the Writer to write to
* @throws NullPointerException if output is null
* @throws IOException if an I/O error occurs
* @since 1.1
* @deprecated replaced by write(CharSequence, Writer)
*/
@Deprecated
public static void write(StringBuffer data, Writer output)
throws IOException {
if (data != null) {
output.write(data.toString());
}
}
/**
* Writes chars from a StringBuffer to bytes on an
* OutputStream using the default character encoding of the
* platform.
*
* This method uses {@link String#getBytes()}.
*
* @param data the StringBuffer to write, null ignored
* @param output the OutputStream to write to
* @throws NullPointerException if output is null
* @throws IOException if an I/O error occurs
* @since 1.1
* @deprecated replaced by write(CharSequence, OutputStream)
*/
@Deprecated
public static void write(StringBuffer data, OutputStream output)
throws IOException {
//noinspection deprecation
write(data, output, (String) null);
}
/**
* Writes chars from a StringBuffer to bytes on an
* OutputStream using the specified character encoding.
*
* Character encoding names can be found at
* iaNa.
*
* This method uses {@link String#getBytes(String)}.
*
* @param data the StringBuffer to write, null ignored
* @param output the OutputStream to write to
* @param encoding the encoding to use, null means platform default
* @throws NullPointerException if output is null
* @throws IOException if an I/O error occurs
* @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link UnsupportedEncodingException} in version 2.2 if the encoding is not
* supported.
* @since 1.1
* @deprecated replaced by write(CharSequence, OutputStream, String)
*/
@Deprecated
public static void write(StringBuffer data, OutputStream output, String encoding) throws IOException {
if (data != null) {
output.write(StringCodingUtils.getBytes(data.toString(), Charsets.toCharset(encoding)));
}
}
// writeLines
//-----------------------------------------------------------------------
/**
* Writes the toString() value of each item in a collection to
* an OutputStream line by line, using the default character
* encoding of the platform and the specified line ending.
*
* @param lines the lines to write, null entries produce blank lines
* @param lineEnding the line separator to use, null is system default
* @param output the OutputStream to write to, not null, not closed
* @throws NullPointerException if the output is null
* @throws IOException if an I/O error occurs
* @since 1.1
*/
public static void writeLines(Collection> lines, String lineEnding,
OutputStream output) throws IOException {
writeLines(lines, lineEnding, output, Charset.defaultCharset());
}
/**
* Writes the toString() value of each item in a collection to
* an OutputStream line by line, using the specified character
* encoding and the specified line ending.
*
* @param lines the lines to write, null entries produce blank lines
* @param lineEnding the line separator to use, null is system default
* @param output the OutputStream to write to, not null, not closed
* @param encoding the encoding to use, null means platform default
* @throws NullPointerException if the output is null
* @throws IOException if an I/O error occurs
* @since 2.3
*/
public static void writeLines(Collection> lines, String lineEnding, OutputStream output, Charset encoding)
throws IOException {
if (lines == null) {
return;
}
if (lineEnding == null) {
lineEnding = LINE_SEPARATOR;
}
Charset cs = Charsets.toCharset(encoding);
for (Object line : lines) {
if (line != null) {
output.write(StringCodingUtils.getBytes(line.toString(), cs));
}
output.write(StringCodingUtils.getBytes(lineEnding, cs));
}
}
/**
* Writes the toString() value of each item in a collection to
* an OutputStream line by line, using the specified character
* encoding and the specified line ending.
*
* Character encoding names can be found at
* iaNa.
*
* @param lines the lines to write, null entries produce blank lines
* @param lineEnding the line separator to use, null is system default
* @param output the OutputStream to write to, not null, not closed
* @param encoding the encoding to use, null means platform default
* @throws NullPointerException if the output is null
* @throws IOException if an I/O error occurs
* @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link UnsupportedEncodingException} in version 2.2 if the encoding is not
* supported.
* @since 1.1
*/
public static void writeLines(Collection> lines, String lineEnding,
OutputStream output, String encoding) throws IOException {
writeLines(lines, lineEnding, output, Charsets.toCharset(encoding));
}
/**
* Writes the toString() value of each item in a collection to
* a Writer line by line, using the specified line ending.
*
* @param lines the lines to write, null entries produce blank lines
* @param lineEnding the line separator to use, null is system default
* @param writer the Writer to write to, not null, not closed
* @throws NullPointerException if the input is null
* @throws IOException if an I/O error occurs
* @since 1.1
*/
public static void writeLines(Collection> lines, String lineEnding,
Writer writer) throws IOException {
if (lines == null) {
return;
}
if (lineEnding == null) {
lineEnding = LINE_SEPARATOR;
}
for (Object line : lines) {
if (line != null) {
writer.write(line.toString());
}
writer.write(lineEnding);
}
}
// copy from InputStream
//-----------------------------------------------------------------------
/**
* Copy bytes from an InputStream to an
* OutputStream.
*
* This method buffers the input internally, so there is no need to use a
* BufferedInputStream.
*
* Large streams (over 2GB) will return a bytes copied value of
* -1 after the copy has completed since the correct
* number of bytes cannot be returned as an int. For large streams
* use the copyLarge(InputStream, OutputStream) method.
*
* @param input the InputStream to read from
* @param output the OutputStream to write to
* @return the number of bytes copied, or -1 if > Integer.MAX_VALUE
* @throws NullPointerException if the input or output is null
* @throws IOException if an I/O error occurs
* @since 1.1
*/
@SuppressWarnings("UnusedReturnValue")
public static int copy(InputStream input, OutputStream output) throws IOException {
long count = copyLarge(input, output);
if (count > Integer.MAX_VALUE) {
return -1;
}
return (int) count;
}
/**
* Copy bytes from a large (over 2GB) InputStream to an
* OutputStream.
*
* This method buffers the input internally, so there is no need to use a
* BufferedInputStream.
*
* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
*
* @param input the InputStream to read from
* @param output the OutputStream to write to
* @return the number of bytes copied
* @throws NullPointerException if the input or output is null
* @throws IOException if an I/O error occurs
* @since 1.3
*/
public static long copyLarge(InputStream input, OutputStream output)
throws IOException {
return copyLarge(input, output, new byte[DEFAULT_BUFFER_SIZE]);
}
/**
* Copy bytes from a large (over 2GB) InputStream to an
* OutputStream.
*
* This method uses the provided buffer, so there is no need to use a
* BufferedInputStream.
*
*
* @param input the InputStream to read from
* @param output the OutputStream to write to
* @param buffer the buffer to use for the copy
* @return the number of bytes copied
* @throws NullPointerException if the input or output is null
* @throws IOException if an I/O error occurs
* @since 2.2
*/
public static long copyLarge(InputStream input, OutputStream output, byte[] buffer)
throws IOException {
long count = 0;
int n;
while (EOF != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
/**
* Copy some or all bytes from a large (over 2GB) InputStream to an
* OutputStream, optionally skipping input bytes.
*
* This method buffers the input internally, so there is no need to use a
* BufferedInputStream.
*
* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
*
* @param input the InputStream to read from
* @param output the OutputStream to write to
* @param inputOffset : number of bytes to skip from input before copying
* -ve values are ignored
* @param length : number of bytes to copy. -ve means all
* @return the number of bytes copied
* @throws NullPointerException if the input or output is null
* @throws IOException if an I/O error occurs
* @since 2.2
*/
public static long copyLarge(InputStream input, OutputStream output, long inputOffset, long length)
throws IOException {
return copyLarge(input, output, inputOffset, length, new byte[DEFAULT_BUFFER_SIZE]);
}
/**
* Copy some or all bytes from a large (over 2GB) InputStream to an
* OutputStream, optionally skipping input bytes.
*
* This method uses the provided buffer, so there is no need to use a
* BufferedInputStream.
*
*
* @param input the InputStream to read from
* @param output the OutputStream to write to
* @param inputOffset : number of bytes to skip from input before copying
* -ve values are ignored
* @param length : number of bytes to copy. -ve means all
* @param buffer the buffer to use for the copy
* @return the number of bytes copied
* @throws NullPointerException if the input or output is null
* @throws IOException if an I/O error occurs
* @since 2.2
*/
public static long copyLarge(InputStream input, OutputStream output,
final long inputOffset, final long length, byte[] buffer) throws IOException {
if (inputOffset > 0) {
skipFully(input, inputOffset);
}
if (length == 0) {
return 0;
}
final int bufferLength = buffer.length;
int bytesToRead = bufferLength;
if (length > 0 && length < bufferLength) {
bytesToRead = (int) length;
}
int read;
long totalRead = 0;
while (bytesToRead > 0 && EOF != (read = input.read(buffer, 0, bytesToRead))) {
output.write(buffer, 0, read);
totalRead += read;
if (length > 0) { // only adjust length if not reading to the end
// Note the cast must work because buffer.length is an integer
bytesToRead = (int) Math.min(length - totalRead, bufferLength);
}
}
return totalRead;
}
/**
* Copy bytes from an InputStream to chars on a
* Writer using the default character encoding of the platform.
*
* This method buffers the input internally, so there is no need to use a
* BufferedInputStream.
*
* This method uses {@link InputStreamReader}.
*
* @param input the InputStream to read from
* @param output the Writer to write to
* @throws NullPointerException if the input or output is null
* @throws IOException if an I/O error occurs
* @since 1.1
*/
public static void copy(InputStream input, Writer output)
throws IOException {
copy(input, output, Charset.defaultCharset());
}
/**
* Copy bytes from an InputStream to chars on a
* Writer using the specified character encoding.
*
* This method buffers the input internally, so there is no need to use a
* BufferedInputStream.
*
* This method uses {@link InputStreamReader}.
*
* @param input the InputStream to read from
* @param output the Writer to write to
* @param encoding the encoding to use, null means platform default
* @throws NullPointerException if the input or output is null
* @throws IOException if an I/O error occurs
* @since 2.3
*/
public static void copy(InputStream input, Writer output, Charset encoding) throws IOException {
InputStreamReader in = new InputStreamReader(input, Charsets.toCharset(encoding));
copy(in, output);
}
/**
* Copy bytes from an InputStream to chars on a
* Writer using the specified character encoding.
*
* This method buffers the input internally, so there is no need to use a
* BufferedInputStream.
*
* Character encoding names can be found at
* iaNa.
*
* This method uses {@link InputStreamReader}.
*
* @param input the InputStream to read from
* @param output the Writer to write to
* @param encoding the encoding to use, null means platform default
* @throws NullPointerException if the input or output is null
* @throws IOException if an I/O error occurs
* @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link UnsupportedEncodingException} in version 2.2 if the encoding is not
* supported.
* @since 1.1
*/
public static void copy(InputStream input, Writer output, String encoding) throws IOException {
copy(input, output, Charsets.toCharset(encoding));
}
// copy from Reader
//-----------------------------------------------------------------------
/**
* Copy chars from a Reader to a Writer.
*
* This method buffers the input internally, so there is no need to use a
* BufferedReader.
*
* Large streams (over 2GB) will return a chars copied value of
* -1 after the copy has completed since the correct
* number of chars cannot be returned as an int. For large streams
* use the copyLarge(Reader, Writer) method.
*
* @param input the Reader to read from
* @param output the Writer to write to
* @return the number of characters copied, or -1 if > Integer.MAX_VALUE
* @throws NullPointerException if the input or output is null
* @throws IOException if an I/O error occurs
* @since 1.1
*/
@SuppressWarnings("UnusedReturnValue")
public static int copy(Reader input, Writer output) throws IOException {
long count = copyLarge(input, output);
if (count > Integer.MAX_VALUE) {
return -1;
}
return (int) count;
}
/**
* Copy chars from a large (over 2GB) Reader to a Writer.
*
* This method buffers the input internally, so there is no need to use a
* BufferedReader.
*
* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
*
* @param input the Reader to read from
* @param output the Writer to write to
* @return the number of characters copied
* @throws NullPointerException if the input or output is null
* @throws IOException if an I/O error occurs
* @since 1.3
*/
public static long copyLarge(Reader input, Writer output) throws IOException {
return copyLarge(input, output, new char[DEFAULT_BUFFER_SIZE]);
}
/**
* Copy chars from a large (over 2GB) Reader to a Writer.
*
* This method uses the provided buffer, so there is no need to use a
* BufferedReader.
*
*
* @param input the Reader to read from
* @param output the Writer to write to
* @param buffer the buffer to be used for the copy
* @return the number of characters copied
* @throws NullPointerException if the input or output is null
* @throws IOException if an I/O error occurs
* @since 2.2
*/
public static long copyLarge(Reader input, Writer output, char[] buffer) throws IOException {
long count = 0;
int n;
while (EOF != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
/**
* Copy some or all chars from a large (over 2GB) InputStream to an
* OutputStream, optionally skipping input chars.
*
* This method buffers the input internally, so there is no need to use a
* BufferedReader.
*
* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
*
* @param input the Reader to read from
* @param output the Writer to write to
* @param inputOffset : number of chars to skip from input before copying
* -ve values are ignored
* @param length : number of chars to copy. -ve means all
* @return the number of chars copied
* @throws NullPointerException if the input or output is null
* @throws IOException if an I/O error occurs
* @since 2.2
*/
public static long copyLarge(Reader input, Writer output, final long inputOffset, final long length)
throws IOException {
return copyLarge(input, output, inputOffset, length, new char[DEFAULT_BUFFER_SIZE]);
}
/**
* Copy some or all chars from a large (over 2GB) InputStream to an
* OutputStream, optionally skipping input chars.
*
* This method uses the provided buffer, so there is no need to use a
* BufferedReader.
*
*
* @param input the Reader to read from
* @param output the Writer to write to
* @param inputOffset : number of chars to skip from input before copying
* -ve values are ignored
* @param length : number of chars to copy. -ve means all
* @param buffer the buffer to be used for the copy
* @return the number of chars copied
* @throws NullPointerException if the input or output is null
* @throws IOException if an I/O error occurs
* @since 2.2
*/
public static long copyLarge(Reader input, Writer output, final long inputOffset, final long length, char[] buffer)
throws IOException {
if (inputOffset > 0) {
skipFully(input, inputOffset);
}
if (length == 0) {
return 0;
}
int bytesToRead = buffer.length;
if (length > 0 && length < buffer.length) {
bytesToRead = (int) length;
}
int read;
long totalRead = 0;
while (bytesToRead > 0 && EOF != (read = input.read(buffer, 0, bytesToRead))) {
output.write(buffer, 0, read);
totalRead += read;
if (length > 0) { // only adjust length if not reading to the end
// Note the cast must work because buffer.length is an integer
bytesToRead = (int) Math.min(length - totalRead, buffer.length);
}
}
return totalRead;
}
/**
* Copy chars from a Reader to bytes on an
* OutputStream using the default character encoding of the
* platform, and calling flush.
*
* This method buffers the input internally, so there is no need to use a
* BufferedReader.
*
* Due to the implementation of OutputStreamWriter, this method performs a
* flush.
*
* This method uses {@link OutputStreamWriter}.
*
* @param input the Reader to read from
* @param output the OutputStream to write to
* @throws NullPointerException if the input or output is null
* @throws IOException if an I/O error occurs
* @since 1.1
*/
public static void copy(Reader input, OutputStream output)
throws IOException {
copy(input, output, Charset.defaultCharset());
}
/**
* Copy chars from a Reader to bytes on an
* OutputStream using the specified character encoding, and
* calling flush.
* BufferedReader.
* Reader to read from
* @param output the OutputStream to write to
* @param encoding the encoding to use, null means platform default
* @throws NullPointerException if the input or output is null
* @throws IOException if an I/O error occurs
* @since 2.3
*/
public static void copy(Reader input, OutputStream output, Charset encoding) throws IOException {
OutputStreamWriter out = new OutputStreamWriter(output, Charsets.toCharset(encoding));
copy(input, out);
// XXX Unless anyone is planning on rewriting OutputStreamWriter,
// we have to flush here.
out.flush();
}
/**
* Copy chars from a Reader to bytes on an
* OutputStream using the specified character encoding, and
* calling flush.
*
* This method buffers the input internally, so there is no need to use a
* BufferedReader.
*
* Character encoding names can be found at
* iaNa.
*
* Due to the implementation of OutputStreamWriter, this method performs a
* flush.
*
* This method uses {@link OutputStreamWriter}.
*
* @param input the Reader to read from
* @param output the OutputStream to write to
* @param encoding the encoding to use, null means platform default
* @throws NullPointerException if the input or output is null
* @throws IOException if an I/O error occurs
* @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link UnsupportedEncodingException} in version 2.2 if the encoding is not
* supported.
* @since 1.1
*/
public static void copy(Reader input, OutputStream output, String encoding) throws IOException {
copy(input, output, Charsets.toCharset(encoding));
}
// content equals
//-----------------------------------------------------------------------
/**
* Compare the contents of two Streams to determine if they are equal or
* not.
*
* This method buffers the input internally using
* BufferedInputStream if they are not already buffered.
*
* @param input1 the first stream
* @param input2 the second stream
* @return true if the content of the streams are equal or they both don't
* exist, false otherwise
* @throws NullPointerException if either input is null
* @throws IOException if an I/O error occurs
*/
public static boolean contentEquals(InputStream input1, InputStream input2)
throws IOException {
if (!(input1 instanceof BufferedInputStream)) {
input1 = new BufferedInputStream(input1);
}
if (!(input2 instanceof BufferedInputStream)) {
input2 = new BufferedInputStream(input2);
}
int ch = input1.read();
while (EOF != ch) {
int ch2 = input2.read();
if (ch != ch2) {
return false;
}
ch = input1.read();
}
int ch2 = input2.read();
return ch2 == EOF;
}
/**
* Compare the contents of two Readers to determine if they are equal or
* not.
*
* This method buffers the input internally using
* BufferedReader if they are not already buffered.
*
* @param input1 the first reader
* @param input2 the second reader
* @return true if the content of the readers are equal or they both don't
* exist, false otherwise
* @throws NullPointerException if either input is null
* @throws IOException if an I/O error occurs
* @since 1.1
*/
public static boolean contentEquals(Reader input1, Reader input2)
throws IOException {
input1 = toBufferedReader(input1);
input2 = toBufferedReader(input2);
int ch = input1.read();
while (EOF != ch) {
int ch2 = input2.read();
if (ch != ch2) {
return false;
}
ch = input1.read();
}
int ch2 = input2.read();
return ch2 == EOF;
}
/**
* Compare the contents of two Readers to determine if they are equal or
* not, ignoring EOL characters.
*
* This method buffers the input internally using
* BufferedReader if they are not already buffered.
*
* @param input1 the first reader
* @param input2 the second reader
* @return true if the content of the readers are equal (ignoring EOL differences), false otherwise
* @throws NullPointerException if either input is null
* @throws IOException if an I/O error occurs
* @since 2.2
*/
public static boolean contentEqualsIgnoreEOL(Reader input1, Reader input2)
throws IOException {
BufferedReader br1 = toBufferedReader(input1);
BufferedReader br2 = toBufferedReader(input2);
String line1 = br1.readLine();
String line2 = br2.readLine();
while (line1 != null && line2 != null && line1.equals(line2)) {
line1 = br1.readLine();
line2 = br2.readLine();
}
return line1 == null ? line2 == null : line1.equals(line2);
}
/**
* Skip bytes from an input byte stream.
* This implementation guarantees that it will read as many bytes
* as possible before giving up; this may not always be the case for
* subclasses of {@link Reader}.
*
* @param input byte stream to skip
* @param toSkip number of bytes to skip.
* @return number of bytes actually skipped.
* @throws IOException if there is a problem reading the file
* @throws IllegalArgumentException if toSkip is negative
* @see InputStream#skip(long)
* @since 2.0
*/
public static long skip(InputStream input, long toSkip) throws IOException {
if (toSkip < 0) {
throw new IllegalArgumentException("Skip count must be non-negative, actual: " + toSkip);
}
/*
* N.B. no need to synchronize this because: - we don't care if the buffer is created multiple times (the data
* is ignored) - we always use the same size buffer, so if it it is recreated it will still be OK (if the buffer
* size were variable, we would need to sync. to ensure some other thread did not create a smaller one)
*/
if (SKIP_BYTE_BUFFER == null) {
SKIP_BYTE_BUFFER = new byte[SKIP_BUFFER_SIZE];
}
long remain = toSkip;
while (remain > 0) {
long n = input.read(SKIP_BYTE_BUFFER, 0, (int) Math.min(remain, SKIP_BUFFER_SIZE));
if (n < 0) { // EOF
break;
}
remain -= n;
}
return toSkip - remain;
}
/**
* Skip characters from an input character stream.
* This implementation guarantees that it will read as many characters
* as possible before giving up; this may not always be the case for
* subclasses of {@link Reader}.
*
* @param input character stream to skip
* @param toSkip number of characters to skip.
* @return number of characters actually skipped.
* @throws IOException if there is a problem reading the file
* @throws IllegalArgumentException if toSkip is negative
* @see Reader#skip(long)
* @since 2.0
*/
public static long skip(Reader input, long toSkip) throws IOException {
if (toSkip < 0) {
throw new IllegalArgumentException("Skip count must be non-negative, actual: " + toSkip);
}
/*
* N.B. no need to synchronize this because: - we don't care if the buffer is created multiple times (the data
* is ignored) - we always use the same size buffer, so if it it is recreated it will still be OK (if the buffer
* size were variable, we would need to sync. to ensure some other thread did not create a smaller one)
*/
if (SKIP_CHAR_BUFFER == null) {
SKIP_CHAR_BUFFER = new char[SKIP_BUFFER_SIZE];
}
long remain = toSkip;
while (remain > 0) {
long n = input.read(SKIP_CHAR_BUFFER, 0, (int) Math.min(remain, SKIP_BUFFER_SIZE));
if (n < 0) { // EOF
break;
}
remain -= n;
}
return toSkip - remain;
}
/**
* Skip the requested number of bytes or fail if there are not enough left.
*
* This allows for the possibility that {@link InputStream#skip(long)} may
* not skip as many bytes as requested (most likely because of reaching EOF).
*
* @param input stream to skip
* @param toSkip the number of bytes to skip
* @throws IOException if there is a problem reading the file
* @throws IllegalArgumentException if toSkip is negative
* @throws EOFException if the number of bytes skipped was incorrect
* @see InputStream#skip(long)
* @since 2.0
*/
public static void skipFully(InputStream input, long toSkip) throws IOException {
if (toSkip < 0) {
throw new IllegalArgumentException("Bytes to skip must not be negative: " + toSkip);
}
long skipped = skip(input, toSkip);
if (skipped != toSkip) {
throw new EOFException("Bytes to skip: " + toSkip + " actual: " + skipped);
}
}
/**
* Skip the requested number of characters or fail if there are not enough left.
*
* This allows for the possibility that {@link Reader#skip(long)} may
* not skip as many characters as requested (most likely because of reaching EOF).
*
* @param input stream to skip
* @param toSkip the number of characters to skip
* @throws IOException if there is a problem reading the file
* @throws IllegalArgumentException if toSkip is negative
* @throws EOFException if the number of characters skipped was incorrect
* @see Reader#skip(long)
* @since 2.0
*/
public static void skipFully(Reader input, long toSkip) throws IOException {
long skipped = skip(input, toSkip);
if (skipped != toSkip) {
throw new EOFException("Chars to skip: " + toSkip + " actual: " + skipped);
}
}
/**
* Read characters from an input character stream.
* This implementation guarantees that it will read as many characters
* as possible before giving up; this may not always be the case for
* subclasses of {@link Reader}.
*
* @param input where to read input from
* @param buffer destination
* @param offset inital offset into buffer
* @param length length to read, must be >= 0
* @return actual length read; may be less than requested if EOF was reached
* @throws IOException if a read error occurs
* @since 2.2
*/
public static int read(Reader input, char[] buffer, int offset, int length) throws IOException {
if (length < 0) {
throw new IllegalArgumentException("Length must not be negative: " + length);
}
int remaining = length;
while (remaining > 0) {
int location = length - remaining;
int count = input.read(buffer, offset + location, remaining);
if (EOF == count) { // EOF
break;
}
remaining -= count;
}
return length - remaining;
}
/**
* Read characters from an input character stream.
* This implementation guarantees that it will read as many characters
* as possible before giving up; this may not always be the case for
* subclasses of {@link Reader}.
*
* @param input where to read input from
* @param buffer destination
* @return actual length read; may be less than requested if EOF was reached
* @throws IOException if a read error occurs
* @since 2.2
*/
public static int read(Reader input, char[] buffer) throws IOException {
return read(input, buffer, 0, buffer.length);
}
/**
* Read bytes from an input stream.
* This implementation guarantees that it will read as many bytes
* as possible before giving up; this may not always be the case for
* subclasses of {@link InputStream}.
*
* @param input where to read input from
* @param buffer destination
* @param offset inital offset into buffer
* @param length length to read, must be >= 0
* @return actual length read; may be less than requested if EOF was reached
* @throws IOException if a read error occurs
* @since 2.2
*/
public static int read(InputStream input, byte[] buffer, int offset, int length) throws IOException {
if (length < 0) {
throw new IllegalArgumentException("Length must not be negative: " + length);
}
int remaining = length;
while (remaining > 0) {
int location = length - remaining;
int count = input.read(buffer, offset + location, remaining);
if (EOF == count) { // EOF
break;
}
remaining -= count;
}
return length - remaining;
}
/**
* Read bytes from an input stream.
* This implementation guarantees that it will read as many bytes
* as possible before giving up; this may not always be the case for
* subclasses of {@link InputStream}.
*
* @param input where to read input from
* @param buffer destination
* @return actual length read; may be less than requested if EOF was reached
* @throws IOException if a read error occurs
* @since 2.2
*/
public static int read(InputStream input, byte[] buffer) throws IOException {
return read(input, buffer, 0, buffer.length);
}
/**
* Read the requested number of characters or fail if there are not enough left.
*
* This allows for the possibility that {@link Reader#read(char[], int, int)} may
* not read as many characters as requested (most likely because of reaching EOF).
*
* @param input where to read input from
* @param buffer destination
* @param offset inital offset into buffer
* @param length length to read, must be >= 0
* @throws IOException if there is a problem reading the file
* @throws IllegalArgumentException if length is negative
* @throws EOFException if the number of characters read was incorrect
* @since 2.2
*/
@SuppressWarnings("SameParameterValue")
public static void readFully(Reader input, char[] buffer, int offset, int length) throws IOException {
int actual = read(input, buffer, offset, length);
if (actual != length) {
throw new EOFException("Length to read: " + length + " actual: " + actual);
}
}
/**
* Read the requested number of characters or fail if there are not enough left.
*
* This allows for the possibility that {@link Reader#read(char[], int, int)} may
* not read as many characters as requested (most likely because of reaching EOF).
*
* @param input where to read input from
* @param buffer destination
* @throws IOException if there is a problem reading the file
* @throws IllegalArgumentException if length is negative
* @throws EOFException if the number of characters read was incorrect
* @since 2.2
*/
public static void readFully(Reader input, char[] buffer) throws IOException {
readFully(input, buffer, 0, buffer.length);
}
/**
* Read the requested number of bytes or fail if there are not enough left.
*
* This allows for the possibility that {@link InputStream#read(byte[], int, int)} may
* not read as many bytes as requested (most likely because of reaching EOF).
*
* @param input where to read input from
* @param buffer destination
* @param offset inital offset into buffer
* @param length length to read, must be >= 0
* @throws IOException if there is a problem reading the file
* @throws IllegalArgumentException if length is negative
* @throws EOFException if the number of bytes read was incorrect
* @since 2.2
*/
@SuppressWarnings("SameParameterValue")
public static void readFully(InputStream input, byte[] buffer, int offset, int length) throws IOException {
int actual = read(input, buffer, offset, length);
if (actual != length) {
throw new EOFException("Length to read: " + length + " actual: " + actual);
}
}
/**
* Read the requested number of bytes or fail if there are not enough left.
*
* This allows for the possibility that {@link InputStream#read(byte[], int, int)} may
* not read as many bytes as requested (most likely because of reaching EOF).
*
* @param input where to read input from
* @param buffer destination
* @throws IOException if there is a problem reading the file
* @throws IllegalArgumentException if length is negative
* @throws EOFException if the number of bytes read was incorrect
* @since 2.2
*/
public static void readFully(InputStream input, byte[] buffer) throws IOException {
readFully(input, buffer, 0, buffer.length);
}
}
================================================
FILE: aliocrlib/src/main/java/com/lib/aliocr/utils/io/SdCardUtil.java
================================================
package com.lib.aliocr.utils.io;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
/**
* 作者:xin on 2018/7/9 0009 15:03
* toByteArray() and
* toString().
* InputStream and represent
* same data as result InputStream.
*
*
* It can be used in favor of {@link #toByteArray()}, since it
* avoids unnecessary allocation and copy of byte[].
* This method buffers the input internally, so there is no need to use a
* BufferedInputStream.
*
* @param input Stream to be fully buffered.
* @return A fully buffered stream.
* @throws IOException if an I/O error occurs
* @since 2.0
*/
public static InputStream toBufferedInputStream(InputStream input)
throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
output.write(input);
return output.toBufferedInputStream();
}
/**
* Gets the current contents of this byte stream as a Input Stream. The
* returned stream is backed by buffers of this stream,
* avoiding memory allocation and copy, thus saving space and time.
*
* @return the current contents of this output stream.
* @see java.io.ByteArrayOutputStream#toByteArray()
* @see #reset()
* @since 2.0
*/
private InputStream toBufferedInputStream() {
int remaining = count;
if (remaining == 0) {
return new ClosedInputStream();
}
Listjava.io.StringWriter, provides an un-synchronized
* (i.e. for use in a single thread) implementation for better performance.
* For safe usage with multiple {@link Thread}s then
* java.io.StringWriter should be used.
*
* @version $Id: StringBuilderWriter.java 1304052 2012-03-22 20:55:29Z ggregory $
* @since 2.0
*/
public class StringBuilderWriter extends Writer implements Serializable {
private static final long serialVersionUID = 8043747493392913171L;
private final StringBuilder builder;
/**
* Construct a new {@link StringBuilder} instance with default capacity.
*/
public StringBuilderWriter() {
this.builder = new StringBuilder();
}
/**
* Construct a new {@link StringBuilder} instance with the specified capacity.
*
* @param capacity The initial capacity of the underlying {@link StringBuilder}
*/
@SuppressWarnings("SameParameterValue")
public StringBuilderWriter(int capacity) {
this.builder = new StringBuilder(capacity);
}
/**
* Construct a new instance with the specified {@link StringBuilder}.
*
* @param builder The String builder
*/
public StringBuilderWriter(StringBuilder builder) {
this.builder = builder != null ? builder : new StringBuilder();
}
/**
* Append a single character to this Writer.
*
* @param value The character to append
* @return This writer instance
*/
@Override
public Writer append(char value) {
builder.append(value);
return this;
}
/**
* Append a character sequence to this Writer.
*
* @param value The character to append
* @return This writer instance
*/
@Override
public Writer append(CharSequence value) {
builder.append(value);
return this;
}
/**
* Append a portion of a character sequence to the {@link StringBuilder}.
*
* @param value The character to append
* @param start The index of the first character
* @param end The index of the last character + 1
* @return This writer instance
*/
@Override
public Writer append(CharSequence value, int start, int end) {
builder.append(value, start, end);
return this;
}
/**
* Closing this writer has no effect.
*/
@Override
public void close() {
}
/**
* Flushing this writer has no effect.
*/
@Override
public void flush() {
}
/**
* Write a String to the {@link StringBuilder}.
*
* @param value The value to write
*/
@Override
public void write(@NonNull String value) {
builder.append(value);
}
/**
* Write a portion of a character array to the {@link StringBuilder}.
*
* @param value The value to write
* @param offset The index of the first character
* @param length The number of characters to write
*/
@Override
public void write(@NonNull char[] value, int offset, int length) {
builder.append(value, offset, length);
}
/**
* Return the underlying builder.
*
* @return The underlying builder
*/
public StringBuilder getBuilder() {
return builder;
}
/**
* Returns {@link StringBuilder#toString()}.
*
* @return The contents of the String builder.
*/
@Override
public String toString() {
return builder.toString();
}
}
================================================
FILE: aliocrlib/src/main/java/com/lib/aliocr/view/OCRMainActivity.java
================================================
package com.lib.aliocr.view;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import com.lib.aliocr.R;
import com.lib.aliocr.callback.OcrCallback;
import com.lib.aliocr.contact.OcrContact;
import com.lib.aliocr.presenter.OCRPresenter;
import com.lib.aliocr.utils.Ocr;
import cameraview.CameraView;
/**
* 作者:xin on 2018/7/9 0009 15:03
*