Showing preview only (255K chars total). Download the full file or copy to clipboard to get everything.
Repository: maning0303/MNMLKitScanner
Branch: master
Commit: 05fc2a8129f5
Files: 76
Total size: 224.3 KB
Directory structure:
gitextract_hdq0awll/
├── .gitignore
├── .idea/
│ ├── codeStyles/
│ │ └── Project.xml
│ ├── compiler.xml
│ ├── encodings.xml
│ ├── gradle.xml
│ ├── inspectionProfiles/
│ │ └── Project_Default.xml
│ ├── jarRepositories.xml
│ ├── misc.xml
│ └── vcs.xml
├── LICENSE
├── README.md
├── apk/
│ └── demo.apk
├── app/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── androidTest/
│ │ └── java/
│ │ └── com/
│ │ └── maning/
│ │ └── mlkitscanner/
│ │ └── ExampleInstrumentedTest.java
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── maning/
│ │ │ └── mlkitscanner/
│ │ │ └── demo/
│ │ │ ├── CustomConfigActivity.java
│ │ │ └── MainActivity.java
│ │ └── res/
│ │ ├── anim/
│ │ │ ├── activity_anmie_in.xml
│ │ │ └── activity_anmie_out.xml
│ │ ├── drawable/
│ │ │ └── ic_launcher_background.xml
│ │ ├── drawable-v24/
│ │ │ └── ic_launcher_foreground.xml
│ │ ├── layout/
│ │ │ ├── activity_custom_config.xml
│ │ │ ├── activity_main.xml
│ │ │ └── layout_custom_view.xml
│ │ ├── mipmap-anydpi-v26/
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ └── values/
│ │ ├── array.xml
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test/
│ └── java/
│ └── com/
│ └── maning/
│ └── mlkitscanner/
│ └── ExampleUnitTest.java
├── build.gradle
├── config.gradle
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── mlkit-scanner/
│ ├── .gitignore
│ ├── build.gradle
│ ├── consumer-rules.pro
│ ├── proguard-rules.pro
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── com/
│ │ └── maning/
│ │ └── mlkitscanner/
│ │ └── scan/
│ │ ├── MNScanManager.java
│ │ ├── analyser/
│ │ │ └── BarcodeAnalyser.java
│ │ ├── callback/
│ │ │ ├── MNCustomViewBindCallback.java
│ │ │ ├── OnCameraAnalyserCallback.java
│ │ │ └── act/
│ │ │ ├── ActResultRequest.java
│ │ │ ├── MNScanCallback.java
│ │ │ └── OnActResultEventDispatcherFragment.java
│ │ ├── camera/
│ │ │ ├── CameraManager.java
│ │ │ └── CameraSizeUtils.java
│ │ ├── model/
│ │ │ └── MNScanConfig.java
│ │ ├── ui/
│ │ │ └── ScanPreviewActivity.java
│ │ ├── utils/
│ │ │ ├── AmbientLightManager.java
│ │ │ ├── BeepManager.java
│ │ │ ├── CommonUtils.java
│ │ │ ├── ImageUtils.java
│ │ │ ├── StatusBarUtil.java
│ │ │ └── ZXingUtils.java
│ │ └── view/
│ │ ├── ScanActionMenuView.java
│ │ ├── ScanResultPointView.java
│ │ └── ViewfinderView.java
│ └── res/
│ ├── anim/
│ │ ├── mn_scan_activity_bottom_in.xml
│ │ └── mn_scan_activity_bottom_out.xml
│ ├── drawable/
│ │ └── mn_scan_result_point_default.xml
│ ├── layout/
│ │ ├── mn_scan_action_menu.xml
│ │ ├── mn_scan_activity_scan_preview.xml
│ │ ├── mn_scan_result_point_item_view.xml
│ │ └── mn_scan_result_point_view.xml
│ ├── raw/
│ │ └── mn_scan_beep.ogg
│ └── values/
│ ├── colors.xml
│ └── styles.xml
└── settings.gradle
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
================================================
FILE: .idea/codeStyles/Project.xml
================================================
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<codeStyleSettings language="XML">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
</code_scheme>
</component>
================================================
FILE: .idea/compiler.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="1.8" />
</component>
</project>
================================================
FILE: .idea/encodings.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with NO BOM">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>
================================================
FILE: .idea/gradle.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="$USER_HOME$/Develop/Android/Gradle/gradle-6.1.1" />
<option name="gradleJvm" value="1.8" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
<option value="$PROJECT_DIR$/mlkit-scanner" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>
================================================
FILE: .idea/inspectionProfiles/Project_Default.xml
================================================
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true">
<option name="TOP_LEVEL_CLASS_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="INNER_CLASS_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="METHOD_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="@return@param@throws or @exception" />
</value>
</option>
<option name="FIELD_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="IGNORE_DEPRECATED" value="false" />
<option name="IGNORE_JAVADOC_PERIOD" value="true" />
<option name="IGNORE_DUPLICATED_THROWS" value="false" />
<option name="IGNORE_POINT_TO_ITSELF" value="false" />
<option name="myAdditionalJavadocTags" value="date" />
</inspection_tool>
</profile>
</component>
================================================
FILE: .idea/jarRepositories.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="BintrayJCenter" />
<option name="name" value="BintrayJCenter" />
<option name="url" value="https://jcenter.bintray.com/" />
</remote-repository>
<remote-repository>
<option name="id" value="Google" />
<option name="name" value="Google" />
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven" />
<option name="name" value="maven" />
<option name="url" value="https://jitpack.io" />
</remote-repository>
</component>
</project>
================================================
FILE: .idea/misc.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DesignSurface">
<option name="filePathToZoomLevelMap">
<map>
<entry key="app/src/main/res/layout/activity_custom_config.xml" value="0.18135528564453127" />
<entry key="app/src/main/res/layout/activity_main.xml" value="0.1" />
<entry key="mlkit-scanner/src/main/res/layout/mn_scan_activity_scan_preview.xml" value="0.1" />
</map>
</option>
</component>
<component name="MarkdownProjectSettings" wasCopied="true">
<PreviewSettings splitEditorLayout="SPLIT" splitEditorPreview="PREVIEW" useGrayscaleRendering="false" zoomFactor="1.0" maxImageWidth="0" showGitHubPageIfSynced="false" allowBrowsingInPreview="false" synchronizePreviewPosition="true" highlightPreviewType="NONE" highlightFadeOut="5" highlightOnTyping="true" synchronizeSourcePosition="true" verticallyAlignSourceAndPreviewSyncPosition="true" showSearchHighlightsInPreview="false" showSelectionInPreview="true" openRemoteLinks="true" replaceUnicodeEmoji="false" lastLayoutSetsDefault="false">
<PanelProvider>
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.panel" providerName="Default - Swing" />
</PanelProvider>
</PreviewSettings>
<ParserSettings gitHubSyntaxChange="false" emojiShortcuts="1" emojiImages="0">
<PegdownExtensions>
<option name="ABBREVIATIONS" value="false" />
<option name="ANCHORLINKS" value="true" />
<option name="ASIDE" value="false" />
<option name="ATXHEADERSPACE" value="true" />
<option name="AUTOLINKS" value="true" />
<option name="DEFINITIONS" value="false" />
<option name="DEFINITION_BREAK_DOUBLE_BLANK_LINE" value="false" />
<option name="FENCED_CODE_BLOCKS" value="true" />
<option name="FOOTNOTES" value="false" />
<option name="HARDWRAPS" value="false" />
<option name="HTML_DEEP_PARSER" value="false" />
<option name="INSERTED" value="false" />
<option name="QUOTES" value="false" />
<option name="RELAXEDHRULES" value="true" />
<option name="SMARTS" value="false" />
<option name="STRIKETHROUGH" value="true" />
<option name="SUBSCRIPT" value="false" />
<option name="SUPERSCRIPT" value="false" />
<option name="SUPPRESS_HTML_BLOCKS" value="false" />
<option name="SUPPRESS_INLINE_HTML" value="false" />
<option name="TABLES" value="true" />
<option name="TASKLISTITEMS" value="true" />
<option name="TOC" value="false" />
<option name="WIKILINKS" value="false" />
</PegdownExtensions>
<ParserOptions>
<option name="ADMONITION_EXT" value="false" />
<option name="ATTRIBUTES_EXT" value="false" />
<option name="COMMONMARK_LISTS" value="true" />
<option name="DUMMY" value="false" />
<option name="EMOJI_SHORTCUTS" value="true" />
<option name="ENUMERATED_REFERENCES_EXT" value="false" />
<option name="FLEXMARK_FRONT_MATTER" value="false" />
<option name="GFM_LOOSE_BLANK_LINE_AFTER_ITEM_PARA" value="false" />
<option name="GFM_TABLE_RENDERING" value="true" />
<option name="GITBOOK_URL_ENCODING" value="false" />
<option name="GITHUB_LISTS" value="false" />
<option name="GITHUB_WIKI_LINKS" value="false" />
<option name="GITLAB_EXT" value="false" />
<option name="GITLAB_MATH_EXT" value="false" />
<option name="GITLAB_MERMAID_EXT" value="false" />
<option name="HEADER_ID_NON_ASCII_TO_LOWERCASE" value="false" />
<option name="HEADER_ID_NO_DUPED_DASHES" value="false" />
<option name="JEKYLL_FRONT_MATTER" value="false" />
<option name="MACROS_EXT" value="false" />
<option name="NO_TEXT_ATTRIBUTES" value="false" />
<option name="PARSE_HTML_ANCHOR_ID" value="false" />
<option name="PLANTUML_FENCED_CODE" value="false" />
<option name="PUML_FENCED_CODE" value="false" />
<option name="SIM_TOC_BLANK_LINE_SPACER" value="true" />
</ParserOptions>
</ParserSettings>
<HtmlSettings headerTopEnabled="false" headerBottomEnabled="false" bodyTopEnabled="false" bodyBottomEnabled="false" embedUrlContent="false" addPageHeader="true" embedImages="false" embedHttpImages="false" imageUriSerials="false" addDocTypeHtml="true" noParaTags="false" plantUmlConversion="0" mathConversion="0">
<GeneratorProvider>
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.generator" providerName="Default Swing HTML Generator" />
</GeneratorProvider>
<headerTop />
<headerBottom />
<bodyTop />
<bodyBottom />
</HtmlSettings>
<CssSettings previewScheme="UI_SCHEME" cssUri="" isCssUriEnabled="false" isCssUriSerial="true" isCssTextEnabled="false" isDynamicPageWidth="true">
<StylesheetProvider>
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.css" providerName="Default Swing Stylesheet" />
</StylesheetProvider>
<ScriptProviders />
<cssText />
<cssUriHistory />
</CssSettings>
<HtmlExportSettings updateOnSave="false" parentDir="" targetDir="" cssDir="" scriptDir="" plainHtml="false" imageDir="" copyLinkedImages="false" imageUniquifyType="0" targetPathType="2" targetExt="" useTargetExt="false" noCssNoScripts="false" useElementStyleAttribute="false" linkToExportedHtml="true" exportOnSettingsChange="true" regenerateOnProjectOpen="false" linkFormatType="HTTP_ABSOLUTE" />
<LinkMapSettings>
<textMaps />
</LinkMapSettings>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>
================================================
FILE: .idea/vcs.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
================================================
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
================================================
# MNMLKitScanner 基于Google MLKit 快速集成二维码扫描,速度比zxing快
## 基于Google MLKit 快速集成二维码扫描,速度比zxing快,可配置相册,闪光灯,相机可以调整焦距放大缩小,自定义扫描线颜色,自定义背景颜色,自定义遮罩层,支持同时扫多个二维码和条形码
[](https://jitpack.io/#maning0303/MNMLKitScanner)
## 功能:
1:二维码扫描,手势缩放,无拉伸,样式自定义
2:相册中选取图片识别
3: 相机可以调整焦距放大缩小
4: 完全自定义遮罩层
5: 支持微信多个二维码/条形码同时扫描
6: 可调整扫描框大小
## 截图:
<div align="center">
<img src = "screenshots/mn_mlkit_scanner_ss_01.jpg" width=200 >
<img src = "screenshots/mn_mlkit_scanner_ss_02.jpg" width=200 >
<img src = "screenshots/mn_mlkit_scanner_ss_03.jpg" width=200 >
<img src = "screenshots/mn_mlkit_scanner_ss_05.jpg" width=200 >
<img src = "screenshots/mn_mlkit_scanner_ss_04.jpg" width=200 >
</div>
## 如何添加
### Gradle添加:
#### 1.在Project的build.gradle中添加仓库地址
``` gradle
allprojects {
repositories {
...
maven { url "https://jitpack.io" }
}
}
```
#### 2.在Module目录下的build.gradle中添加依赖
``` gradle
dependencies {
implementation 'com.github.maning0303:MNMLKitScanner:V1.0.4'
//下面版本自己控制,barcode-scanning>=17.0.2
implementation 'com.google.mlkit:barcode-scanning:17.0.2'
implementation "androidx.camera:camera-core:1.0.2"
implementation "androidx.camera:camera-camera2:1.0.2"
implementation "androidx.camera:camera-lifecycle:1.0.2"
implementation "androidx.camera:camera-view:1.0.0-alpha25"
}
```
#### 3.如果想加入二维码生成功能
``` gradle
dependencies {
implementation 'com.google.zxing:core:3.3.3'
}
```
com.maning.mlkitscanner.scan.utils.ZXingUtils 有具体的方法,详细可以查看Demo
## 使用方法:
### 进入需要提前申请相机权限;进入需要提前申请相机权限;进入需要提前申请相机权限;
``` java
1:开始扫描:
//默认扫描
MNScanManager.startScan(this, new MNScanCallback() {
@Override
public void onActivityResult(int resultCode, Intent data) {
switch (resultCode) {
case MNScanManager.RESULT_SUCCESS:
ArrayList<String> results = data.getStringArrayListExtra(MNScanManager.INTENT_KEY_RESULT_SUCCESS);
break;
case MNScanManager.RESULT_FAIL:
String resultError = data.getStringExtra(MNScanManager.INTENT_KEY_RESULT_ERROR);
break;
case MNScanManager.RESULT_CANCLE:
showToast("取消扫码");
break;
}
}
});
//自定义扫描
MNScanConfig scanConfig = new MNScanConfig.Builder()
//设置完成震动
.isShowVibrate(true)
//扫描完成声音
.isShowBeep(true)
//显示相册功能
.isShowPhotoAlbum(true)
//显示闪光灯
.isShowLightController(true)
//打开扫描页面的动画
.setActivityOpenAnime(R.anim.activity_anmie_in)
//退出扫描页面动画
.setActivityExitAnime(R.anim.activity_anmie_out)
//自定义文案
.setScanHintText("xxxx")
.setScanHintTextColor("#FF0000")
.setScanHintTextSize(14)
//扫描线的颜色
.setScanColor("#FF0000")
//是否支持手势缩放
.setSupportZoom(true)
//扫描线样式
.setLaserStyle(MNScanConfig.LaserStyle.Grid/MNScanConfig.LaserStyle.Line)
//背景颜色
.setBgColor("")
//网格扫描线的列数
.setGridScanLineColumn(30)
//网格高度
.setGridScanLineHeight(300)
//是否全屏扫描,默认全屏
.setFullScreenScan(true)
//单位dp
.setResultPointConfigs(36, 12, 3, colorResultPointStroke, colorResultPoint)
//状态栏设置
.setStatusBarConfigs(colorStatusBar, true)
//扫描框宽度大小比例,非全屏模式下生效,默认0.7,范围0.5-0.9
.setScanFrameSizeScale(0.7f)
//自定义遮罩
.setCustomShadeViewLayoutID(R.layout.layout_custom_view, new MNCustomViewBindCallback() {
@Override
public void onBindView(View customView) {
//TODO:通过findviewById 获取View
}
})
.builder();
MNScanManager.startScan(this, scanConfig, new MNScanCallback() {
@Override
public void onActivityResult(int resultCode, Intent data) {
switch (resultCode) {
case MNScanManager.RESULT_SUCCESS:
String resultSuccess = data.getStringExtra(MNScanManager.INTENT_KEY_RESULT_SUCCESS);
break;
case MNScanManager.RESULT_FAIL:
String resultError = data.getStringExtra(MNScanManager.INTENT_KEY_RESULT_ERROR);
break;
case MNScanManager.RESULT_CANCLE:
showToast("取消扫码");
break;
}
}
});
2.提供扫描界面相关方法(自定义遮罩层会使用):
/**
* 关闭当前页面
*/
MNScanManager.closeScanPage();
/**
* 打开相册扫描图片
*/
MNScanManager.openAlbumPage();
/**
* 打开手电筒
*/
MNScanManager.openScanLight();
/**
* 关闭手电筒
*/
MNScanManager.closeScanLight();
/**
* 手电筒是否开启
*/
MNScanManager.isLightOn();
```
## 感谢:
[googlesamples/mlkit](https://github.com/googlesamples/mlkit)
[jenly1314/MLKit](https://github.com/jenly1314/MLKit)
[Ye-Miao/StatusBarUtil](https://github.com/Ye-Miao/StatusBarUtil)
感谢所有开源的人;
## 推荐:
Name | Describe |
--- | --- |
[GankMM](https://github.com/maning0303/GankMM) | (Material Design & MVP & Retrofit + OKHttp & RecyclerView ...)Gank.io Android客户端:每天一张美女图片,一个视频短片,若干Android,iOS等程序干货,周一到周五每天更新,数据全部由 干货集中营 提供,持续更新。 |
[MNUpdateAPK](https://github.com/maning0303/MNUpdateAPK) | Android APK 版本更新的下载和安装,适配7.0,简单方便。 |
[MNImageBrowser](https://github.com/maning0303/MNImageBrowser) | 交互特效的图片浏览框架,微信向下滑动动态关闭 |
[MNZXingCode](https://github.com/maning0303/MNZXingCode) | 快速集成二维码扫描和生成二维码 |
[MNMLKitScanner](https://github.com/maning0303/MNMLKitScanner) | 基于Google MLKit 快速集成二维码扫描,速度比zxing快 |
[MNPasswordEditText](https://github.com/maning0303/MNPasswordEditText) | 类似微信支付宝的密码输入框。 |
[MClearEditText](https://github.com/maning0303/MClearEditText) | 带有删除功能的EditText |
[MNCrashMonitor](https://github.com/maning0303/MNCrashMonitor) | Debug监听程序崩溃日志,展示崩溃日志列表,方便自己平时调试。 |
[MNProgressHUD](https://github.com/maning0303/MNProgressHUD) | MNProgressHUD是对常用的自定义弹框封装,加载ProgressDialog,状态显示的StatusDialog和自定义Toast,支持背景颜色,圆角,边框和文字的自定义。 |
[SwitcherView](https://github.com/maning0303/SwitcherView) | 垂直滚动的广告栏文字展示。 |
[MNVideoPlayer](https://github.com/maning0303/MNVideoPlayer) | SurfaceView + MediaPlayer 实现的视频播放器,支持横竖屏切换,手势快进快退、调节音量,亮度等。------代码简单,新手可以看一看。 |
[MNChangeSkin](https://github.com/maning0303/MNChangeSkin) | Android夜间模式,通过Theme实现 |
[MNXUtilsDB](https://github.com/maning0303/MNXUtilsDB) | xUtils3 数据库模块单独抽取出来,方便使用。 |
[MNCalendar](https://github.com/maning0303/MNCalendar) | 简单的日历控件练习,水平方向日历支持手势滑动切换,跳转月份;垂直方向日历选取区间范围。 |
[MNSwipeToLoadDemo](https://github.com/maning0303/MNSwipeToLoadDemo) | 利用SwipeToLoadLayout实现的各种下拉刷新效果(饿了吗,京东,百度外卖,美团外卖,天猫下拉刷新等)。 |
================================================
FILE: app/.gitignore
================================================
/build
================================================
FILE: app/build.gradle
================================================
apply plugin: 'com.android.application'
def versions = rootProject.ext.versions
def appId = rootProject.ext.appId
def dependenciesGoogle = rootProject.ext.dependenciesGoogle
def dependenciesOther = rootProject.ext.dependenciesOther
android {
compileSdkVersion versions.compileSdkVersion
ndkVersion "20.1.5948944"
defaultConfig {
applicationId appId.app
minSdkVersion versions.minSdkVersion
targetSdkVersion versions.targetSdkVersion
versionCode versions.versionCode
versionName versions.versionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
// 循环引入库
dependenciesGoogle.each { k, v -> api v }
dependenciesOther.each { k, v -> api v }
dependenciesDebug.each { k, v -> debugImplementation v }
//扫码核心库
implementation project(path: ':mlkit-scanner')
// implementation 'com.github.maning0303:MNMLKitScanner:V1.0.4'
implementation 'com.google.mlkit:barcode-scanning:17.0.2'
implementation 'androidx.camera:camera-core:1.0.2'
implementation 'androidx.camera:camera-camera2:1.0.2'
implementation 'androidx.camera:camera-lifecycle:1.0.2'
implementation 'androidx.camera:camera-view:1.0.0-alpha25'
implementation 'com.google.zxing:core:3.3.3'
}
================================================
FILE: app/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
================================================
FILE: app/src/androidTest/java/com/maning/mlkitscanner/ExampleInstrumentedTest.java
================================================
package com.maning.mlkitscanner;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.maning.mlkitscanner", appContext.getPackageName());
}
}
================================================
FILE: app/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.maning.mlkitscanner.demo">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".CustomConfigActivity"
android:screenOrientation="portrait" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
================================================
FILE: app/src/main/java/com/maning/mlkitscanner/demo/CustomConfigActivity.java
================================================
package com.maning.mlkitscanner.demo;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.maning.mlkitscanner.scan.MNScanManager;
import com.maning.mlkitscanner.scan.callback.MNCustomViewBindCallback;
import com.maning.mlkitscanner.scan.callback.act.MNScanCallback;
import com.maning.mlkitscanner.scan.model.MNScanConfig;
import java.util.ArrayList;
import top.defaults.colorpicker.ColorPickerPopup;
public class CustomConfigActivity extends AppCompatActivity implements View.OnClickListener {
/**
* 是否显示相册功能
*/
private CheckBox mCbPhoto;
/**
* 是否显示闪光灯
*/
private CheckBox mCbLight;
/**
* 是否需要全屏扫描识别(默认)
*/
private CheckBox mCbFullscreenScan;
/**
* 是否开启扫描完成震动提醒
*/
private CheckBox mCbVibrate;
/**
* 是否开启扫描完成声音提醒
*/
private CheckBox mCbBeep;
/**
* 是否完全自定义遮罩层
*/
private CheckBox mCbCustomView;
/**
* 输入自定义提示文案
*/
private EditText mEtHintText;
/**
* 文字大小(sp)
*/
private EditText mEtHintTextSize;
/**
* 网格扫描高度
*/
private EditText mEtGridlineHeight;
/**
* 网格扫描列数
*/
private EditText mEtGridlineNum;
private TextView mBtnColorPickerText;
private TextView mBtnColorPickerLine;
private TextView mBtnColorPickerBg;
/**
* 线性
*/
private RadioButton mRbScanlineLine;
/**
* 网格
*/
private RadioButton mRbScanlineGrid;
private String colorText = "#22CE6B";
private String colorLine = "#22CE6B";
private String colorBackground = "#22FF0000";
private String colorStatusBar = "#00000000";
private String colorResultPoint = "#CC22CE6B";
private String colorResultPointStroke = "#FFFFFFFF";
/**
* 是否支持手势缩放
*/
private CheckBox mCbSupportZoom;
/**
* 是否状态栏黑色字体
*/
private CheckBox mCbStatusDark;
private TextView mBtnColorStatusbarBg;
private SeekBar mSbarFrameSize;
private TextView mTvFrameSize;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_config);
initView();
}
private void initView() {
mCbPhoto = (CheckBox) findViewById(R.id.cb_photo);
mCbLight = (CheckBox) findViewById(R.id.cb_light);
mCbFullscreenScan = (CheckBox) findViewById(R.id.cb_fullscreen_scan);
mCbVibrate = (CheckBox) findViewById(R.id.cb_vibrate);
mCbBeep = (CheckBox) findViewById(R.id.cb_beep);
mCbCustomView = (CheckBox) findViewById(R.id.cb_custom_view);
mEtHintText = (EditText) findViewById(R.id.et_hint_text);
mEtHintTextSize = (EditText) findViewById(R.id.et_hint_text_size);
mEtGridlineHeight = (EditText) findViewById(R.id.et_gridline_height);
mEtGridlineNum = (EditText) findViewById(R.id.et_gridline_num);
mBtnColorPickerText = (TextView) findViewById(R.id.btn_color_picker_text);
mBtnColorPickerText.setOnClickListener(this);
mBtnColorPickerLine = (TextView) findViewById(R.id.btn_color_picker_line);
mBtnColorPickerLine.setOnClickListener(this);
mBtnColorPickerBg = (TextView) findViewById(R.id.btn_color_picker_bg);
mBtnColorPickerBg.setOnClickListener(this);
mRbScanlineLine = (RadioButton) findViewById(R.id.rb_scanline_line);
mRbScanlineGrid = (RadioButton) findViewById(R.id.rb_scanline_grid);
mCbSupportZoom = (CheckBox) findViewById(R.id.cb_support_zoom);
mCbStatusDark = (CheckBox) findViewById(R.id.cb_status_dark);
mBtnColorStatusbarBg = (TextView) findViewById(R.id.btn_color_statusbar_bg);
mBtnColorStatusbarBg.setOnClickListener(this);
mTvFrameSize = (TextView) findViewById(R.id.tv_frameSize);
mSbarFrameSize = (SeekBar) findViewById(R.id.sbar_frameSize);
mSbarFrameSize.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
if (mSbarFrameSize.getProgress() < 50) {
mSbarFrameSize.setProgress(50);
}
if (mSbarFrameSize.getProgress() > 90) {
mSbarFrameSize.setProgress(90);
}
mTvFrameSize.setText("扫描框大小比例:" + (mSbarFrameSize.getProgress() / 100f) + "\n(非全屏模式生效,范围0.5-0.9)");
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_color_picker_text:
new ColorPickerPopup.Builder(this)
.initialColor(Color.parseColor(colorText))
.enableBrightness(true)
.enableAlpha(false)
.okTitle("选择颜色")
.cancelTitle("取消")
.showIndicator(true)
.showValue(true)
.build()
.show(mBtnColorPickerText, new ColorPickerPopup.ColorPickerObserver() {
@Override
public void onColorPicked(int color) {
colorText = getHexString(color);
mBtnColorPickerText.setBackgroundColor(color);
}
});
break;
case R.id.btn_color_picker_line:
new ColorPickerPopup.Builder(this)
.initialColor(Color.parseColor(colorLine))
.enableBrightness(true)
.enableAlpha(false)
.okTitle("选择颜色")
.cancelTitle("取消")
.showIndicator(true)
.showValue(true)
.build()
.show(mBtnColorPickerLine, new ColorPickerPopup.ColorPickerObserver() {
@Override
public void onColorPicked(int color) {
colorLine = getHexString(color);
mBtnColorPickerLine.setBackgroundColor(color);
}
});
break;
case R.id.btn_color_picker_bg:
new ColorPickerPopup.Builder(this)
.initialColor(Color.parseColor(colorBackground))
.enableBrightness(true)
.enableAlpha(true)
.okTitle("选择颜色")
.cancelTitle("取消")
.showIndicator(true)
.showValue(true)
.build()
.show(mBtnColorPickerBg, new ColorPickerPopup.ColorPickerObserver() {
@Override
public void onColorPicked(int color) {
colorBackground = getHexString(color);
mBtnColorPickerBg.setBackgroundColor(color);
}
});
break;
case R.id.btn_color_statusbar_bg:
new ColorPickerPopup.Builder(this)
.initialColor(Color.parseColor(colorStatusBar))
.enableBrightness(true)
.enableAlpha(true)
.okTitle("选择颜色")
.cancelTitle("取消")
.showIndicator(true)
.showValue(true)
.build()
.show(mBtnColorStatusbarBg, new ColorPickerPopup.ColorPickerObserver() {
@Override
public void onColorPicked(int color) {
colorStatusBar = getHexString(color);
mBtnColorStatusbarBg.setBackgroundColor(color);
}
});
break;
default:
break;
}
}
private String getHexString(int color) {
String format = String.format("#%X", color);
Log.e("=====", "format:" + format);
if ("#0".equals(format)) {
format = "#00000000";
Log.e("=====", "format:" + format);
}
return format;
}
public void scanCode(View view) {
//需要判断有没有权限
MNScanConfig scanConfig = new MNScanConfig.Builder()
//设置完成震动
.isShowVibrate(mCbVibrate.isChecked())
//扫描完成声音
.isShowBeep(mCbBeep.isChecked())
//显示相册功能
.isShowPhotoAlbum(mCbPhoto.isChecked())
//显示闪光灯
.isShowLightController(mCbLight.isChecked())
//打开扫描页面的动画
.setActivityOpenAnime(R.anim.activity_anmie_in)
//退出扫描页面动画
.setActivityExitAnime(R.anim.activity_anmie_out)
//自定义文案
.setScanHintText(mEtHintText.getText().toString())
.setScanHintTextColor(colorText)
.setScanHintTextSize(TextUtils.isEmpty(mEtHintTextSize.getText().toString()) ? 14 : Integer.parseInt(mEtHintTextSize.getText().toString()))
//扫描线的颜色
.setScanColor(colorLine)
//是否支持手势缩放
.setSupportZoom(mCbSupportZoom.isChecked())
//扫描线样式
.setLaserStyle(mRbScanlineGrid.isChecked() ? MNScanConfig.LaserStyle.Grid : MNScanConfig.LaserStyle.Line)
//背景颜色
.setBgColor(colorBackground)
//网格扫描线的列数
.setGridScanLineColumn(TextUtils.isEmpty(mEtGridlineNum.getText().toString()) ? 30 : Integer.parseInt(mEtGridlineNum.getText().toString()))
//网格高度
.setGridScanLineHeight(TextUtils.isEmpty(mEtGridlineHeight.getText().toString()) ? 0 : Integer.parseInt(mEtGridlineHeight.getText().toString()))
//是否全屏扫描,默认全屏
.setFullScreenScan(mCbFullscreenScan.isChecked())
//单位dp
.setResultPointConfigs(36, 12, 3, colorResultPointStroke, colorResultPoint)
//状态栏设置
.setStatusBarConfigs(colorStatusBar, mCbStatusDark.isChecked())
//扫描框宽度大小比例,非全屏模式下生效,默认0.7,范围0.5-0.9
.setScanFrameSizeScale(mSbarFrameSize.getProgress() / 100f)
//自定义遮罩
.setCustomShadeViewLayoutID(mCbCustomView.isChecked() ? R.layout.layout_custom_view : 0, new MNCustomViewBindCallback() {
@Override
public void onBindView(View customView) {
if (customView == null) {
return;
}
ImageView iv_back = customView.findViewById(R.id.iv_back);
ImageView iv_photo = customView.findViewById(R.id.iv_photo);
LinearLayout btn_scan_light = customView.findViewById(R.id.btn_scan_light);
final ImageView iv_scan_light = customView.findViewById(R.id.iv_scan_light);
final TextView tv_scan_light = customView.findViewById(R.id.tv_scan_light);
LinearLayout btn_my_card = customView.findViewById(R.id.btn_my_card);
LinearLayout btn_scan_record = customView.findViewById(R.id.btn_scan_record);
iv_back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//关闭扫描页面
MNScanManager.closeScanPage();
}
});
btn_scan_light.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//手电筒
if (MNScanManager.isLightOn()) {
MNScanManager.closeScanLight();
iv_scan_light.setImageResource(R.drawable.icon_custom_light_close);
tv_scan_light.setText("开启手电筒");
} else {
MNScanManager.openScanLight();
iv_scan_light.setImageResource(R.drawable.icon_custom_light_open);
tv_scan_light.setText("关闭手电筒");
}
}
});
iv_photo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//打开相册扫描
MNScanManager.openAlbumPage();
}
});
btn_my_card.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//我的名片
showToast("我的名片");
}
});
btn_scan_record.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//扫码记录
showToast("扫码记录");
}
});
}
})
.builder();
MNScanManager.startScan(this, scanConfig, new MNScanCallback() {
@Override
public void onActivityResult(int resultCode, Intent data) {
handlerResult(resultCode, data);
}
});
}
private void showToast(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
private void handlerResult(int resultCode, Intent data) {
switch (resultCode) {
case MNScanManager.RESULT_SUCCESS:
ArrayList<String> results = data.getStringArrayListExtra(MNScanManager.INTENT_KEY_RESULT_SUCCESS);
StringBuilder resultStr = new StringBuilder();
for (int i = 0; i < results.size(); i++) {
resultStr.append("第" + (i + 1) + "条:");
resultStr.append(results.get(i));
resultStr.append("\n");
}
showToast(resultStr.toString());
break;
case MNScanManager.RESULT_FAIL:
String resultError = data.getStringExtra(MNScanManager.INTENT_KEY_RESULT_ERROR);
showToast(resultError);
break;
case MNScanManager.RESULT_CANCLE:
showToast("取消扫码");
break;
}
}
}
================================================
FILE: app/src/main/java/com/maning/mlkitscanner/demo/MainActivity.java
================================================
package com.maning.mlkitscanner.demo;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.maning.mlkitscanner.scan.MNScanManager;
import com.maning.mlkitscanner.scan.callback.act.MNScanCallback;
import com.maning.mlkitscanner.scan.utils.ZXingUtils;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button btnScanDefault;
private Button btnScanCustom;
private TextView tvResults;
private ImageView imageView;
private EditText editText;
private CheckBox checkbox;
private CheckBox checkbox2;
private Spinner mSpColorBlack;
private Spinner mSpColorWhite;
private Spinner mSpMargin;
private String error_correction_level;
private int margin = 0;
private int color_black = Color.BLACK;
private int color_white = Color.WHITE;
private Spinner mSpErrorCorrectionLevel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
requestCameraPerm();
}
private void initView() {
btnScanDefault = (Button) findViewById(R.id.btn_scan_default);
btnScanCustom = (Button) findViewById(R.id.btn_scan_custom);
btnScanDefault.setOnClickListener(this);
btnScanCustom.setOnClickListener(this);
tvResults = (TextView) findViewById(R.id.tv_results);
imageView = (ImageView) findViewById(R.id.imageView);
editText = (EditText) findViewById(R.id.editText);
checkbox = (CheckBox) findViewById(R.id.checkbox);
checkbox2 = (CheckBox) findViewById(R.id.checkbox2);
mSpColorBlack = (Spinner) findViewById(R.id.sp_color_black);
mSpColorWhite = (Spinner) findViewById(R.id.sp_color_white);
mSpMargin = (Spinner) findViewById(R.id.sp_margin);
mSpMargin.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
margin = Integer.parseInt(getResources().getStringArray(R.array.spinarr_margin)[position]);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
mSpColorBlack.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String str_color_black = getResources().getStringArray(R.array.spinarr_color_black)[position];
if (str_color_black.equals("黑色")) {
color_black = Color.BLACK;
} else if (str_color_black.equals("白色")) {
color_black = Color.WHITE;
} else if (str_color_black.equals("蓝色")) {
color_black = Color.BLUE;
} else if (str_color_black.equals("绿色")) {
color_black = Color.GREEN;
} else if (str_color_black.equals("黄色")) {
color_black = Color.YELLOW;
} else if (str_color_black.equals("红色")) {
color_black = Color.RED;
} else {
color_black = Color.BLACK;
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
mSpColorWhite.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String str_color_white = getResources().getStringArray(R.array.spinarr_color_white)[position];
if (str_color_white.equals("黑色")) {
color_white = Color.BLACK;
} else if (str_color_white.equals("白色")) {
color_white = Color.WHITE;
} else if (str_color_white.equals("蓝色")) {
color_white = Color.BLUE;
} else if (str_color_white.equals("绿色")) {
color_white = Color.GREEN;
} else if (str_color_white.equals("黄色")) {
color_white = Color.YELLOW;
} else if (str_color_white.equals("红色")) {
color_white = Color.RED;
} else {
color_white = Color.WHITE;
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
mSpErrorCorrectionLevel = (Spinner) findViewById(R.id.sp_error_correction_level);
mSpErrorCorrectionLevel.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
error_correction_level = getResources().getStringArray(R.array.spinarr_error_correction)[position];
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
public void requestCameraPerm() {
//判断权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.CAMERA}, 10010);
}
}
}
@Override
public void onClick(View view) {
if (view.getId() == R.id.btn_scan_default) {
MNScanManager.startScan(this, new MNScanCallback() {
@Override
public void onActivityResult(int resultCode, Intent data) {
handlerResult(resultCode, data);
}
});
}else if (view.getId() == R.id.btn_scan_custom) {
//跳转到自定义界面
startActivity(new Intent(this, CustomConfigActivity.class));
}
}
private void handlerResult(int resultCode, Intent data) {
if (data == null) {
return;
}
switch (resultCode) {
default:
break;
case MNScanManager.RESULT_SUCCESS:
ArrayList<String> results = data.getStringArrayListExtra(MNScanManager.INTENT_KEY_RESULT_SUCCESS);
StringBuilder resultStr = new StringBuilder();
for (int i = 0; i < results.size(); i++) {
resultStr.append("第" + (i + 1) + "条:");
resultStr.append(results.get(i));
resultStr.append("\n");
}
tvResults.setText(resultStr.toString());
break;
case MNScanManager.RESULT_FAIL:
String resultError = data.getStringExtra(MNScanManager.INTENT_KEY_RESULT_ERROR);
showToast(resultError);
break;
case MNScanManager.RESULT_CANCLE:
showToast("取消扫码");
break;
}
}
private void showToast(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
public void createQRImage(View view) {
String str = editText.getText().toString();
if (TextUtils.isEmpty(str)) {
Toast.makeText(this, "字符串不能为空", Toast.LENGTH_SHORT).show();
return;
}
Bitmap qrImage;
Bitmap logo = null;
Bitmap foreground_bitmap = null;
if (checkbox.isChecked()) {
logo = BitmapFactory.decodeResource(getResources(), R.drawable.ic_wx);
}
if (checkbox2.isChecked()) {
foreground_bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.tmp);
}
qrImage = ZXingUtils.createQRCodeImage(str, 500, margin, color_black, color_white, error_correction_level, logo, foreground_bitmap);
if (qrImage != null) {
imageView.setImageBitmap(qrImage);
} else {
Toast.makeText(this, "生成失败", Toast.LENGTH_SHORT).show();
}
}
}
================================================
FILE: app/src/main/res/anim/activity_anmie_in.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator">
<scale
android:duration="200"
android:fromXScale="0.1"
android:fromYScale="0.1"
android:pivotX="50%p"
android:pivotY="50%p"
android:toXScale="1.0"
android:toYScale="1.0" />
<alpha
android:duration="200"
android:fromAlpha="0.1"
android:toAlpha="1.0" />
</set>
================================================
FILE: app/src/main/res/anim/activity_anmie_out.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator">
<scale
android:duration="200"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:pivotX="50%p"
android:pivotY="50%p"
android:toXScale="0.1"
android:toYScale="0.1" />
<alpha
android:duration="200"
android:fromAlpha="1.0"
android:toAlpha="0.1" />
</set>
================================================
FILE: app/src/main/res/drawable/ic_launcher_background.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>
================================================
FILE: app/src/main/res/drawable-v24/ic_launcher_foreground.xml
================================================
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>
================================================
FILE: app/src/main/res/layout/activity_custom_config.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="vertical"
android:padding="10dp">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:onClick="scanCode"
android:text="自定义扫描"
android:textColor="#FFFFFF" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="10dp"
android:layout_marginBottom="10dp"
android:background="@color/colorAccent" />
<CheckBox
android:id="@+id/cb_photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="是否显示相册功能" />
<CheckBox
android:id="@+id/cb_light"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="是否显示闪光灯" />
<CheckBox
android:id="@+id/cb_support_zoom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="是否支持手势缩放" />
<CheckBox
android:id="@+id/cb_fullscreen_scan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"
android:text="是否需要全屏扫描识别(默认)" />
<CheckBox
android:id="@+id/cb_vibrate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="是否开启扫描完成震动提醒" />
<CheckBox
android:id="@+id/cb_beep"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="是否开启扫描完成声音提醒" />
<CheckBox
android:id="@+id/cb_custom_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="是否完全自定义遮罩层" />
<CheckBox
android:id="@+id/cb_status_dark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"
android:text="是否状态栏黑色字体" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/et_hint_text"
android:layout_width="0dp"
android:layout_height="44dp"
android:layout_weight="4"
android:hint="输入自定义提示文案"
android:textSize="14sp" />
<EditText
android:id="@+id/et_hint_text_size"
android:layout_width="0dp"
android:layout_height="44dp"
android:layout_marginLeft="10dp"
android:layout_weight="2"
android:hint="文字大小(sp)"
android:inputType="number"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal">
<EditText
android:id="@+id/et_gridline_height"
android:layout_width="0dp"
android:layout_height="44dp"
android:layout_weight="2"
android:hint="网格扫描高度"
android:inputType="number"
android:textSize="14sp" />
<EditText
android:id="@+id/et_gridline_num"
android:layout_width="0dp"
android:layout_height="44dp"
android:layout_marginLeft="10dp"
android:layout_weight="2"
android:hint="网格扫描列数"
android:inputType="number"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="提示文字的颜色:"
android:textSize="14sp" />
<TextView
android:id="@+id/btn_color_picker_text"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:background="#22CE6B" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="扫描线的颜色:"
android:textSize="14sp" />
<TextView
android:id="@+id/btn_color_picker_line"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:background="#22CE6B" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="遮罩背景颜色(非全屏模式下生效):"
android:textSize="14sp" />
<TextView
android:id="@+id/btn_color_picker_bg"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:background="#33FF0000" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="状态栏颜色:"
android:textSize="14sp" />
<TextView
android:id="@+id/btn_color_statusbar_bg"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:background="#00000000" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="扫描线样式:"
android:textSize="14sp" />
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rb_scanline_line"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="20dp"
android:text="线性" />
<RadioButton
android:id="@+id/rb_scanline_grid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="网格" />
</RadioGroup>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/tv_frameSize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="扫描框大小比例:0.7\n(非全屏模式生效,范围0.5-0.9)"
android:textSize="14sp" />
<SeekBar
android:id="@+id/sbar_frameSize"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:max="100"
android:progress="70" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="10dp"
android:layout_marginTop="10dp"
android:background="@color/colorAccent" />
</LinearLayout>
</LinearLayout>
</ScrollView>
================================================
FILE: app/src/main/res/layout/activity_main.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">
<Button
android:id="@+id/btn_scan_default"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:background="@color/colorPrimary"
android:text="默认扫描"
android:textColor="#FFFFFF" />
<Button
android:id="@+id/btn_scan_custom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:text="自定义扫描"
android:textColor="#FFFFFF" />
<TextView
android:id="@+id/tv_results"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="扫描结果显示..."
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="@color/colorPrimary"
android:onClick="createQRImage"
android:text="生成二维码"
android:textColor="#FFFFFF" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="50dp"
android:hint="输入要生成二维码的文本"
android:textSize="15sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<CheckBox
android:id="@+id/checkbox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="中间Logo" />
<CheckBox
android:id="@+id/checkbox2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="图片替代二维码(不建议,太花识别率可能比较低)" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:text="前景色:" />
<Spinner
android:id="@+id/sp_color_black"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:entries="@array/spinarr_color_black" />
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:text="背景色:" />
<Spinner
android:id="@+id/sp_color_white"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:entries="@array/spinarr_color_white" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:text="边距:" />
<Spinner
android:id="@+id/sp_margin"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:entries="@array/spinarr_margin" />
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:gravity="center_vertical"
android:text="容错率:" />
<Spinner
android:id="@+id/sp_error_correction_level"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:entries="@array/spinarr_error_correction" />
</LinearLayout>
<ImageView
android:id="@+id/imageView"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center_horizontal"
android:scaleType="fitXY"
android:src="@mipmap/ic_launcher" />
</LinearLayout>
</ScrollView>
================================================
FILE: app/src/main/res/layout/layout_custom_view.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:background="#000000">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp">
<ImageView
android:id="@+id/iv_back"
android:layout_width="50dp"
android:layout_height="50dp"
android:padding="15dp"
android:src="@drawable/icon_custom_back" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="扫一扫"
android:textColor="#FFFFFF"
android:textSize="18sp"
android:textStyle="bold" />
<ImageView
android:id="@+id/iv_photo"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"
android:padding="12dp"
android:src="@drawable/icon_custom_photo" />
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:gravity="center"
android:paddingTop="12dp"
android:paddingBottom="16dp">
<LinearLayout
android:id="@+id/btn_scan_light"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/iv_scan_light"
android:layout_width="50dp"
android:layout_height="50dp"
android:padding="12dp"
android:src="@drawable/icon_custom_light_close" />
<TextView
android:id="@+id/tv_scan_light"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="打开手电筒"
android:textColor="#FFFFFF"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/btn_my_card"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:padding="10dp"
android:src="@drawable/icon_custom_my_card" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我的名片"
android:textColor="#FFFFFF"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/btn_scan_record"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:padding="12dp"
android:src="@drawable/icon_custom_record" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="扫码记录"
android:textColor="#FFFFFF"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
================================================
FILE: app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
================================================
FILE: app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
================================================
FILE: app/src/main/res/values/array.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="spinarr_error_correction">
<item>L </item>
<item>M </item>
<item>Q</item>
<item>H</item>
</string-array>
<string-array name="spinarr_margin">
<item>0</item>
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
</string-array>
<string-array name="spinarr_color_black">
<item>黑色</item>
<item>白色</item>
<item>蓝色</item>
<item>绿色</item>
<item>黄色</item>
<item>红色</item>
</string-array>
<string-array name="spinarr_color_white">
<item>白色</item>
<item>黑色</item>
<item>蓝色</item>
<item>绿色</item>
<item>黄色</item>
<item>红色</item>
</string-array>
</resources>
================================================
FILE: app/src/main/res/values/colors.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#6200EE</color>
<color name="colorPrimaryDark">#3700B3</color>
<color name="colorAccent">#03DAC5</color>
</resources>
================================================
FILE: app/src/main/res/values/strings.xml
================================================
<resources>
<string name="app_name">MLKit扫码</string>
</resources>
================================================
FILE: app/src/main/res/values/styles.xml
================================================
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>
================================================
FILE: app/src/test/java/com/maning/mlkitscanner/ExampleUnitTest.java
================================================
package com.maning.mlkitscanner;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}
================================================
FILE: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.
apply from: "config.gradle"
buildscript {
repositories {
google()
jcenter()
maven { url 'https://jitpack.io' }
}
dependencies {
classpath "com.android.tools.build:gradle:4.0.0"
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0'
}
}
allprojects {
repositories {
google()
jcenter()
maven { url 'https://jitpack.io' }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
================================================
FILE: config.gradle
================================================
/**
* 全局统一配置
*/
ext {
/**
* 版本统一管理
*/
versions = [
versionCode : 101, //版本号
versionName : "1.0.1", //版本名称
compileSdkVersion: 29,
minSdkVersion : 21,
targetSdkVersion : 28,
]
appId = [
"app": "com.maning.mlkitscanner.demo",
]
dependenciesGoogle = [
annotation : 'androidx.annotation:annotation:1.1.0',
supportv4 : 'androidx.legacy:legacy-support-v4:1.0.0',
appcompat : 'androidx.appcompat:appcompat:1.2.0',
design : 'com.google.android.material:material:1.0.0',
recyclerView : 'androidx.recyclerview:recyclerview:1.0.0',
constraintlayout: 'androidx.constraintlayout:constraintlayout:1.1.3',
multidex : 'androidx.multidex:multidex:2.0.0',
]
dependenciesOther = [
//颜色选择器
"colorpicker": 'com.github.duanhong169:colorpicker:1.1.6',
"xpopup" : 'com.lxj:xpopup:2.2.19'
]
dependenciesDebug = [
"leakcanary": "com.squareup.leakcanary:leakcanary-android:2.5",
]
}
================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Fri Aug 20 09:04:58 CST 2021
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
================================================
FILE: gradle.properties
================================================
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app"s APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
================================================
FILE: gradlew
================================================
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: mlkit-scanner/.gitignore
================================================
/build
================================================
FILE: mlkit-scanner/build.gradle
================================================
apply plugin: 'com.android.library'
def versions = rootProject.ext.versions
android {
compileSdkVersion versions.compileSdkVersion
defaultConfig {
minSdkVersion versions.minSdkVersion
targetSdkVersion versions.targetSdkVersion
versionCode versions.versionCode
versionName versions.versionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
compileOnly 'androidx.appcompat:appcompat:1.1.0'
compileOnly 'com.google.mlkit:barcode-scanning:17.0.2'
compileOnly "androidx.camera:camera-core:1.0.2"
compileOnly "androidx.camera:camera-camera2:1.0.2"
compileOnly "androidx.camera:camera-lifecycle:1.0.2"
compileOnly "androidx.camera:camera-view:1.0.0-alpha25"
compileOnly 'com.google.zxing:core:3.3.3'
}
================================================
FILE: mlkit-scanner/consumer-rules.pro
================================================
================================================
FILE: mlkit-scanner/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
================================================
FILE: mlkit-scanner/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.maning.mlkitscanner">
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera.any" />
<uses-feature
android:name="android.hardware.camera.autofocus"
android:required="false" />
<uses-feature
android:name="android.hardware.camera.flash"
android:required="false" />
<application
android:allowBackup="true"
android:supportsRtl="true">
<activity
android:name=".scan.ui.ScanPreviewActivity"
android:screenOrientation="portrait"
android:theme="@style/MNScanCaptureTheme" />
</application>
</manifest>
================================================
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/MNScanManager.java
================================================
package com.maning.mlkitscanner.scan;
import android.app.Activity;
import android.content.Intent;
import com.maning.mlkitscanner.scan.callback.act.ActResultRequest;
import com.maning.mlkitscanner.scan.callback.act.MNScanCallback;
import com.maning.mlkitscanner.scan.model.MNScanConfig;
import com.maning.mlkitscanner.scan.ui.ScanPreviewActivity;
/**
* Created by maning on 2017/12/7.
* 启动扫描的主类
*/
public class MNScanManager {
//常量
public static final int RESULT_SUCCESS = 0;
public static final int RESULT_FAIL = 1;
public static final int RESULT_CANCLE = 2;
public static final String INTENT_KEY_RESULT_SUCCESS = "INTENT_KEY_RESULT_SUCCESS";
public static final String INTENT_KEY_RESULT_ERROR = "INTENT_KEY_RESULT_ERROR";
//是否是调试模式
public static final boolean isDebugMode = false;
//跳转传入的数据
public static final String INTENT_KEY_CONFIG_MODEL = "INTENT_KEY_CONFIG_MODEL";
public static void startScan(Activity activity, MNScanCallback scanCallback) {
startScan(activity, null, scanCallback);
}
public static void startScan(Activity activity, MNScanConfig mnScanConfig, MNScanCallback scanCallback) {
if (mnScanConfig == null) {
mnScanConfig = new MNScanConfig.Builder().builder();
}
Intent intent = new Intent(activity.getApplicationContext(), ScanPreviewActivity.class);
//传递数据
intent.putExtra(MNScanManager.INTENT_KEY_CONFIG_MODEL, mnScanConfig);
ActResultRequest actResultRequest = new ActResultRequest(activity);
actResultRequest.startForResult(intent, scanCallback);
activity.overridePendingTransition(mnScanConfig.getActivityOpenAnime(), android.R.anim.fade_out);
}
/**
* 关闭当前页面
*/
public static void closeScanPage() {
ScanPreviewActivity.closeScanPage();
}
/**
* 打开相册扫描图片
*/
public static void openAlbumPage() {
ScanPreviewActivity.openAlbumPage();
}
/**
* 打开手电筒
*/
public static void openScanLight() {
ScanPreviewActivity.openScanLight();
}
/**
* 关闭手电筒
*/
public static void closeScanLight() {
ScanPreviewActivity.closeScanLight();
}
/**
* 手电筒是否开启
*/
public static boolean isLightOn() {
return ScanPreviewActivity.isLightOn();
}
}
================================================
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/analyser/BarcodeAnalyser.java
================================================
package com.maning.mlkitscanner.scan.analyser;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.ImageProxy;
import androidx.camera.view.PreviewView;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.mlkit.vision.barcode.BarcodeScanner;
import com.google.mlkit.vision.barcode.BarcodeScannerOptions;
import com.google.mlkit.vision.barcode.BarcodeScanning;
import com.google.mlkit.vision.barcode.common.Barcode;
import com.google.mlkit.vision.common.InputImage;
import com.maning.mlkitscanner.scan.callback.OnCameraAnalyserCallback;
import com.maning.mlkitscanner.scan.utils.ImageUtils;
import java.util.List;
/**
* @author : maning
* @date : 8/18/21
* @desc :
*/
public class BarcodeAnalyser implements ImageAnalysis.Analyzer {
private OnCameraAnalyserCallback onCameraAnalyserCallback;
private final BarcodeScanner barcodeScanner;
/**
* 是否分析
*/
private volatile boolean isAnalyze = true;
private Context context;
private PreviewView mPreviewView;
public BarcodeScanner getBarcodeScanner() {
return barcodeScanner;
}
public void setAnalyze(boolean analyze) {
isAnalyze = analyze;
}
public void setOnCameraAnalyserCallback(OnCameraAnalyserCallback onCameraAnalyserCallback) {
this.onCameraAnalyserCallback = onCameraAnalyserCallback;
}
public BarcodeAnalyser() {
BarcodeScannerOptions options = new BarcodeScannerOptions.Builder()
.setBarcodeFormats(Barcode.FORMAT_ALL_FORMATS)
.build();
barcodeScanner = BarcodeScanning.getClient(options);
}
public void setPreviewView(PreviewView mPreviewView) {
this.mPreviewView = mPreviewView;
}
private Bitmap cropBitmap(Bitmap bitmap, int cropWidth, int cropHeight) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
return Bitmap.createBitmap(bitmap, (w - cropWidth) / 2, (h - cropHeight) / 2, cropWidth, cropHeight, null, false);
}
@Override
public void analyze(@NonNull final ImageProxy imageProxy) {
Bitmap bitmap = null;
try {
bitmap = ImageUtils.imageProxyToBitmap(imageProxy, imageProxy.getImageInfo().getRotationDegrees());
} catch (Exception e) {
e.printStackTrace();
}
if (mPreviewView != null) {
//bitmap转为16:9
int height = mPreviewView.getHeight();
int width = mPreviewView.getWidth();
if (bitmap.getHeight() / (float) bitmap.getWidth() > mPreviewView.getHeight() / (float) mPreviewView.getWidth()) {
int newHeight = bitmap.getWidth() * height / width;
bitmap = cropBitmap(bitmap, bitmap.getWidth(), newHeight);
} else if (bitmap.getHeight() / (float) bitmap.getWidth() < mPreviewView.getHeight() / (float) mPreviewView.getWidth()) {
int newWith = bitmap.getHeight() * width / height;
bitmap = cropBitmap(bitmap, newWith, bitmap.getHeight());
}
//大小控制和预览一样
bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
}
InputImage inputImage = InputImage.fromBitmap(bitmap, 0);
//InputImage inputImage = InputImage.fromMediaImage(imageProxy.getImage(), imageProxy.getImageInfo().getRotationDegrees());
final Bitmap finalBitmap = bitmap;
barcodeScanner.process(inputImage)
.addOnSuccessListener(new OnSuccessListener<List<Barcode>>() {
@Override
public void onSuccess(@NonNull List<Barcode> barcodes) {
if (barcodes.size() == 0) {
return;
}
if (!isAnalyze) {
return;
}
isAnalyze = false;
for (Barcode barcode : barcodes) {
Log.i("======", "barcode-getDisplayValue:" + barcode.getDisplayValue());
Log.i("======", "barcode-getRawValue:" + barcode.getRawValue());
}
if (onCameraAnalyserCallback != null) {
onCameraAnalyserCallback.onSuccess(finalBitmap, barcodes);
}
}
})
.addOnCompleteListener(new OnCompleteListener<List<Barcode>>() {
@Override
public void onComplete(@NonNull Task<List<Barcode>> task) {
imageProxy.close();
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.e("======", "onFailure---:" + e.toString());
}
});
}
}
================================================
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/callback/MNCustomViewBindCallback.java
================================================
package com.maning.mlkitscanner.scan.callback;
import android.view.View;
/**
* 自定义View回调
*/
public interface MNCustomViewBindCallback {
void onBindView(View customView);
}
================================================
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/callback/OnCameraAnalyserCallback.java
================================================
package com.maning.mlkitscanner.scan.callback;
import android.graphics.Bitmap;
import com.google.mlkit.vision.barcode.common.Barcode;
import java.util.List;
/**
* @author : maning
* @date : 8/19/21
* @desc : 扫码分析结果回调
*/
public interface OnCameraAnalyserCallback {
void onSuccess(Bitmap bitmap, List<Barcode> barcodes);
}
================================================
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/callback/act/ActResultRequest.java
================================================
package com.maning.mlkitscanner.scan.callback.act;
import android.app.Activity;
import android.app.FragmentManager;
import android.content.Intent;
/**
* <pre>
* author : maning
* e-mail : xxx@xx
* time : 2018/06/04
* desc :
* version: 1.0
* </pre>
*/
public class ActResultRequest {
private OnActResultEventDispatcherFragment fragment;
public ActResultRequest(Activity activity) {
fragment = getEventDispatchFragment(activity);
}
private OnActResultEventDispatcherFragment getEventDispatchFragment(Activity activity) {
final FragmentManager fragmentManager = activity.getFragmentManager();
OnActResultEventDispatcherFragment fragment = findEventDispatchFragment(fragmentManager);
if (fragment == null) {
fragment = new OnActResultEventDispatcherFragment();
fragmentManager
.beginTransaction()
.add(fragment, OnActResultEventDispatcherFragment.TAG)
.commitAllowingStateLoss();
fragmentManager.executePendingTransactions();
}
return fragment;
}
private OnActResultEventDispatcherFragment findEventDispatchFragment(FragmentManager manager) {
return (OnActResultEventDispatcherFragment) manager.findFragmentByTag(OnActResultEventDispatcherFragment.TAG);
}
public void startForResult(Intent intent, MNScanCallback callback) {
fragment.startForResult(intent, callback);
}
}
================================================
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/callback/act/MNScanCallback.java
================================================
package com.maning.mlkitscanner.scan.callback.act;
import android.content.Intent;
/**
* <pre>
* author : maning
* e-mail : xxx@xx
* time : 2018/06/04
* desc :
* version: 1.0
* </pre>
*/
public interface MNScanCallback {
void onActivityResult(int resultCode, Intent data);
}
================================================
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/callback/act/OnActResultEventDispatcherFragment.java
================================================
package com.maning.mlkitscanner.scan.callback.act;
import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.util.SparseArray;
/**
* <pre>
* author : maning
* e-mail : xxx@xx
* time : 2018/06/04
* desc :
* version: 1.0
* </pre>
*/
public class OnActResultEventDispatcherFragment extends Fragment {
public static final String TAG = "on_act_result_event_dispatcher";
private SparseArray<MNScanCallback> mCallbacks = new SparseArray<>();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
public void startForResult(Intent intent, MNScanCallback callback) {
mCallbacks.put(callback.hashCode(), callback);
startActivityForResult(intent, callback.hashCode());
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
MNScanCallback callback = mCallbacks.get(requestCode);
mCallbacks.remove(requestCode);
if (callback != null) {
callback.onActivityResult(resultCode, data);
}
}
}
================================================
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/camera/CameraManager.java
================================================
package com.maning.mlkitscanner.scan.camera;
import android.content.Context;
import android.graphics.Bitmap;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import androidx.camera.core.Camera;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.FocusMeteringAction;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.MeteringPoint;
import androidx.camera.core.Preview;
import androidx.camera.core.ZoomState;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.view.PreviewView;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.LifecycleOwner;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.mlkit.vision.barcode.common.Barcode;
import com.maning.mlkitscanner.scan.analyser.BarcodeAnalyser;
import com.maning.mlkitscanner.scan.callback.OnCameraAnalyserCallback;
import com.maning.mlkitscanner.scan.model.MNScanConfig;
import com.maning.mlkitscanner.scan.utils.BeepManager;
import java.util.List;
import java.util.concurrent.Executors;
/**
* @author : maning
* @date : 8/19/21
* @desc :
*/
public class CameraManager {
private static final int HOVER_TAP_TIMEOUT = 150;
private static final int HOVER_TAP_SLOP = 20;
private ListenableFuture<ProcessCameraProvider> cameraProviderFuture;
private LifecycleOwner mLifecycleOwner;
private Camera mCamera;
private long mLastHoveTapTime;
private boolean isClickTap;
private float mDownX;
private float mDownY;
private PreviewView mPreviewView;
private Context mContext;
private BarcodeAnalyser barcodeAnalyser;
private OnCameraAnalyserCallback onCameraAnalyserCallback;
private MNScanConfig scanConfig;
private BeepManager beepManager;
public static CameraManager getInstance(Context mContext, PreviewView mPreviewView) {
return new CameraManager(mContext, mPreviewView);
}
public CameraManager(Context mContext, PreviewView mPreviewView) {
this.mContext = mContext;
this.mPreviewView = mPreviewView;
initDatas();
}
public BarcodeAnalyser getBarcodeAnalyser() {
return barcodeAnalyser;
}
public void setOnCameraAnalyserCallback(OnCameraAnalyserCallback callback) {
this.onCameraAnalyserCallback = callback;
}
public void setScanConfig(MNScanConfig config) {
scanConfig = config;
beepManager.setPlayBeep(scanConfig.isShowBeep());
beepManager.setVibrate(scanConfig.isShowVibrate());
}
public void setAnalyze(boolean analyze) {
barcodeAnalyser.setAnalyze(analyze);
}
private void initDatas() {
mLifecycleOwner = (LifecycleOwner) mContext;
beepManager = new BeepManager(mContext);
initBarcodeAnalyser();
initScaleGesture();
}
public void startCamera() {
cameraProviderFuture = ProcessCameraProvider.getInstance(mContext);
cameraProviderFuture.addListener(new Runnable() {
@Override
public void run() {
try {
ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
Preview preview = new Preview.Builder().build();
//绑定预览
preview.setSurfaceProvider(mPreviewView.getSurfaceProvider());
//使用后置相机
CameraSelector cameraSelector = new CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build();
//配置图片扫描
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder()
.setTargetResolution(CameraSizeUtils.getSize(mContext))
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build();
imageAnalysis.setAnalyzer(Executors.newSingleThreadExecutor(), barcodeAnalyser);
if (mCamera != null) {
cameraProviderFuture.get().unbindAll();
}
//将相机绑定到当前控件的生命周期
mCamera = cameraProvider.bindToLifecycle(mLifecycleOwner, cameraSelector, imageAnalysis, preview);
} catch (Exception e) {
}
}
}, ContextCompat.getMainExecutor(mContext));
}
private void initBarcodeAnalyser() {
barcodeAnalyser = new BarcodeAnalyser();
barcodeAnalyser.setPreviewView(mPreviewView);
barcodeAnalyser.setAnalyze(true);
barcodeAnalyser.setOnCameraAnalyserCallback(new OnCameraAnalyserCallback() {
@Override
public void onSuccess(Bitmap bitmap, List<Barcode> barcodes) {
beepManager.playBeepSoundAndVibrate();
if (onCameraAnalyserCallback != null) {
onCameraAnalyserCallback.onSuccess(bitmap, barcodes);
}
}
});
}
private void initScaleGesture() {
ScaleGestureDetector scaleGestureDetector = new ScaleGestureDetector(mContext, mOnScaleGestureListener);
mPreviewView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
handlePreviewViewClickTap(event);
if (scanConfig != null && scanConfig.isSupportZoom()) {
return scaleGestureDetector.onTouchEvent(event);
}
return false;
}
});
}
private ScaleGestureDetector.OnScaleGestureListener mOnScaleGestureListener = new ScaleGestureDetector.SimpleOnScaleGestureListener() {
@Override
public boolean onScale(ScaleGestureDetector detector) {
float scale = detector.getScaleFactor();
if (mCamera != null) {
float ratio = mCamera.getCameraInfo().getZoomState().getValue().getZoomRatio();
zoomTo(ratio * scale);
}
return true;
}
};
private void handlePreviewViewClickTap(MotionEvent event) {
if (event.getPointerCount() == 1) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isClickTap = true;
mDownX = event.getX();
mDownY = event.getY();
mLastHoveTapTime = System.currentTimeMillis();
break;
case MotionEvent.ACTION_MOVE:
isClickTap = distance(mDownX, mDownY, event.getX(), event.getY()) < HOVER_TAP_SLOP;
break;
case MotionEvent.ACTION_UP:
if (isClickTap && mLastHoveTapTime + HOVER_TAP_TIMEOUT > System.currentTimeMillis()) {
startFocusAndMetering(event.getX(), event.getY());
}
break;
}
}
}
private float distance(float aX, float aY, float bX, float bY) {
float xDiff = aX - bX;
float yDiff = aY - bY;
return (float) Math.sqrt(xDiff * xDiff + yDiff * yDiff);
}
public void zoomTo(float ratio) {
if (mCamera != null) {
ZoomState zoomState = mCamera.getCameraInfo().getZoomState().getValue();
float maxRatio = zoomState.getMaxZoomRatio();
float minRatio = zoomState.getMinZoomRatio();
float zoom = Math.max(Math.min(ratio, maxRatio), minRatio);
mCamera.getCameraControl().setZoomRatio(zoom);
}
}
private void startFocusAndMetering(float x, float y) {
if (mCamera != null) {
MeteringPoint point = mPreviewView.getMeteringPointFactory().createPoint(x, y);
mCamera.getCameraControl().startFocusAndMetering(new FocusMeteringAction.Builder(point).build());
}
}
public void openLight() {
if (mCamera != null) {
mCamera.getCameraControl().enableTorch(true);
}
}
public void closeLight() {
if (mCamera != null) {
mCamera.getCameraControl().enableTorch(false);
}
}
public void stopCamera() {
try {
if (cameraProviderFuture != null) {
cameraProviderFuture.get().unbindAll();
}
} catch (Exception e) {
}
}
public void release() {
try {
mPreviewView = null;
mLifecycleOwner = null;
stopCamera();
} catch (Exception e) {
}
}
}
================================================
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/camera/CameraSizeUtils.java
================================================
package com.maning.mlkitscanner.scan.camera;
import android.content.Context;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Size;
/**
* @author : maning
* @date : 8/19/21
* @desc :
*/
public class CameraSizeUtils {
public static Size getSize(Context context) {
Size mTargetSize;
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
int width = displayMetrics.widthPixels;
int height = displayMetrics.heightPixels;
Log.i("======", String.format("displayMetrics:%d x %d", width, height));
//因为为了保持流畅性和性能,限制在1080p,在此前提下尽可能的找到屏幕接近的分辨率
if (width < height) {
int size = Math.min(width, 1080);
float ratio = width / (float) height;
if (ratio > 0.7) {//一般应用于平板
mTargetSize = new Size(size, (int) (size / 3.0f * 4.0f));
} else {
mTargetSize = new Size(size, (int) (size / 9.0f * 16.0f));
}
} else {
int size = Math.min(height, 1080);
float ratio = height / (float) width;
if (ratio > 0.7) {//一般应用于平板
mTargetSize = new Size((int) (size / 3.0f * 4.0f), size);
} else {
mTargetSize = new Size((int) (size / 9.0f * 16.0), size);
}
}
Log.i("======", "mTargetSize:" + mTargetSize.getWidth() + "," + mTargetSize.getHeight());
return mTargetSize;
}
}
================================================
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/model/MNScanConfig.java
================================================
package com.maning.mlkitscanner.scan.model;
import com.maning.mlkitscanner.R;
import com.maning.mlkitscanner.scan.callback.MNCustomViewBindCallback;
import java.io.Serializable;
/**
* Created by maning on 2017/12/7.
* 启动Activity的一些配置参数
*/
public class MNScanConfig implements Serializable {
private static final long serialVersionUID = -5260676142223049891L;
public static MNCustomViewBindCallback mCustomViewBindCallback;
//枚举类型:扫描线样式
public enum LaserStyle {
Line,
Grid,
}
//是否显示相册
private boolean showPhotoAlbum;
//扫描声音
private boolean showBeep;
//扫描震动
private boolean showVibrate;
//扫描框和扫描线的颜色
private String scanColor;
//扫描线的样式
private LaserStyle laserStyle;
//扫描提示文案
private String scanHintText;
//扫描提示文案颜色
private String scanHintTextColor;
//扫描提示文案字体大小
private int scanHintTextSize;
//开启Activity动画
private int activityOpenAnime;
//关闭Activity动画
private int activityExitAnime;
//是否支持手势缩放,默认支持
private boolean isSupportZoom = true;
//自定义View
private int customShadeViewLayoutID;
//扫描背景色
private String bgColor;
//网格扫描线的列数
private int gridScanLineColumn;
//网格扫描线的高度
private int gridScanLineHeight;
//显示闪光灯
private boolean showLightController = true;
//是否需要全屏扫描,默认全屏扫描
private boolean isFullScreenScan = true;
//扫描二维码中心点宽高
private int resultPointWithdHeight = 0;
//扫描二维码中心点显示圆角
private int resultPointCorners = 0;
//扫描二维码中心点显示描边
private int resultPointStrokeWidth = 0;
//扫描二维码中心点显示描边颜色
private String resultPointStrokeColor;
//扫描二维码中心点显示颜色
private String resultPointColor;
//状态栏颜色
private String statusBarColor = "#00000000";
//状态栏是否显示黑色字体
private boolean statusBarDarkMode = false;
//扫描框宽度大小比例,非全屏模式下生效,默认0.7,范围0.5-0.9
private float scanFrameSizeScale = 0.7f;
private MNScanConfig() {
}
private MNScanConfig(Builder builder) {
showPhotoAlbum = builder.showPhotoAlbum;
showBeep = builder.showBeep;
showVibrate = builder.showVibrate;
scanColor = builder.scanColor;
laserStyle = builder.laserStyle;
scanHintText = builder.scanHintText;
activityOpenAnime = builder.activityOpenAnime;
activityExitAnime = builder.activityExitAnime;
customShadeViewLayoutID = builder.customShadeViewLayoutID;
bgColor = builder.bgColor;
gridScanLineColumn = builder.gridScanLineColumn;
gridScanLineHeight = builder.gridScanLineHeight;
showLightController = builder.showLightController;
scanHintTextColor = builder.scanHintTextColor;
scanHintTextSize = builder.scanHintTextSize;
isFullScreenScan = builder.isFullScreenScan;
isSupportZoom = builder.isSupportZoom;
resultPointWithdHeight = builder.resultPointWithdHeight;
resultPointCorners = builder.resultPointCorners;
resultPointStrokeWidth = builder.resultPointStrokeWidth;
resultPointStrokeColor = builder.resultPointStrokeColor;
resultPointColor = builder.resultPointColor;
statusBarColor = builder.statusBarColor;
statusBarDarkMode = builder.statusBarDarkMode;
scanFrameSizeScale = builder.scanFrameSizeScale;
}
public String getStatusBarColor() {
return statusBarColor;
}
public boolean isStatusBarDarkMode() {
return statusBarDarkMode;
}
public int getResultPointWithdHeight() {
return resultPointWithdHeight;
}
public int getResultPointCorners() {
return resultPointCorners;
}
public int getResultPointStrokeWidth() {
return resultPointStrokeWidth;
}
public String getResultPointStrokeColor() {
return resultPointStrokeColor;
}
public String getResultPointColor() {
return resultPointColor;
}
public boolean isShowPhotoAlbum() {
return showPhotoAlbum;
}
public boolean isShowBeep() {
return showBeep;
}
public boolean isShowVibrate() {
return showVibrate;
}
public String getScanColor() {
return scanColor;
}
public LaserStyle getLaserStyle() {
return laserStyle;
}
public String getScanHintText() {
return scanHintText;
}
public String getScanHintTextColor() {
return scanHintTextColor;
}
public int getScanHintTextSize() {
return scanHintTextSize;
}
public int getActivityOpenAnime() {
return activityOpenAnime;
}
public int getActivityExitAnime() {
return activityExitAnime;
}
public int getCustomShadeViewLayoutID() {
return customShadeViewLayoutID;
}
public String getBgColor() {
return bgColor;
}
public int getGridScanLineColumn() {
return gridScanLineColumn;
}
public int getGridScanLineHeight() {
return gridScanLineHeight;
}
public boolean isShowLightController() {
return showLightController;
}
public boolean isFullScreenScan() {
return isFullScreenScan;
}
public boolean isSupportZoom() {
return isSupportZoom;
}
public float getScanFrameSizeScale() {
if (scanFrameSizeScale > 0.9) {
scanFrameSizeScale = 0.9f;
}
if (scanFrameSizeScale < 0.5) {
scanFrameSizeScale = 0.5f;
}
return scanFrameSizeScale;
}
public static class Builder {
private boolean showPhotoAlbum = true;
private boolean showBeep = true;
private boolean showVibrate = true;
//扫描颜色
private String scanColor;
private String bgColor;
private LaserStyle laserStyle = LaserStyle.Line;
private int activityOpenAnime = R.anim.mn_scan_activity_bottom_in;
private int activityExitAnime = R.anim.mn_scan_activity_bottom_out;
private int customShadeViewLayoutID;
//网格扫描线的列数
private int gridScanLineColumn;
//网格扫描线的高度
private int gridScanLineHeight;
//闪光灯
private boolean showLightController = true;
//扫描提示文案
private String scanHintText = "扫二维码/条形码";
//扫描提示文案颜色
private String scanHintTextColor;
//扫描提示文案字体大小
private int scanHintTextSize;
//是否需要全屏扫描,默认值扫描扫描框中的二维码
private boolean isFullScreenScan = true;
//是否支持手势缩放,默认支持
private boolean isSupportZoom = true;
//扫描二维码中心点显示半径
private int resultPointWithdHeight = 0;
//扫描二维码中心点显示圆角
private int resultPointCorners = 0;
//扫描二维码中心点显示描边
private int resultPointStrokeWidth = 0;
//扫描二维码中心点显示描边颜色
private String resultPointStrokeColor;
//扫描二维码中心点显示颜色
private String resultPointColor;
//状态栏颜色
private String statusBarColor = "#00000000";
//状态栏是否显示黑色字体
private boolean statusBarDarkMode = false;
//扫描框宽度大小比例,非全屏模式下生效,默认0.7,范围0.5-0.9
private float scanFrameSizeScale = 0.7f;
public MNScanConfig builder() {
return new MNScanConfig(this);
}
public Builder setStatusBarConfigs(String statusBarColor,
boolean statusBarDarkMode) {
this.statusBarColor = statusBarColor;
this.statusBarDarkMode = statusBarDarkMode;
return this;
}
/**
* 设置扫描点大小圆角等(单位dp)
*
* @param resultPointWithdHeight
* @param resultPointCorners
* @param resultPointStrokeWidth
* @param resultPointStrokeColor
* @param resultPointColor
* @return
*/
public Builder setResultPointConfigs(int resultPointWithdHeight,
int resultPointCorners,
int resultPointStrokeWidth,
String resultPointStrokeColor,
String resultPointColor) {
this.resultPointWithdHeight = resultPointWithdHeight;
this.resultPointCorners = resultPointCorners;
this.resultPointStrokeWidth = resultPointStrokeWidth;
this.resultPointStrokeColor = resultPointStrokeColor;
this.resultPointColor = resultPointColor;
return this;
}
public Builder setLaserStyle(LaserStyle laserStyle) {
this.laserStyle = laserStyle;
return this;
}
public Builder isShowPhotoAlbum(boolean showPhotoAlbum) {
this.showPhotoAlbum = showPhotoAlbum;
return this;
}
public Builder isShowBeep(boolean showBeep) {
this.showBeep = showBeep;
return this;
}
public Builder isShowVibrate(boolean showVibrate) {
this.showVibrate = showVibrate;
return this;
}
public Builder setScanColor(String scanColor) {
this.scanColor = scanColor;
return this;
}
public Builder setScanHintText(String scanHintText) {
this.scanHintText = scanHintText;
return this;
}
public Builder setActivityOpenAnime(int activityOpenAnime) {
this.activityOpenAnime = activityOpenAnime;
return this;
}
public Builder setActivityExitAnime(int activityExitAnime) {
this.activityExitAnime = activityExitAnime;
return this;
}
public Builder setCustomShadeViewLayoutID(int customShadeViewLayoutID, MNCustomViewBindCallback mnCustomViewBindCallback) {
this.customShadeViewLayoutID = customShadeViewLayoutID;
mCustomViewBindCallback = mnCustomViewBindCallback;
return this;
}
public Builder setBgColor(String bgColor) {
this.bgColor = bgColor;
return this;
}
public Builder setGridScanLineColumn(int gridScanLineColumn) {
this.gridScanLineColumn = gridScanLineColumn;
return this;
}
public Builder setGridScanLineHeight(int gridScanLineHeight) {
this.gridScanLineHeight = gridScanLineHeight;
return this;
}
public Builder isShowLightController(boolean showLightController) {
this.showLightController = showLightController;
return this;
}
public Builder setScanHintTextColor(String scanHintTextColor) {
this.scanHintTextColor = scanHintTextColor;
return this;
}
public Builder setScanHintTextSize(int scanHintTextSize) {
this.scanHintTextSize = scanHintTextSize;
return this;
}
public Builder setFullScreenScan(boolean fullScreenScan) {
isFullScreenScan = fullScreenScan;
return this;
}
public Builder setSupportZoom(boolean supportZoom) {
isSupportZoom = supportZoom;
return this;
}
public Builder setScanFrameSizeScale(float widthScale) {
scanFrameSizeScale = widthScale;
return this;
}
}
}
================================================
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/ui/ScanPreviewActivity.java
================================================
package com.maning.mlkitscanner.scan.ui;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.view.PreviewView;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.mlkit.vision.barcode.common.Barcode;
import com.google.mlkit.vision.common.InputImage;
import com.maning.mlkitscanner.R;
import com.maning.mlkitscanner.scan.MNScanManager;
import com.maning.mlkitscanner.scan.callback.OnCameraAnalyserCallback;
import com.maning.mlkitscanner.scan.camera.CameraManager;
import com.maning.mlkitscanner.scan.model.MNScanConfig;
import com.maning.mlkitscanner.scan.utils.BeepManager;
import com.maning.mlkitscanner.scan.utils.ImageUtils;
import com.maning.mlkitscanner.scan.utils.StatusBarUtil;
import com.maning.mlkitscanner.scan.view.ScanActionMenuView;
import com.maning.mlkitscanner.scan.view.ScanResultPointView;
import com.maning.mlkitscanner.scan.view.ViewfinderView;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
public class ScanPreviewActivity extends AppCompatActivity {
//用来保存当前Activity
private static WeakReference<ScanPreviewActivity> sActivityRef;
private static final int REQUEST_CODE_PICK_IMAGE = 10010;
private static final int REQUEST_CODE_PERMISSION_CAMERA = 10011;
private static final int REQUEST_CODE_PERMISSION_STORAGE = 10012;
private Context mContext;
//闪光灯是否打开
private boolean is_light_on = false;
private MNScanConfig mScanConfig;
private CameraManager cameraManager;
private View fakeStatusBar;
private PreviewView mPreviewView;
private ViewfinderView viewfinderView;
private ScanResultPointView result_point_view;
private ScanActionMenuView action_menu_view;
private RelativeLayout rl_act_root;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.mn_scan_activity_scan_preview);
mContext = this;
sActivityRef = new WeakReference<>(this);
initConfig();
initViews();
initCamera();
initStatusBar();
initPermission();
}
private void initStatusBar() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
StatusBarUtil.setTransparentForWindow(this);
int statusBarHeight = StatusBarUtil.getStatusBarHeight(mContext);
ViewGroup.LayoutParams fakeStatusBarLayoutParams = fakeStatusBar.getLayoutParams();
fakeStatusBarLayoutParams.height = statusBarHeight;
fakeStatusBar.setLayoutParams(fakeStatusBarLayoutParams);
//状态栏文字颜色
if (mScanConfig.isStatusBarDarkMode()) {
StatusBarUtil.setDarkMode(this);
}
//状态栏颜色
String statusBarColor = mScanConfig.getStatusBarColor();
fakeStatusBar.setBackgroundColor(Color.parseColor(statusBarColor));
} else {
ViewGroup.LayoutParams fakeStatusBarLayoutParams = fakeStatusBar.getLayoutParams();
fakeStatusBarLayoutParams.height = 0;
fakeStatusBar.setLayoutParams(fakeStatusBarLayoutParams);
}
}
private void initPermission() {
//检查相机权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
//没有相机权限
requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CODE_PERMISSION_CAMERA);
} else {
startCamera();
}
} else {
startCamera();
}
}
private void initCamera() {
cameraManager = CameraManager.getInstance(sActivityRef.get(), mPreviewView);
cameraManager.setScanConfig(mScanConfig);
cameraManager.setOnCameraAnalyserCallback(new OnCameraAnalyserCallback() {
@Override
public void onSuccess(Bitmap bitmap, List<Barcode> barcodes) {
result_point_view.setDatas(barcodes, bitmap);
result_point_view.setVisibility(View.VISIBLE);
if (barcodes.size() == 1) {
finishSuccess(barcodes.get(0).getDisplayValue());
}
}
});
}
private void startCamera() {
cameraManager.startCamera();
}
private void initConfig() {
mScanConfig = (MNScanConfig) getIntent().getSerializableExtra(MNScanManager.INTENT_KEY_CONFIG_MODEL);
if (mScanConfig == null) {
mScanConfig = new MNScanConfig.Builder().builder();
}
}
private void initViews() {
rl_act_root = (RelativeLayout) findViewById(R.id.rl_act_root);
mPreviewView = (PreviewView) findViewById(R.id.previewView);
mPreviewView.setScaleType(PreviewView.ScaleType.FILL_CENTER);
fakeStatusBar = (View) findViewById(R.id.fakeStatusBar);
viewfinderView = (ViewfinderView) findViewById(R.id.viewfinderView);
action_menu_view = (ScanActionMenuView) findViewById(R.id.action_menu_view);
result_point_view = (ScanResultPointView) findViewById(R.id.result_point_view);
action_menu_view.setOnScanActionMenuListener(new ScanActionMenuView.OnScanActionMenuListener() {
@Override
public void onClose() {
finishCancle();
}
@Override
public void onLight() {
if (is_light_on) {
closeLight();
} else {
openLight();
}
}
@Override
public void onPhoto() {
getImageFromAlbum();
}
});
result_point_view.setOnResultPointClickListener(new ScanResultPointView.OnResultPointClickListener() {
@Override
public void onPointClick(String result) {
finishSuccess(result);
}
@Override
public void onCancle() {
cameraManager.setAnalyze(true);
result_point_view.removeAllPoints();
result_point_view.setVisibility(View.GONE);
}
});
viewfinderView.setScanConfig(mScanConfig);
result_point_view.setScanConfig(mScanConfig);
action_menu_view.setScanConfig(mScanConfig, MNScanConfig.mCustomViewBindCallback);
}
private void openLight() {
if (!is_light_on) {
is_light_on = true;
action_menu_view.openLight();
cameraManager.openLight();
}
}
private void closeLight() {
if (is_light_on) {
is_light_on = false;
action_menu_view.closeLight();
cameraManager.closeLight();
}
}
/**
* 获取相册中的图片
*/
public void getImageFromAlbum() {
if (checkStoragePermission()) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE);
}
}
private boolean checkStoragePermission() {
//判断权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE_PERMISSION_STORAGE);
return false;
}
}
return true;
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_PERMISSION_CAMERA:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission Granted 授予权限
//用户同意了权限申请
startCamera();
} else {
// Permission Denied 权限被拒绝
Toast.makeText(mContext, "初始化相机失败,相机权限被拒绝", Toast.LENGTH_SHORT).show();
finishFailed("初始化相机失败,相机权限被拒绝");
}
break;
case REQUEST_CODE_PERMISSION_STORAGE:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//用户同意使用write
getImageFromAlbum();
} else {
//缺少权限
Toast.makeText(mContext, "打开相册失败,读写权限被拒绝", Toast.LENGTH_SHORT).show();
}
default:
break;
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//去相册选择图片
if (requestCode == REQUEST_CODE_PICK_IMAGE && resultCode == RESULT_OK) {
if (data == null) {
return;
}
Bitmap decodeAbleBitmap = ImageUtils.getBitmap(mContext, data.getData());
if (decodeAbleBitmap == null) {
Log.e("======", "decodeAbleBitmap == null");
return;
}
cameraManager.setAnalyze(false);
new Thread(new Runnable() {
@Override
public void run() {
//分析这个图片
InputImage inputImage = InputImage.fromBitmap(decodeAbleBitmap, 0);
cameraManager.getBarcodeAnalyser().getBarcodeScanner().process(inputImage)
.addOnSuccessListener(new OnSuccessListener<List<Barcode>>() {
@Override
public void onSuccess(@NonNull List<Barcode> barcodes) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.e("======", "barcodes.size():" + barcodes.size());
if (barcodes.size() == 0) {
cameraManager.setAnalyze(true);
Toast.makeText(mContext, "未找到二维码或者条形码", Toast.LENGTH_SHORT).show();
return;
}
ArrayList<String> results = new ArrayList<>();
for (Barcode barcode : barcodes) {
String value = barcode.getDisplayValue();
Log.e("======", "value:" + value);
results.add(value);
}
finishSuccess(results);
}
});
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.e("======", "onFailure---:" + e.toString());
}
});
}
}).start();
}
}
@Override
public void onBackPressed() {
if (result_point_view.getVisibility() == View.VISIBLE) {
cameraManager.setAnalyze(true);
result_point_view.removeAllPoints();
result_point_view.setVisibility(View.GONE);
return;
}
//取消扫码
finishCancle();
}
@Override
protected void onDestroy() {
cameraManager.release();
super.onDestroy();
}
private void finishCancle() {
setResult(MNScanManager.RESULT_CANCLE, new Intent());
finishFinal();
}
private void finishFailed(String errorMsg) {
Intent intent = new Intent();
intent.putExtra(MNScanManager.INTENT_KEY_RESULT_ERROR, errorMsg);
setResult(MNScanManager.RESULT_FAIL, intent);
finishFinal();
}
private void finishSuccess(String result) {
ArrayList<String> results = new ArrayList<>();
results.add(result);
finishSuccess(results);
}
private void finishSuccess(ArrayList<String> results) {
Intent intent = new Intent();
intent.putStringArrayListExtra(MNScanManager.INTENT_KEY_RESULT_SUCCESS, results);
setResult(MNScanManager.RESULT_SUCCESS, intent);
finishFinal();
}
private void finishFinal() {
closeLight();
MNScanConfig.mCustomViewBindCallback = null;
sActivityRef = null;
viewfinderView.destroyView();
cameraManager.release();
rl_act_root.removeView(viewfinderView);
rl_act_root.removeView(mPreviewView);
rl_act_root.removeView(action_menu_view);
finish();
overridePendingTransition(0, mScanConfig.getActivityExitAnime() == 0 ? R.anim.mn_scan_activity_bottom_out : mScanConfig.getActivityExitAnime());
}
//---------对外提供方法----------
/**
* 关闭当前Activity
*/
public static void closeScanPage() {
if (sActivityRef != null && sActivityRef.get() != null) {
sActivityRef.get().finishCancle();
}
}
/**
* 打开相册扫描图片
*/
public static void openAlbumPage() {
if (sActivityRef != null && sActivityRef.get() != null) {
sActivityRef.get().getImageFromAlbum();
}
}
/**
* 打开手电筒
*/
public static void openScanLight() {
if (sActivityRef != null && sActivityRef.get() != null) {
sActivityRef.get().openLight();
}
}
/**
* 关闭手电筒
*/
public static void closeScanLight() {
if (sActivityRef != null && sActivityRef.get() != null) {
sActivityRef.get().closeLight();
}
}
/**
* 是否开启手电筒
*/
public static boolean isLightOn() {
if (sActivityRef != null && sActivityRef.get() != null) {
return sActivityRef.get().is_light_on;
}
return false;
}
}
================================================
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/utils/AmbientLightManager.java
================================================
/*
* Copyright (C) Jenly, MLKit 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.maning.mlkitscanner.scan.utils;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
/**
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
*/
public class AmbientLightManager implements SensorEventListener {
private static final int INTERVAL_TIME = 200;
protected static final float DARK_LUX = 45.0f;
protected static final float BRIGHT_LUX = 100.0f;
/**
* 光线太暗时,默认:照度45 lux
*/
private float darkLightLux = DARK_LUX;
/**
* 光线足够亮时,默认:照度100 lux
*/
private float brightLightLux = BRIGHT_LUX;
private SensorManager sensorManager;
private Sensor lightSensor;
private long lastTime;
private boolean isLightSensorEnabled;
private OnLightSensorEventListener mOnLightSensorEventListener;
public AmbientLightManager(Context context) {
sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
isLightSensorEnabled = true;
}
public void register() {
if (sensorManager != null && lightSensor != null) {
sensorManager.registerListener(this, lightSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
}
public void unregister() {
if (sensorManager != null && lightSensor != null) {
sensorManager.unregisterListener(this);
}
}
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
if(isLightSensorEnabled){
long currentTime = System.currentTimeMillis();
if(currentTime - lastTime < INTERVAL_TIME){//降低频率
return;
}
lastTime = currentTime;
if (mOnLightSensorEventListener != null) {
float lightLux = sensorEvent.values[0];
mOnLightSensorEventListener.onSensorChanged(lightLux);
if (lightLux <= darkLightLux) {
mOnLightSensorEventListener.onSensorChanged(true,lightLux);
} else if (lightLux >= brightLightLux) {
mOnLightSensorEventListener.onSensorChanged(false,lightLux);
}
}
}
}
/**
* 设置光线足够暗的阈值(单位:lux)
* @param lightLux
*/
public void setDarkLightLux(float lightLux){
this.darkLightLux = lightLux;
}
/**
* 设置光线足够明亮的阈值(单位:lux)
* @param lightLux
*/
public void setBrightLightLux(float lightLux){
this.brightLightLux = lightLux;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// do nothing
}
public boolean isLightSensorEnabled() {
return isLightSensorEnabled;
}
/**
* 设置是否启用光线亮度传感器
* @param lightSensorEnabled
*/
public void setLightSensorEnabled(boolean lightSensorEnabled) {
isLightSensorEnabled = lightSensorEnabled;
}
/**
* 设置光线亮度传感器监听器,只有在 {@link #isLightSensorEnabled} 为{@code true} 才有效
* @param listener
*/
public void setOnLightSensorEventListener(OnLightSensorEventListener listener){
mOnLightSensorEventListener = listener;
}
public interface OnLightSensorEventListener{
/**
*
* @param lightLux 当前检测到的光线照度值
*/
default void onSensorChanged(float lightLux){
}
/**
* 传感器改变事件
* @param dark 是否太暗了,当检测到的光线照度值小于{@link #darkLightLux}时,为{@code true}
* @param lightLux 当前检测到的光线照度值
*/
void onSensorChanged(boolean dark, float lightLux);
}
}
================================================
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/utils/BeepManager.java
================================================
/*
* Copyright (C) Jenly, MLKit 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.maning.mlkitscanner.scan.utils;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Vibrator;
import com.maning.mlkitscanner.R;
import java.io.Closeable;
/**
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
*/
public final class BeepManager implements MediaPlayer.OnErrorListener, Closeable {
private static final long VIBRATE_DURATION = 200L;
private final Context context;
private MediaPlayer mediaPlayer;
private Vibrator vibrator;
private boolean playBeep;
private boolean vibrate;
public BeepManager(Context context) {
this.context = context;
this.mediaPlayer = null;
updatePrefs();
}
public void setVibrate(boolean vibrate){
this.vibrate = vibrate;
}
public void setPlayBeep(boolean playBeep){
this.playBeep = playBeep;
}
private synchronized void updatePrefs() {
if (mediaPlayer == null) {
mediaPlayer = buildMediaPlayer(context);
}
if(vibrator == null){
vibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
}
}
public synchronized void playBeepSoundAndVibrate() {
if (playBeep && mediaPlayer != null) {
mediaPlayer.start();
}
if (vibrate) {
vibrator.vibrate(VIBRATE_DURATION);
}
}
private MediaPlayer buildMediaPlayer(Context context) {
MediaPlayer mediaPlayer = new MediaPlayer();
try {
AssetFileDescriptor file = context.getResources().openRawResourceFd(R.raw.mn_scan_beep);
mediaPlayer.setDataSource(file.getFileDescriptor(), file.getStartOffset(), file.getLength());
mediaPlayer.setOnErrorListener(this);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setLooping(false);
mediaPlayer.prepare();
return mediaPlayer;
} catch (Exception e) {
mediaPlayer.release();
return null;
}
}
@Override
public synchronized boolean onError(MediaPlayer mp, int what, int extra) {
close();
updatePrefs();
return true;
}
@Override
public synchronized void close() {
try{
if (mediaPlayer != null) {
mediaPlayer.release();
mediaPlayer = null;
}
}catch (Exception e){
}
}
}
================================================
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/utils/CommonUtils.java
================================================
package com.maning.mlkitscanner.scan.utils;
import android.content.Context;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.view.WindowManager;
/**
* Created by maning on 2017/11/9.
*/
public class CommonUtils {
/**
* 根据手机分辨率从DP转成PX
*
* @param context
* @param dpValue
* @return
*/
public static int dip2px(Context context, float dpValue) {
float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 将sp值转换为px值,保证文字大小不变
*
* @param spValue
* @return
*/
public static int sp2px(Context context, float spValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}
/**
* 根据手机的分辨率PX(像素)转成DP
*
* @param context
* @param pxValue
* @return
*/
public static int px2dip(Context context, float pxValue) {
float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
/**
* 将px值转换为sp值,保证文字大小不变
*
* @param pxValue
* @return
*/
public static int px2sp(Context context, float pxValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (pxValue / fontScale + 0.5f);
}
public static int getScreenWidth(Context context) {
try {
final WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
final DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.widthPixels;
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
public static int getTextWidth(String text, Paint paint){
Rect rect = new Rect();
paint.getTextBounds(text, 0, text.length(), rect);
return rect.width();
}
public static int getTextHeight(String text, Paint paint){
Rect rect = new Rect();
paint.getTextBounds(text, 0, text.length(), rect);
return rect.height();
}
}
================================================
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/utils/ImageUtils.java
================================================
/*
* Copyright (C) Jenly, MLKit 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.maning.mlkitscanner.scan.utils;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.net.Uri;
import android.util.DisplayMetrics;
import androidx.camera.core.ImageProxy;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
/**
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
*/
public class ImageUtils {
private ImageUtils(){
throw new AssertionError();
}
public static Bitmap imageProxyToBitmap(ImageProxy imageProxy) throws Exception {
return imageProxyToBitmap(imageProxy,0);
}
public static Bitmap imageProxyToBitmap(ImageProxy imageProxy, int rotationDegrees) throws Exception {
ImageProxy.PlaneProxy[] plane = imageProxy.getPlanes();
ByteBuffer yBuffer = plane[0].getBuffer(); // Y
ByteBuffer uBuffer = plane[1].getBuffer(); // U
ByteBuffer vBuffer = plane[2].getBuffer(); // V
int ySize = yBuffer.remaining();
int uSize = uBuffer.remaining();
int vSize = vBuffer.remaining();
byte[] nv21 = new byte[ySize + uSize + vSize];
//U and V are swapped
yBuffer.get(nv21, 0, ySize);
vBuffer.get(nv21, ySize, vSize);
uBuffer.get(nv21, ySize + vSize, uSize);
YuvImage yuvImage = new YuvImage(nv21, ImageFormat.NV21, imageProxy.getWidth(), imageProxy.getHeight(), null);
ByteArrayOutputStream stream = new ByteArrayOutputStream(nv21.length);
yuvImage.compressToJpeg(new Rect(0, 0, yuvImage.getWidth(), yuvImage.getHeight()), 90, stream);
Bitmap bitmap = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size());
if(rotationDegrees != 0){
Matrix matrix = new Matrix();
matrix.postRotate(rotationDegrees);
bitmap = Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(), matrix, true);
}
return bitmap;
}
public static Bitmap getBitmap(Context context,Uri uri){
InputStream Stream = null;
InputStream inputStream = null;
try {
//根据uri获取图片的流
inputStream = context.getContentResolver().openInputStream(uri);
BitmapFactory.Options options = new BitmapFactory.Options();
//options的in系列的设置了,injustdecodebouond只解析图片的大小,而不加载到内存中去
options.inJustDecodeBounds = true;
//1.如果通过options.outHeight获取图片的宽高,就必须通过decodestream解析同options赋值
//否则options.outheight获取不到宽高
BitmapFactory.decodeStream(inputStream,null,options);
//2.通过 btm.getHeight()获取图片的宽高就不需要1的解析,我这里采取第一张方式
// Bitmap btm = BitmapFactory.decodeStream(inputStream);
//以屏幕的宽高进行压缩
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
int heightPixels = displayMetrics.heightPixels;
int widthPixels = displayMetrics.widthPixels;
//获取图片的宽高
int outHeight = options.outHeight;
int outWidth = options.outWidth;
//heightPixels就是要压缩后的图片高度,宽度也一样
int a = (int) Math.ceil((outHeight/(float)heightPixels));
int b = (int) Math.ceil(outWidth/(float)widthPixels);
//比例计算,一般是图片比较大的情况下进行压缩
int max = Math.max(a, b);
if(max > 1){
options.inSampleSize = max;
}
//解析到内存中去
options.inJustDecodeBounds = false;
// 根据uri重新获取流,inputstream在解析中发生改变了
Stream = context.getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(Stream, null, options);
return bitmap;
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(inputStream != null) {
inputStream.close();
}
if(Stream != null){
Stream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
================================================
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/utils/StatusBarUtil.java
================================================
package com.maning.mlkitscanner.scan.utils;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.regex.Pattern;
/**
* @author:created by leaf on 2019-05-07
* Github地址:https://github.com/Ye-Miao
* Desc: 状态栏工具类
*/
public class StatusBarUtil {
private static final int DEFAULT_ALPHA = 0;
/**
* 设置状态栏颜色(自定义颜色)
*
* @param activity 目标activity
* @param color 状态栏颜色值
*/
public static void setColor(Activity activity, int color) {
WeakReference<Activity> activityWeakReference = new WeakReference<>(activity);
setColor(activityWeakReference.get(), color, DEFAULT_ALPHA);
}
/**
* 设置纯色状态栏(自定义颜色,alpha)
*
* @param activity 目标activity
* @param color 状态栏颜色值
* @param alpha 状态栏透明度
*/
public static void setColor(Activity activity, int color, int alpha) {
WeakReference<Activity> activityWeakReference = new WeakReference<>(activity);
Window window = activityWeakReference.get().getWindow();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(cipherColor(color, alpha));
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
setTranslucentView((ViewGroup) window.getDecorView(), color, alpha);
setRootView(activityWeakReference.get(), true);
}
}
/**
* 设置状态栏渐变颜色
*
* @param activity 目标activity
* @param view 目标View
*/
public static void setGradientColor(Activity activity, View view) {
WeakReference<Activity> activityWeakReference = new WeakReference<>(activity);
ViewGroup decorView = (ViewGroup) activityWeakReference.get().getWindow().getDecorView();
View fakeStatusBarView = decorView.findViewById(android.R.id.custom);
if (fakeStatusBarView != null) {
decorView.removeView(fakeStatusBarView);
}
setRootView(activityWeakReference.get(), false);
setTransparentForWindow(activityWeakReference.get());
setPaddingTop(activityWeakReference.get(), view);
}
/**
* 设置透明状态栏
*
* @param activity 目标界面
*/
public static void setTransparentForWindow(Activity activity) {
WeakReference<Activity> activityWeakReference = new WeakReference<>(activity);
Window window = activityWeakReference.get().getWindow();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
window.getDecorView()
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
/**
* 增加View的paddingTop,增加的值为状态栏高度 (智能判断,并设置高度)
*
* @param context 目标Context
* @param view 需要增高的View
*/
public static void setPaddingTop(Context context, View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
ViewGroup.LayoutParams lp = view.getLayoutParams();
if (lp != null && lp.height > 0 && view.getPaddingTop() == 0) {
lp.height += getStatusBarHeight(context);
view.setPadding(view.getPaddingLeft(), view.getPaddingTop() + getStatusBarHeight(context),
view.getPaddingRight(), view.getPaddingBottom());
}
}
}
/**
* 设置状态栏darkMode,字体颜色及icon变黑(目前支持MIUI6以上,Flyme4以上,Android M以上)
*
* @param activity 目标activity
*/
public static void setDarkMode(Activity activity) {
WeakReference<Activity> activityWeakReference = new WeakReference<>(activity);
darkMode(activityWeakReference.get().getWindow(), true);
}
/**
* 设置状态栏darkMode,字体颜色及icon变亮(目前支持MIUI6以上,Flyme4以上,Android M以上)
*
* @param activity 目标activity
*/
public static void setLightMode(Activity activity) {
WeakReference<Activity> activityWeakReference = new WeakReference<>(activity);
darkMode(activityWeakReference.get().getWindow(), false);
}
@TargetApi(Build.VERSION_CODES.M)
private static void darkMode(Window window, boolean dark) {
if (isFlyme4()) {
setModeForFlyme4(window, dark);
} else if (isMIUI6()) {
setModeForMIUI6(window, dark);
}
darkModeForM(window, dark);
}
/**
* android 6.0设置字体颜色
*
* @param window 目标window
* @param dark 亮色 or 暗色
*/
private static void darkModeForM(Window window, boolean dark) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int systemUiVisibility = window.getDecorView().getSystemUiVisibility();
if (dark) {
systemUiVisibility |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
} else {
systemUiVisibility &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
}
window.getDecorView().setSystemUiVisibility(systemUiVisibility);
}
}
/**
* 设置MIUI6+的状态栏的darkMode,darkMode时候字体颜色及icon
* http://dev.xiaomi.com/doc/p=4769/
*
* @param window 目标window
* @param dark 亮色 or 暗色
*/
private static void setModeForMIUI6(Window window, boolean dark) {
Class<? extends Window> clazz = window.getClass();
try {
Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
int darkModeFlag = field.getInt(layoutParams);
Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
extraFlagField.invoke(window, dark ? darkModeFlag : 0, darkModeFlag);
} catch (Exception e) {
Log.e("StatusBar", "darkIcon: failed");
}
}
/**
* 设置Flyme4+的状态栏的darkMode,darkMode时候字体颜色及icon
* http://open-wiki.flyme.cn/index.php?title=Flyme%E7%B3%BB%E7%BB%9FAPI
*
* @param window 目标window
* @param dark 亮色 or 暗色
*/
private static void setModeForFlyme4(Window window, boolean dark) {
try {
WindowManager.LayoutParams lp = window.getAttributes();
Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags");
darkFlag.setAccessible(true);
meizuFlags.setAccessible(true);
int bit = darkFlag.getInt(null);
int value = meizuFlags.getInt(lp);
if (dark) {
value |= bit;
} else {
value &= ~bit;
}
meizuFlags.setInt(lp, value);
window.setAttributes(lp);
} catch (Exception e) {
Log.e("StatusBar", "darkIcon: failed");
}
}
/**
* 判断是否Flyme4以上
*/
private static boolean isFlyme4() {
return Build.FINGERPRINT.contains("Flyme_OS_4") || Build.VERSION.INCREMENTAL.contains("Flyme_OS_4")
|| Pattern.compile("Flyme OS [4|5]", Pattern.CASE_INSENSITIVE).matcher(Build.DISPLAY).find();
}
/**
* 判断是否MIUI6以上
*/
private static boolean isMIUI6() {
try {
Class<?> clz = Class.forName("android.os.SystemProperties");
Method mtd = clz.getMethod("get", String.class);
String val = (String) mtd.invoke(null, "ro.miui.ui.version.name");
val = val.replaceAll("[vV]", "");
int version = Integer.parseInt(val);
return version >= 6;
} catch (Exception e) {
return false;
}
}
/**
* 计算alpha色值
*
* @param color 状态栏颜色值
* @param alpha 状态栏透明度
*/
private static int cipherColor(int color, int alpha) {
if (alpha == 0) {
return color;
}
float a = 1 - alpha / 255f;
int red = color >> 16 & 0xff;
int green = color >> 8 & 0xff;
int blue = color & 0xff;
red = (int) (red * a + 0.5);
green = (int) (green * a + 0.5);
blue = (int) (blue * a + 0.5);
return 0xff << 24 | red << 16 | green << 8 | blue;
}
/**
* 创建透明View
*
* @param viewGroup 目标视图
* @param color 状态栏颜色值
* @param alpha 状态栏透明度
*/
private static void setTranslucentView(ViewGroup viewGroup, int color, int alpha) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
int cipherColor = cipherColor(color, alpha);
View translucentView = viewGroup.findViewById(android.R.id.custom);
if (translucentView == null && cipherColor != 0) {
translucentView = new View(viewGroup.getContext());
translucentView.setId(android.R.id.custom);
ViewGroup.LayoutParams params =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(viewGroup.getContext()));
viewGroup.addView(translucentView, params);
}
if (translucentView != null) {
translucentView.setBackgroundColor(cipherColor);
}
}
}
/**
* 设置根布局参数
*
* @param activity 目标activity
* @param fitSystemWindows 是否预留toolbar的高度
*/
private static void setRootView(Activity activity, boolean fitSystemWindows) {
WeakReference<Activity> activityWeakReference = new WeakReference<>(activity);
ViewGroup parent = activityWeakReference.get().findViewById(android.R.id.content);
for (int i = 0, count = parent.getChildCount(); i < count; i++) {
View childView = parent.getChildAt(i);
if (childView instanceof ViewGroup) {
childView.setFitsSystemWindows(fitSystemWindows);
((ViewGroup) childView).setClipToPadding(fitSystemWindows);
}
}
}
/**
* 获取状态栏高度
*
* @param context 目标Context
*/
public static int getStatusBarHeight(Context context) {
// 获得状态栏高度
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
return context.getResources().getDimensionPixelSize(resourceId);
}
}
================================================
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/utils/ZXingUtils.java
================================================
package com.maning.mlkitscanner.scan.utils;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Matrix;
import android.text.TextUtils;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
/**
* Created by maning on 2017/11/10.
*/
public class ZXingUtils {
public static final Map<DecodeHintType, Object> HINTS = new EnumMap<>(DecodeHintType.class);
static {
List<BarcodeFormat> allFormats = new ArrayList<>();
allFormats.add(BarcodeFormat.AZTEC);
allFormats.add(BarcodeFormat.CODABAR);
allFormats.add(BarcodeFormat.CODE_39);
allFormats.add(BarcodeFormat.CODE_93);
allFormats.add(BarcodeFormat.CODE_128);
allFormats.add(BarcodeFormat.DATA_MATRIX);
allFormats.add(BarcodeFormat.EAN_8);
allFormats.add(BarcodeFormat.EAN_13);
allFormats.add(BarcodeFormat.ITF);
allFormats.add(BarcodeFormat.MAXICODE);
allFormats.add(BarcodeFormat.PDF_417);
allFormats.add(BarcodeFormat.QR_CODE);
allFormats.add(BarcodeFormat.RSS_14);
allFormats.add(BarcodeFormat.RSS_EXPANDED);
allFormats.add(BarcodeFormat.UPC_A);
allFormats.add(BarcodeFormat.UPC_E);
allFormats.add(BarcodeFormat.UPC_EAN_EXTENSION);
HINTS.put(DecodeHintType.POSSIBLE_FORMATS, allFormats);
HINTS.put(DecodeHintType.CHARACTER_SET, "utf-8");
}
public static Bitmap createQRCodeImage(String content) {
return createQRCodeImage(content, 500, 0, Color.BLACK, Color.WHITE, null, null, null);
}
public static Bitmap createQRCodeImage(String content, int size) {
return createQRCodeImage(content, size, 0, Color.BLACK, Color.WHITE, null, null, null);
}
public static Bitmap createQRCodeImage(String content, int size, int margin) {
return createQRCodeImage(content, size, margin, Color.BLACK, Color.WHITE, null, null, null);
}
public static Bitmap createQRCodeImage(String text, Bitmap logo_bitmap) {
return createQRCodeImage(text, 500, 0, Color.BLACK, Color.WHITE, null, logo_bitmap, null);
}
public static Bitmap createQRCodeImage(String text, int size, Bitmap logo_bitmap) {
return createQRCodeImage(text, size, 0, Color.BLACK, Color.WHITE, null, logo_bitmap, null);
}
public static Bitmap createQRCodeImage(String text, int size, int margin, Bitmap logo_bitmap) {
return createQRCodeImage(text, size, margin, Color.BLACK, Color.WHITE, null, logo_bitmap, null);
}
/**
* 生成带logo的二维码,logo默认为二维码的1/5
*
* @param text 需要生成二维码的内容
* @param size 需要生成二维码的大小
* @param margin 二维码边距
* @param foreground_color 二维码前景色
* @param background_color 二维码背景颜色
* @param error_correction_level 容错率 L:7% M:15% Q:25% H:35%
* @param logo_bitmap logo文件
* @return bitmap
*/
public static Bitmap createQRCodeImage(String text, int size, int margin, int foreground_color, int background_color, String error_correction_level, Bitmap logo_bitmap) {
return createQRCodeImage(text, size, margin, foreground_color, background_color, error_correction_level, logo_bitmap, null);
}
/**
* 生成带logo的二维码,logo默认为二维码的1/5
*
* @param text 需要生成二维码的内容
* @param size 需要生成二维码的大小
* @param margin 二维码边距
* @param foreground_color 二维码前景色
* @param background_color 二维码背景颜色
* @param error_correction_level 容错率 L:7% M:15% Q:25% H:35%
* @param logo_bitmap logo文件
* @param logo_bitmap 二维码前景图片,不建议使用(可能太花识别率会降低)
* @return bitmap
*/
public static Bitmap createQRCodeImage(String text, int size, int margin, int foreground_color, int background_color, String error_correction_level, Bitmap logo_bitmap, Bitmap foreground_bitmap) {
try {
int IMAGE_HALFWIDTH = size / 10;
Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hints.put(EncodeHintType.MARGIN, Math.max(margin, 0));
/*
* 设置容错级别,默认为ErrorCorrectionLevel.L
* 因为中间加入logo所以建议你把容错级别调至H,否则可能会出现识别不了
*/
if (TextUtils.isEmpty(error_correction_level)) {
if (logo_bitmap != null) {
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
} else {
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
}
} else {
hints.put(EncodeHintType.ERROR_CORRECTION, error_correction_level);
}
BitMatrix bitMatrix = new QRCodeWriter().encode(text,
BarcodeFormat.QR_CODE, size, size, hints);
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
int halfW = width / 2;
int halfH = height / 2;
if (logo_bitmap != null) {
Matrix m = new Matrix();
float sx = (float) 2 * IMAGE_HALFWIDTH / logo_bitmap.getWidth();
float sy = (float) 2 * IMAGE_HALFWIDTH / logo_bitmap.getHeight();
m.setScale(sx, sy);
//设置缩放信息
//将logo图片按martix设置的信息缩放
logo_bitmap = Bitmap.createBitmap(logo_bitmap, 0, 0,
logo_bitmap.getWidth(), logo_bitmap.getHeight(), m, false);
}
if (foreground_bitmap != null) {
//从当前位图按一定的比例创建一个新的位图
foreground_bitmap = Bitmap.createScaledBitmap(foreground_bitmap, width, height, false);
}
int[] pixels = new int[size * size];
for (int y = 0; y < size; y++) {
for (int x = 0; x < size; x++) {
if (logo_bitmap != null) {
if (x > halfW - IMAGE_HALFWIDTH && x < halfW + IMAGE_HALFWIDTH
&& y > halfH - IMAGE_HALFWIDTH
&& y < halfH + IMAGE_HALFWIDTH) {
//该位置用于存放图片信息
//记录图片每个像素信息
pixels[y * width + x] = logo_bitmap.getPixel(x - halfW
+ IMAGE_HALFWIDTH, y - halfH + IMAGE_HALFWIDTH);
} else {
if (bitMatrix.get(x, y)) {
if (foreground_bitmap != null) {
pixels[y * width + x] = foreground_bitmap.getPixel(x, y);
} else {
pixels[y * width + x] = foreground_color;
}
} else {
pixels[y * size + x] = background_color;
}
}
} else {
if (bitMatrix.get(x, y)) {
if (foreground_bitmap != null) {
pixels[y * width + x] = foreground_bitmap.getPixel(x, y);
} else {
pixels[y * width + x] = foreground_color;
}
} else {
pixels[y * size + x] = background_color;
}
}
}
}
Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, size, 0, 0, size, size);
return bitmap;
} catch (WriterException e) {
e.printStackTrace();
return null;
}
}
//------解析图片-----
/**
* 同步解析本地图片二维码。该方法是耗时操作,请在子线程中调用。
*
* @param picturePath 要解析的二维码图片本地路径
* @return 返回二维码图片里的内容 或 null
*/
public static String syncDecodeQRCode(String picturePath) {
return syncDecodeQRCode(getDecodeAbleBitmap(picturePath));
}
/**
* 同步解析bitmap二维码。该方法是耗时操作,请在子线程中调用。
*
* @param bitmap 要解析的二维码图片
* @return 返回二维码图片里的内容 或 null
*/
public static String syncDecodeQRCode(Bitmap bitmap) {
try {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int[] pixels = new int[width * height];
bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
com.google.zxing.RGBLuminanceSource source = new com.google.zxing.RGBLuminanceSource(width, height, pixels);
Result result = new MultiFormatReader().decode(new BinaryBitmap(new HybridBinarizer(source)), HINTS);
if (result != null) {
return recode(result.getText());
} else {
return null;
}
} catch (Exception e) {
return null;
}
}
/**
* 将本地图片文件转换成可解码二维码的 Bitmap
*
* @param picturePath 本地图片文件路径
* @return
*/
private static Bitmap getDecodeAbleBitmap(String picturePath) {
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(picturePath, options);
int sampleSize = options.outHeight / 400;
if (sampleSize <= 0) {
sampleSize = 1;
}
options.inSampleSize = sampleSize;
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(picturePath, options);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 中文乱码
*
* @return
*/
public static String recode(String str) {
String formart = "";
try
gitextract_hdq0awll/ ├── .gitignore ├── .idea/ │ ├── codeStyles/ │ │ └── Project.xml │ ├── compiler.xml │ ├── encodings.xml │ ├── gradle.xml │ ├── inspectionProfiles/ │ │ └── Project_Default.xml │ ├── jarRepositories.xml │ ├── misc.xml │ └── vcs.xml ├── LICENSE ├── README.md ├── apk/ │ └── demo.apk ├── app/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ ├── androidTest/ │ │ └── java/ │ │ └── com/ │ │ └── maning/ │ │ └── mlkitscanner/ │ │ └── ExampleInstrumentedTest.java │ ├── main/ │ │ ├── AndroidManifest.xml │ │ ├── java/ │ │ │ └── com/ │ │ │ └── maning/ │ │ │ └── mlkitscanner/ │ │ │ └── demo/ │ │ │ ├── CustomConfigActivity.java │ │ │ └── MainActivity.java │ │ └── res/ │ │ ├── anim/ │ │ │ ├── activity_anmie_in.xml │ │ │ └── activity_anmie_out.xml │ │ ├── drawable/ │ │ │ └── ic_launcher_background.xml │ │ ├── drawable-v24/ │ │ │ └── ic_launcher_foreground.xml │ │ ├── layout/ │ │ │ ├── activity_custom_config.xml │ │ │ ├── activity_main.xml │ │ │ └── layout_custom_view.xml │ │ ├── mipmap-anydpi-v26/ │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ └── values/ │ │ ├── array.xml │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test/ │ └── java/ │ └── com/ │ └── maning/ │ └── mlkitscanner/ │ └── ExampleUnitTest.java ├── build.gradle ├── config.gradle ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── mlkit-scanner/ │ ├── .gitignore │ ├── build.gradle │ ├── consumer-rules.pro │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── java/ │ │ └── com/ │ │ └── maning/ │ │ └── mlkitscanner/ │ │ └── scan/ │ │ ├── MNScanManager.java │ │ ├── analyser/ │ │ │ └── BarcodeAnalyser.java │ │ ├── callback/ │ │ │ ├── MNCustomViewBindCallback.java │ │ │ ├── OnCameraAnalyserCallback.java │ │ │ └── act/ │ │ │ ├── ActResultRequest.java │ │ │ ├── MNScanCallback.java │ │ │ └── OnActResultEventDispatcherFragment.java │ │ ├── camera/ │ │ │ ├── CameraManager.java │ │ │ └── CameraSizeUtils.java │ │ ├── model/ │ │ │ └── MNScanConfig.java │ │ ├── ui/ │ │ │ └── ScanPreviewActivity.java │ │ ├── utils/ │ │ │ ├── AmbientLightManager.java │ │ │ ├── BeepManager.java │ │ │ ├── CommonUtils.java │ │ │ ├── ImageUtils.java │ │ │ ├── StatusBarUtil.java │ │ │ └── ZXingUtils.java │ │ └── view/ │ │ ├── ScanActionMenuView.java │ │ ├── ScanResultPointView.java │ │ └── ViewfinderView.java │ └── res/ │ ├── anim/ │ │ ├── mn_scan_activity_bottom_in.xml │ │ └── mn_scan_activity_bottom_out.xml │ ├── drawable/ │ │ └── mn_scan_result_point_default.xml │ ├── layout/ │ │ ├── mn_scan_action_menu.xml │ │ ├── mn_scan_activity_scan_preview.xml │ │ ├── mn_scan_result_point_item_view.xml │ │ └── mn_scan_result_point_view.xml │ ├── raw/ │ │ └── mn_scan_beep.ogg │ └── values/ │ ├── colors.xml │ └── styles.xml └── settings.gradle
SYMBOL INDEX (260 symbols across 24 files)
FILE: app/src/androidTest/java/com/maning/mlkitscanner/ExampleInstrumentedTest.java
class ExampleInstrumentedTest (line 18) | @RunWith(AndroidJUnit4.class)
method useAppContext (line 20) | @Test
FILE: app/src/main/java/com/maning/mlkitscanner/demo/CustomConfigActivity.java
class CustomConfigActivity (line 29) | public class CustomConfigActivity extends AppCompatActivity implements V...
method onCreate (line 104) | @Override
method initView (line 111) | private void initView() {
method onClick (line 160) | @Override
method getHexString (line 240) | private String getHexString(int color) {
method scanCode (line 250) | public void scanCode(View view) {
method showToast (line 357) | private void showToast(String msg) {
method handlerResult (line 362) | private void handlerResult(int resultCode, Intent data) {
FILE: app/src/main/java/com/maning/mlkitscanner/demo/MainActivity.java
class MainActivity (line 30) | public class MainActivity extends AppCompatActivity implements View.OnCl...
method onCreate (line 50) | @Override
method initView (line 58) | private void initView() {
method requestCameraPerm (line 150) | public void requestCameraPerm() {
method onClick (line 159) | @Override
method handlerResult (line 174) | private void handlerResult(int resultCode, Intent data) {
method showToast (line 201) | private void showToast(String msg) {
method createQRImage (line 206) | public void createQRImage(View view) {
FILE: app/src/test/java/com/maning/mlkitscanner/ExampleUnitTest.java
class ExampleUnitTest (line 12) | public class ExampleUnitTest {
method addition_isCorrect (line 13) | @Test
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/MNScanManager.java
class MNScanManager (line 16) | public class MNScanManager {
method startScan (line 32) | public static void startScan(Activity activity, MNScanCallback scanCal...
method startScan (line 36) | public static void startScan(Activity activity, MNScanConfig mnScanCon...
method closeScanPage (line 51) | public static void closeScanPage() {
method openAlbumPage (line 58) | public static void openAlbumPage() {
method openScanLight (line 65) | public static void openScanLight() {
method closeScanLight (line 72) | public static void closeScanLight() {
method isLightOn (line 79) | public static boolean isLightOn() {
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/analyser/BarcodeAnalyser.java
class BarcodeAnalyser (line 31) | public class BarcodeAnalyser implements ImageAnalysis.Analyzer {
method getBarcodeScanner (line 42) | public BarcodeScanner getBarcodeScanner() {
method setAnalyze (line 46) | public void setAnalyze(boolean analyze) {
method setOnCameraAnalyserCallback (line 50) | public void setOnCameraAnalyserCallback(OnCameraAnalyserCallback onCam...
method BarcodeAnalyser (line 54) | public BarcodeAnalyser() {
method setPreviewView (line 61) | public void setPreviewView(PreviewView mPreviewView) {
method cropBitmap (line 65) | private Bitmap cropBitmap(Bitmap bitmap, int cropWidth, int cropHeight) {
method analyze (line 71) | @Override
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/callback/MNCustomViewBindCallback.java
type MNCustomViewBindCallback (line 8) | public interface MNCustomViewBindCallback {
method onBindView (line 10) | void onBindView(View customView);
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/callback/OnCameraAnalyserCallback.java
type OnCameraAnalyserCallback (line 15) | public interface OnCameraAnalyserCallback {
method onSuccess (line 16) | void onSuccess(Bitmap bitmap, List<Barcode> barcodes);
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/callback/act/ActResultRequest.java
class ActResultRequest (line 16) | public class ActResultRequest {
method ActResultRequest (line 19) | public ActResultRequest(Activity activity) {
method getEventDispatchFragment (line 23) | private OnActResultEventDispatcherFragment getEventDispatchFragment(Ac...
method findEventDispatchFragment (line 38) | private OnActResultEventDispatcherFragment findEventDispatchFragment(F...
method startForResult (line 42) | public void startForResult(Intent intent, MNScanCallback callback) {
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/callback/act/MNScanCallback.java
type MNScanCallback (line 14) | public interface MNScanCallback {
method onActivityResult (line 16) | void onActivityResult(int resultCode, Intent data);
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/callback/act/OnActResultEventDispatcherFragment.java
class OnActResultEventDispatcherFragment (line 17) | public class OnActResultEventDispatcherFragment extends Fragment {
method onCreate (line 22) | @Override
method startForResult (line 28) | public void startForResult(Intent intent, MNScanCallback callback) {
method onActivityResult (line 33) | @Override
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/camera/CameraManager.java
class CameraManager (line 36) | public class CameraManager {
method getInstance (line 55) | public static CameraManager getInstance(Context mContext, PreviewView ...
method CameraManager (line 59) | public CameraManager(Context mContext, PreviewView mPreviewView) {
method getBarcodeAnalyser (line 65) | public BarcodeAnalyser getBarcodeAnalyser() {
method setOnCameraAnalyserCallback (line 69) | public void setOnCameraAnalyserCallback(OnCameraAnalyserCallback callb...
method setScanConfig (line 73) | public void setScanConfig(MNScanConfig config) {
method setAnalyze (line 79) | public void setAnalyze(boolean analyze) {
method initDatas (line 83) | private void initDatas() {
method startCamera (line 90) | public void startCamera() {
method initBarcodeAnalyser (line 121) | private void initBarcodeAnalyser() {
method initScaleGesture (line 136) | private void initScaleGesture() {
method onScale (line 151) | @Override
method handlePreviewViewClickTap (line 163) | private void handlePreviewViewClickTap(MotionEvent event) {
method distance (line 184) | private float distance(float aX, float aY, float bX, float bY) {
method zoomTo (line 190) | public void zoomTo(float ratio) {
method startFocusAndMetering (line 200) | private void startFocusAndMetering(float x, float y) {
method openLight (line 207) | public void openLight() {
method closeLight (line 213) | public void closeLight() {
method stopCamera (line 219) | public void stopCamera() {
method release (line 228) | public void release() {
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/camera/CameraSizeUtils.java
class CameraSizeUtils (line 13) | public class CameraSizeUtils {
method getSize (line 15) | public static Size getSize(Context context) {
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/model/MNScanConfig.java
class MNScanConfig (line 14) | public class MNScanConfig implements Serializable {
type LaserStyle (line 21) | public enum LaserStyle {
method MNScanConfig (line 77) | private MNScanConfig() {
method MNScanConfig (line 82) | private MNScanConfig(Builder builder) {
method getStatusBarColor (line 111) | public String getStatusBarColor() {
method isStatusBarDarkMode (line 115) | public boolean isStatusBarDarkMode() {
method getResultPointWithdHeight (line 119) | public int getResultPointWithdHeight() {
method getResultPointCorners (line 123) | public int getResultPointCorners() {
method getResultPointStrokeWidth (line 127) | public int getResultPointStrokeWidth() {
method getResultPointStrokeColor (line 131) | public String getResultPointStrokeColor() {
method getResultPointColor (line 135) | public String getResultPointColor() {
method isShowPhotoAlbum (line 139) | public boolean isShowPhotoAlbum() {
method isShowBeep (line 143) | public boolean isShowBeep() {
method isShowVibrate (line 147) | public boolean isShowVibrate() {
method getScanColor (line 151) | public String getScanColor() {
method getLaserStyle (line 155) | public LaserStyle getLaserStyle() {
method getScanHintText (line 159) | public String getScanHintText() {
method getScanHintTextColor (line 163) | public String getScanHintTextColor() {
method getScanHintTextSize (line 167) | public int getScanHintTextSize() {
method getActivityOpenAnime (line 171) | public int getActivityOpenAnime() {
method getActivityExitAnime (line 175) | public int getActivityExitAnime() {
method getCustomShadeViewLayoutID (line 179) | public int getCustomShadeViewLayoutID() {
method getBgColor (line 183) | public String getBgColor() {
method getGridScanLineColumn (line 187) | public int getGridScanLineColumn() {
method getGridScanLineHeight (line 191) | public int getGridScanLineHeight() {
method isShowLightController (line 195) | public boolean isShowLightController() {
method isFullScreenScan (line 199) | public boolean isFullScreenScan() {
method isSupportZoom (line 203) | public boolean isSupportZoom() {
method getScanFrameSizeScale (line 207) | public float getScanFrameSizeScale() {
class Builder (line 217) | public static class Builder {
method builder (line 261) | public MNScanConfig builder() {
method setStatusBarConfigs (line 265) | public Builder setStatusBarConfigs(String statusBarColor,
method setResultPointConfigs (line 282) | public Builder setResultPointConfigs(int resultPointWithdHeight,
method setLaserStyle (line 295) | public Builder setLaserStyle(LaserStyle laserStyle) {
method isShowPhotoAlbum (line 300) | public Builder isShowPhotoAlbum(boolean showPhotoAlbum) {
method isShowBeep (line 305) | public Builder isShowBeep(boolean showBeep) {
method isShowVibrate (line 310) | public Builder isShowVibrate(boolean showVibrate) {
method setScanColor (line 315) | public Builder setScanColor(String scanColor) {
method setScanHintText (line 320) | public Builder setScanHintText(String scanHintText) {
method setActivityOpenAnime (line 325) | public Builder setActivityOpenAnime(int activityOpenAnime) {
method setActivityExitAnime (line 330) | public Builder setActivityExitAnime(int activityExitAnime) {
method setCustomShadeViewLayoutID (line 335) | public Builder setCustomShadeViewLayoutID(int customShadeViewLayoutI...
method setBgColor (line 341) | public Builder setBgColor(String bgColor) {
method setGridScanLineColumn (line 346) | public Builder setGridScanLineColumn(int gridScanLineColumn) {
method setGridScanLineHeight (line 351) | public Builder setGridScanLineHeight(int gridScanLineHeight) {
method isShowLightController (line 356) | public Builder isShowLightController(boolean showLightController) {
method setScanHintTextColor (line 361) | public Builder setScanHintTextColor(String scanHintTextColor) {
method setScanHintTextSize (line 366) | public Builder setScanHintTextSize(int scanHintTextSize) {
method setFullScreenScan (line 371) | public Builder setFullScreenScan(boolean fullScreenScan) {
method setSupportZoom (line 376) | public Builder setSupportZoom(boolean supportZoom) {
method setScanFrameSizeScale (line 381) | public Builder setScanFrameSizeScale(float widthScale) {
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/ui/ScanPreviewActivity.java
class ScanPreviewActivity (line 42) | public class ScanPreviewActivity extends AppCompatActivity {
method onCreate (line 62) | @Override
method initStatusBar (line 77) | private void initStatusBar() {
method initPermission (line 98) | private void initPermission() {
method initCamera (line 112) | private void initCamera() {
method startCamera (line 127) | private void startCamera() {
method initConfig (line 131) | private void initConfig() {
method initViews (line 138) | private void initViews() {
method openLight (line 187) | private void openLight() {
method closeLight (line 195) | private void closeLight() {
method getImageFromAlbum (line 206) | public void getImageFromAlbum() {
method checkStoragePermission (line 215) | private boolean checkStoragePermission() {
method onRequestPermissionsResult (line 226) | @Override
method onActivityResult (line 255) | @Override
method onBackPressed (line 311) | @Override
method onDestroy (line 323) | @Override
method finishCancle (line 329) | private void finishCancle() {
method finishFailed (line 334) | private void finishFailed(String errorMsg) {
method finishSuccess (line 341) | private void finishSuccess(String result) {
method finishSuccess (line 347) | private void finishSuccess(ArrayList<String> results) {
method finishFinal (line 354) | private void finishFinal() {
method closeScanPage (line 372) | public static void closeScanPage() {
method openAlbumPage (line 381) | public static void openAlbumPage() {
method openScanLight (line 390) | public static void openScanLight() {
method closeScanLight (line 399) | public static void closeScanLight() {
method isLightOn (line 408) | public static boolean isLightOn() {
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/utils/AmbientLightManager.java
class AmbientLightManager (line 27) | public class AmbientLightManager implements SensorEventListener {
method AmbientLightManager (line 52) | public AmbientLightManager(Context context) {
method register (line 58) | public void register() {
method unregister (line 64) | public void unregister() {
method onSensorChanged (line 71) | @Override
method setDarkLightLux (line 96) | public void setDarkLightLux(float lightLux){
method setBrightLightLux (line 104) | public void setBrightLightLux(float lightLux){
method onAccuracyChanged (line 108) | @Override
method isLightSensorEnabled (line 113) | public boolean isLightSensorEnabled() {
method setLightSensorEnabled (line 121) | public void setLightSensorEnabled(boolean lightSensorEnabled) {
method setOnLightSensorEventListener (line 129) | public void setOnLightSensorEventListener(OnLightSensorEventListener l...
type OnLightSensorEventListener (line 133) | public interface OnLightSensorEventListener{
method onSensorChanged (line 138) | default void onSensorChanged(float lightLux){
method onSensorChanged (line 147) | void onSensorChanged(boolean dark, float lightLux);
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/utils/BeepManager.java
class BeepManager (line 32) | public final class BeepManager implements MediaPlayer.OnErrorListener, C...
method BeepManager (line 42) | public BeepManager(Context context) {
method setVibrate (line 48) | public void setVibrate(boolean vibrate){
method setPlayBeep (line 52) | public void setPlayBeep(boolean playBeep){
method updatePrefs (line 56) | private synchronized void updatePrefs() {
method playBeepSoundAndVibrate (line 65) | public synchronized void playBeepSoundAndVibrate() {
method buildMediaPlayer (line 74) | private MediaPlayer buildMediaPlayer(Context context) {
method onError (line 90) | @Override
method close (line 97) | @Override
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/utils/CommonUtils.java
class CommonUtils (line 13) | public class CommonUtils {
method dip2px (line 21) | public static int dip2px(Context context, float dpValue) {
method sp2px (line 32) | public static int sp2px(Context context, float spValue) {
method px2dip (line 44) | public static int px2dip(Context context, float pxValue) {
method px2sp (line 56) | public static int px2sp(Context context, float pxValue) {
method getScreenWidth (line 61) | public static int getScreenWidth(Context context) {
method getTextWidth (line 74) | public static int getTextWidth(String text, Paint paint){
method getTextHeight (line 80) | public static int getTextHeight(String text, Paint paint){
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/utils/ImageUtils.java
class ImageUtils (line 38) | public class ImageUtils {
method ImageUtils (line 40) | private ImageUtils(){
method imageProxyToBitmap (line 44) | public static Bitmap imageProxyToBitmap(ImageProxy imageProxy) throws ...
method imageProxyToBitmap (line 48) | public static Bitmap imageProxyToBitmap(ImageProxy imageProxy, int rot...
method getBitmap (line 79) | public static Bitmap getBitmap(Context context,Uri uri){
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/utils/StatusBarUtil.java
class StatusBarUtil (line 24) | public class StatusBarUtil {
method setColor (line 34) | public static void setColor(Activity activity, int color) {
method setColor (line 46) | public static void setColor(Activity activity, int color, int alpha) {
method setGradientColor (line 66) | public static void setGradientColor(Activity activity, View view) {
method setTransparentForWindow (line 83) | public static void setTransparentForWindow(Activity activity) {
method setPaddingTop (line 102) | public static void setPaddingTop(Context context, View view) {
method setDarkMode (line 119) | public static void setDarkMode(Activity activity) {
method setLightMode (line 129) | public static void setLightMode(Activity activity) {
method darkMode (line 134) | @TargetApi(Build.VERSION_CODES.M)
method darkModeForM (line 151) | private static void darkModeForM(Window window, boolean dark) {
method setModeForMIUI6 (line 171) | private static void setModeForMIUI6(Window window, boolean dark) {
method setModeForFlyme4 (line 192) | private static void setModeForFlyme4(Window window, boolean dark) {
method isFlyme4 (line 217) | private static boolean isFlyme4() {
method isMIUI6 (line 225) | private static boolean isMIUI6() {
method cipherColor (line 244) | private static int cipherColor(int color, int alpha) {
method setTranslucentView (line 266) | private static void setTranslucentView(ViewGroup viewGroup, int color,...
method setRootView (line 290) | private static void setRootView(Activity activity, boolean fitSystemWi...
method getStatusBarHeight (line 307) | public static int getStatusBarHeight(Context context) {
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/utils/ZXingUtils.java
class ZXingUtils (line 33) | public class ZXingUtils {
method createQRCodeImage (line 61) | public static Bitmap createQRCodeImage(String content) {
method createQRCodeImage (line 65) | public static Bitmap createQRCodeImage(String content, int size) {
method createQRCodeImage (line 69) | public static Bitmap createQRCodeImage(String content, int size, int m...
method createQRCodeImage (line 73) | public static Bitmap createQRCodeImage(String text, Bitmap logo_bitmap) {
method createQRCodeImage (line 77) | public static Bitmap createQRCodeImage(String text, int size, Bitmap l...
method createQRCodeImage (line 82) | public static Bitmap createQRCodeImage(String text, int size, int marg...
method createQRCodeImage (line 98) | public static Bitmap createQRCodeImage(String text, int size, int marg...
method createQRCodeImage (line 115) | public static Bitmap createQRCodeImage(String text, int size, int marg...
method syncDecodeQRCode (line 213) | public static String syncDecodeQRCode(String picturePath) {
method syncDecodeQRCode (line 223) | public static String syncDecodeQRCode(Bitmap bitmap) {
method getDecodeAbleBitmap (line 247) | private static Bitmap getDecodeAbleBitmap(String picturePath) {
method recode (line 271) | public static String recode(String str) {
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/view/ScanActionMenuView.java
class ScanActionMenuView (line 23) | public class ScanActionMenuView extends FrameLayout {
type OnScanActionMenuListener (line 36) | public interface OnScanActionMenuListener {
method onClose (line 37) | void onClose();
method onLight (line 39) | void onLight();
method onPhoto (line 41) | void onPhoto();
method setOnScanActionMenuListener (line 44) | public void setOnScanActionMenuListener(OnScanActionMenuListener onSca...
method ScanActionMenuView (line 49) | public ScanActionMenuView(Context context) {
method ScanActionMenuView (line 53) | public ScanActionMenuView(Context context, AttributeSet attrs) {
method ScanActionMenuView (line 57) | public ScanActionMenuView(Context context, AttributeSet attrs, int def...
method initView (line 62) | private void initView() {
method setScanConfig (line 108) | public void setScanConfig(MNScanConfig config, MNCustomViewBindCallbac...
method openLight (line 137) | public void openLight() {
method closeLight (line 142) | public void closeLight() {
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/view/ScanResultPointView.java
class ScanResultPointView (line 35) | public class ScanResultPointView extends FrameLayout {
method setOnResultPointClickListener (line 53) | public void setOnResultPointClickListener(OnResultPointClickListener o...
type OnResultPointClickListener (line 57) | public interface OnResultPointClickListener {
method onPointClick (line 58) | void onPointClick(String result);
method onCancle (line 60) | void onCancle();
method ScanResultPointView (line 63) | public ScanResultPointView(Context context) {
method ScanResultPointView (line 67) | public ScanResultPointView(Context context, AttributeSet attrs) {
method ScanResultPointView (line 71) | public ScanResultPointView(Context context, AttributeSet attrs, int de...
method initView (line 76) | private void initView() {
method setScanConfig (line 108) | public void setScanConfig(MNScanConfig config) {
method initResultPointConfigs (line 113) | private void initResultPointConfigs() {
method setDatas (line 143) | public void setDatas(List<Barcode> results, Bitmap barcode) {
method removeAllPoints (line 149) | public void removeAllPoints() {
method drawableResultPoint (line 153) | private void drawableResultPoint() {
FILE: mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/view/ViewfinderView.java
class ViewfinderView (line 45) | public final class ViewfinderView extends View {
method ViewfinderView (line 77) | public ViewfinderView(Context context, AttributeSet attrs) {
method initSize (line 106) | private void initSize() {
method setLaserColor (line 124) | public void setLaserColor(int laserColor) {
method setLaserStyle (line 135) | public void setLaserStyle(MNScanConfig.LaserStyle laserStyle) {
method setMaskColor (line 144) | public void setMaskColor(int maskColor) {
method setGridScannerColumn (line 153) | public void setGridScannerColumn(int gridColumn) {
method setGridScannerHeight (line 164) | public void setGridScannerHeight(int gridHeight) {
method setScanConfig (line 169) | public void setScanConfig(MNScanConfig scanConfig) {
method setHintText (line 191) | public void setHintText(String hintMsg, String hintTextColor, int hint...
method onDraw (line 210) | @SuppressLint("DrawAllocation")
method drawLineScanner (line 303) | private void drawLineScanner(Canvas canvas, Rect frame) {
method drawGridScanner (line 322) | private void drawGridScanner(Canvas canvas, Rect frame) {
method shadeColor (line 369) | public int shadeColor(int color) {
method startAnimation (line 375) | public void startAnimation() {
method destroyView (line 404) | public void destroyView() {
Condensed preview — 76 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (252K chars).
[
{
"path": ".gitignore",
"chars": 208,
"preview": "*.iml\n.gradle\n/local.properties\n/.idea/caches\n/.idea/libraries\n/.idea/modules.xml\n/.idea/workspace.xml\n/.idea/navEditor."
},
{
"path": ".idea/codeStyles/Project.xml",
"chars": 3309,
"preview": "<component name=\"ProjectCodeStyleConfiguration\">\n <code_scheme name=\"Project\" version=\"173\">\n <codeStyleSettings lan"
},
{
"path": ".idea/compiler.xml",
"chars": 170,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"CompilerConfiguration\">\n <bytecodeTar"
},
{
"path": ".idea/encodings.xml",
"chars": 191,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"Encoding\" addBOMForNewFiles=\"with NO BOM"
},
{
"path": ".idea/gradle.xml",
"chars": 946,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"GradleMigrationSettings\" migrationVersio"
},
{
"path": ".idea/inspectionProfiles/Project_Default.xml",
"chars": 1444,
"preview": "<component name=\"InspectionProjectProfileManager\">\n <profile version=\"1.0\">\n <option name=\"myName\" value=\"Project De"
},
{
"path": ".idea/jarRepositories.xml",
"chars": 1240,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"RemoteRepositoriesConfiguration\">\n <r"
},
{
"path": ".idea/misc.xml",
"chars": 5981,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"DesignSurface\">\n <option name=\"filePa"
},
{
"path": ".idea/vcs.xml",
"chars": 180,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"VcsDirectoryMappings\">\n <mapping dire"
},
{
"path": "LICENSE",
"chars": 11357,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README.md",
"chars": 7791,
"preview": "# MNMLKitScanner 基于Google MLKit 快速集成二维码扫描,速度比zxing快\n\n## 基于Google MLKit 快速集成二维码扫描,速度比zxing快,可配置相册,闪光灯,相机可以调整焦距放大缩小,自定义"
},
{
"path": "app/.gitignore",
"chars": 6,
"preview": "/build"
},
{
"path": "app/build.gradle",
"chars": 1807,
"preview": "apply plugin: 'com.android.application'\n\ndef versions = rootProject.ext.versions\ndef appId = rootProject.ext.appId\ndef d"
},
{
"path": "app/proguard-rules.pro",
"chars": 750,
"preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
},
{
"path": "app/src/androidTest/java/com/maning/mlkitscanner/ExampleInstrumentedTest.java",
"chars": 760,
"preview": "package com.maning.mlkitscanner;\n\nimport android.content.Context;\n\nimport androidx.test.platform.app.InstrumentationRegi"
},
{
"path": "app/src/main/AndroidManifest.xml",
"chars": 843,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package="
},
{
"path": "app/src/main/java/com/maning/mlkitscanner/demo/CustomConfigActivity.java",
"chars": 15840,
"preview": "package com.maning.mlkitscanner.demo;\n\nimport android.content.Intent;\nimport android.graphics.Color;\nimport android.os.B"
},
{
"path": "app/src/main/java/com/maning/mlkitscanner/demo/MainActivity.java",
"chars": 8770,
"preview": "package com.maning.mlkitscanner.demo;\n\nimport android.Manifest;\nimport android.content.Intent;\nimport android.content.pm"
},
{
"path": "app/src/main/res/anim/activity_anmie_in.xml",
"chars": 515,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:inter"
},
{
"path": "app/src/main/res/anim/activity_anmie_out.xml",
"chars": 515,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:inter"
},
{
"path": "app/src/main/res/drawable/ic_launcher_background.xml",
"chars": 5606,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:wi"
},
{
"path": "app/src/main/res/drawable-v24/ic_launcher_foreground.xml",
"chars": 1702,
"preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:aapt=\"http://schemas.android.com/aapt\"\n "
},
{
"path": "app/src/main/res/layout/activity_custom_config.xml",
"chars": 11041,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ScrollView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:"
},
{
"path": "app/src/main/res/layout/activity_main.xml",
"chars": 5562,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ScrollView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:"
},
{
"path": "app/src/main/res/layout/layout_custom_view.xml",
"chars": 4005,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xm"
},
{
"path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
"chars": 272,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n <b"
},
{
"path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
"chars": 272,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n <b"
},
{
"path": "app/src/main/res/values/array.xml",
"chars": 828,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <string-array name=\"spinarr_error_correction\">\n <item>L </"
},
{
"path": "app/src/main/res/values/colors.xml",
"chars": 207,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <color name=\"colorPrimary\">#6200EE</color>\n <color name=\"color"
},
{
"path": "app/src/main/res/values/strings.xml",
"chars": 69,
"preview": "<resources>\n <string name=\"app_name\">MLKit扫码</string>\n</resources>"
},
{
"path": "app/src/main/res/values/styles.xml",
"chars": 381,
"preview": "<resources>\n <!-- Base application theme. -->\n <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\""
},
{
"path": "app/src/test/java/com/maning/mlkitscanner/ExampleUnitTest.java",
"chars": 384,
"preview": "package com.maning.mlkitscanner;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * Example local unit t"
},
{
"path": "build.gradle",
"chars": 584,
"preview": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\napply from: \"config."
},
{
"path": "config.gradle",
"chars": 1207,
"preview": "/**\n * 全局统一配置\n */\next {\n\n /**\n * 版本统一管理\n */\n versions = [\n versionCode : 101, "
},
{
"path": "gradle/wrapper/gradle-wrapper.properties",
"chars": 232,
"preview": "#Fri Aug 20 09:04:58 CST 2021\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
},
{
"path": "gradle.properties",
"chars": 1071,
"preview": "# Project-wide Gradle settings.\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will ov"
},
{
"path": "gradlew",
"chars": 5296,
"preview": "#!/usr/bin/env sh\n\n##############################################################################\n##\n## Gradle start up"
},
{
"path": "gradlew.bat",
"chars": 2176,
"preview": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem "
},
{
"path": "mlkit-scanner/.gitignore",
"chars": 6,
"preview": "/build"
},
{
"path": "mlkit-scanner/build.gradle",
"chars": 1201,
"preview": "apply plugin: 'com.android.library'\n\ndef versions = rootProject.ext.versions\n\nandroid {\n compileSdkVersion versions.c"
},
{
"path": "mlkit-scanner/consumer-rules.pro",
"chars": 0,
"preview": ""
},
{
"path": "mlkit-scanner/proguard-rules.pro",
"chars": 750,
"preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
},
{
"path": "mlkit-scanner/src/main/AndroidManifest.xml",
"chars": 1054,
"preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package=\"com.maning.mlkitscanner\">\n\n <uses-p"
},
{
"path": "mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/MNScanManager.java",
"chars": 2348,
"preview": "package com.maning.mlkitscanner.scan;\n\nimport android.app.Activity;\nimport android.content.Intent;\n\nimport com.maning.ml"
},
{
"path": "mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/analyser/BarcodeAnalyser.java",
"chars": 5231,
"preview": "package com.maning.mlkitscanner.scan.analyser;\n\nimport android.content.Context;\nimport android.graphics.Bitmap;\nimport a"
},
{
"path": "mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/callback/MNCustomViewBindCallback.java",
"chars": 182,
"preview": "package com.maning.mlkitscanner.scan.callback;\n\nimport android.view.View;\n\n/**\n * 自定义View回调\n */\npublic interface MNCusto"
},
{
"path": "mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/callback/OnCameraAnalyserCallback.java",
"chars": 334,
"preview": "package com.maning.mlkitscanner.scan.callback;\n\nimport android.graphics.Bitmap;\n\n\nimport com.google.mlkit.vision.barcode"
},
{
"path": "mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/callback/act/ActResultRequest.java",
"chars": 1504,
"preview": "package com.maning.mlkitscanner.scan.callback.act;\n\nimport android.app.Activity;\nimport android.app.FragmentManager;\nimp"
},
{
"path": "mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/callback/act/MNScanCallback.java",
"chars": 314,
"preview": "package com.maning.mlkitscanner.scan.callback.act;\n\nimport android.content.Intent;\n\n/**\n * <pre>\n * author : maning\n"
},
{
"path": "mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/callback/act/OnActResultEventDispatcherFragment.java",
"chars": 1240,
"preview": "package com.maning.mlkitscanner.scan.callback.act;\n\nimport android.app.Fragment;\nimport android.content.Intent;\nimport a"
},
{
"path": "mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/camera/CameraManager.java",
"chars": 8646,
"preview": "package com.maning.mlkitscanner.scan.camera;\n\nimport android.content.Context;\nimport android.graphics.Bitmap;\nimport and"
},
{
"path": "mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/camera/CameraSizeUtils.java",
"chars": 1479,
"preview": "package com.maning.mlkitscanner.scan.camera;\n\nimport android.content.Context;\nimport android.util.DisplayMetrics;\nimport"
},
{
"path": "mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/model/MNScanConfig.java",
"chars": 11316,
"preview": "package com.maning.mlkitscanner.scan.model;\n\n\nimport com.maning.mlkitscanner.R;\nimport com.maning.mlkitscanner.scan.call"
},
{
"path": "mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/ui/ScanPreviewActivity.java",
"chars": 15112,
"preview": "package com.maning.mlkitscanner.scan.ui;\n\nimport android.Manifest;\nimport android.content.Context;\nimport android.conten"
},
{
"path": "mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/utils/AmbientLightManager.java",
"chars": 4329,
"preview": "/*\n * Copyright (C) Jenly, MLKit Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
},
{
"path": "mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/utils/BeepManager.java",
"chars": 3168,
"preview": "/*\n * Copyright (C) Jenly, MLKit Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
},
{
"path": "mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/utils/CommonUtils.java",
"chars": 2296,
"preview": "package com.maning.mlkitscanner.scan.utils;\n\nimport android.content.Context;\nimport android.graphics.Paint;\nimport andro"
},
{
"path": "mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/utils/ImageUtils.java",
"chars": 4926,
"preview": "/*\n * Copyright (C) Jenly, MLKit Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
},
{
"path": "mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/utils/StatusBarUtil.java",
"chars": 11204,
"preview": "package com.maning.mlkitscanner.scan.utils;\n\nimport android.annotation.TargetApi;\nimport android.app.Activity;\nimport an"
},
{
"path": "mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/utils/ZXingUtils.java",
"chars": 10980,
"preview": "package com.maning.mlkitscanner.scan.utils;\n\nimport android.graphics.Bitmap;\nimport android.graphics.BitmapFactory;\nimpo"
},
{
"path": "mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/view/ScanActionMenuView.java",
"chars": 4663,
"preview": "package com.maning.mlkitscanner.scan.view;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\nimport and"
},
{
"path": "mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/view/ScanResultPointView.java",
"chars": 9065,
"preview": "package com.maning.mlkitscanner.scan.view;\n\nimport android.content.Context;\nimport android.graphics.Bitmap;\nimport andro"
},
{
"path": "mlkit-scanner/src/main/java/com/maning/mlkitscanner/scan/view/ViewfinderView.java",
"chars": 14492,
"preview": "/*\n * Copyright (C) 2008 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may "
},
{
"path": "mlkit-scanner/src/main/res/anim/mn_scan_activity_bottom_in.xml",
"chars": 356,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:durat"
},
{
"path": "mlkit-scanner/src/main/res/anim/mn_scan_activity_bottom_out.xml",
"chars": 331,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n <alpha\n "
},
{
"path": "mlkit-scanner/src/main/res/drawable/mn_scan_result_point_default.xml",
"chars": 472,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:sha"
},
{
"path": "mlkit-scanner/src/main/res/layout/mn_scan_action_menu.xml",
"chars": 3395,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--LoadingDialog-->\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/re"
},
{
"path": "mlkit-scanner/src/main/res/layout/mn_scan_activity_scan_preview.xml",
"chars": 1667,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xm"
},
{
"path": "mlkit-scanner/src/main/res/layout/mn_scan_result_point_item_view.xml",
"chars": 807,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xm"
},
{
"path": "mlkit-scanner/src/main/res/layout/mn_scan_result_point_view.xml",
"chars": 1562,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xm"
},
{
"path": "mlkit-scanner/src/main/res/values/colors.xml",
"chars": 339,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <color name=\"mn_scan_viewfinder_laser\">#FFff3535</color>\n <col"
},
{
"path": "mlkit-scanner/src/main/res/values/styles.xml",
"chars": 1310,
"preview": "<resources>\n\n <style name=\"MNScanAnimation\">\n <item name=\"android:activityOpenEnterAnimation\">@null</item>\n "
},
{
"path": "settings.gradle",
"chars": 75,
"preview": "include ':mlkit-scanner'\ninclude ':app'\nrootProject.name = \"MNMLKitScanner\""
}
]
// ... and 3 more files (download for full content)
About this extraction
This page contains the full source code of the maning0303/MNMLKitScanner GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 76 files (224.3 KB), approximately 55.5k tokens, and a symbol index with 260 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.