33 Commits

Author SHA1 Message Date
Jenly
c0d7192ba9 Update README 2020-12-29 15:02:23 +08:00
Jenly
2878dc8069 Update README 2020-12-24 18:09:56 +08:00
Jenly
4458ea747d Update README 2020-04-28 22:32:28 +08:00
Jenly
fa8c2166c7 fix #86 2020-04-28 22:02:24 +08:00
Jenly
f7bc5d2d01 优化细节 2020-04-28 22:01:23 +08:00
Jenly
a9c04fb310 统一日志管理 2020-04-27 21:14:05 +08:00
Jenly
aba5fcadf2 Update APK 2020-03-29 17:25:14 +08:00
Jenly
888687e06a fix#81 2020-03-29 17:01:42 +08:00
jenly1314
5c16340d78 Update README 2019-12-30 09:20:59 +08:00
jenly1314
f521b9e057 发布v1.1.6 2019-12-27 17:57:22 +08:00
jenly1314
56f3fed338 支持识别反色码(#66,#72) 2019-12-27 16:41:14 +08:00
jenly1314
72378b0a6d 生成条形码/二维码支持自定义颜色 (#73) 2019-12-27 14:49:14 +08:00
jenly1314
f1d16dceae Update README 2019-12-17 09:12:39 +08:00
jenly1314
69fef8f69f 优化Camera初始化相关策略,减少出现卡顿的可能性(#64,#65) 2019-12-16 11:35:57 +08:00
jenly1314
c7dbf12f57 优化细节 2019-12-05 09:54:12 +08:00
jenly1314
ef9344d77d Update README 2019-11-28 15:50:47 +08:00
jenly1314
7f8ab364b5 增加混淆规则 2019-11-25 10:53:53 +08:00
jenly1314
7096f1edd9 Update README 2019-11-19 15:21:14 +08:00
jenly1314
572096da10 Update README 2019-11-18 11:48:36 +08:00
jenly1314
c1c70bec5b Update README 2019-11-18 11:10:55 +08:00
jenly1314
154fe31526 Update README 2019-11-18 09:46:58 +08:00
jenly1314
c9b74fd707 * 内置手电筒按钮,当光线太暗时,自动显示手电筒 fix(#58)
*  生成二维码时Logo支持自定义大小 fix(#62)
2019-11-15 18:22:48 +08:00
jenly1314
39f13c3c3f 1、支持真实识别区域比例和识别区域偏移量可配置
2、对外暴露更多可配置参数
2019-09-24 11:04:36 +08:00
jenly1314
3465b76e96 CI 2019-08-23 09:33:17 +08:00
jenly1314
7db08d87d8 CI 2019-07-01 15:52:14 +08:00
jenly1314
9479cad482 CI 2019-07-01 15:44:32 +08:00
jenly1314
913af19017 CI 2019-07-01 15:43:17 +08:00
jenly1314
3e8f612e9f 支持AndroidX对应版本 2019-06-27 17:09:10 +08:00
jenly1314
10554f1a9f 支持AndroidX对应版本 2019-06-27 14:44:37 +08:00
jenly1314
d16a02d768 支持AndroidX对应版本 2019-06-27 14:39:34 +08:00
jenly1314
a69485d2ef 支持AndroidX对应版本 2019-06-27 14:33:40 +08:00
jenly1314
ab26e53c09 支持AndroidX对应版本 2019-06-27 14:09:26 +08:00
jenly1314
5b4c15db1f 支持AndroidX对应版本 2019-06-27 14:08:41 +08:00
61 changed files with 1667 additions and 1271 deletions

27
.circleci/config.yml Normal file
View File

@@ -0,0 +1,27 @@
version: 2
jobs:
build:
working_directory: ~/code
docker:
- image: circleci/android:api-28
environment:
JVM_OPTS: -Xmx3200m
steps:
- checkout
- restore_cache:
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
- run:
name: Download Dependencies
command: ./gradlew androidDependencies
- save_cache:
paths:
- ~/.gradle
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
- run:
name: Run Tests
command: ./gradlew lint test
- store_artifacts:
path: app/build/reports
destination: reports
- store_test_results:
path: app/build/test-results

4
.gitignore vendored
View File

@@ -1,9 +1,7 @@
*.iml
.gradle
/local.properties
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea
.DS_Store
/build
/captures

View File

@@ -1,57 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="WizardSettings">
<option name="children">
<map>
<entry key="imageWizard">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="imageAssetPanel">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="launcher">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="foregroundImage">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="scalingPercent" value="46" />
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
<option name="values">
<map>
<entry key="backgroundAssetType" value="COLOR" />
<entry key="backgroundColor" value="1fb3e2" />
<entry key="foregroundImage" value="C:\code_icon(1).png" />
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
</component>
</project>

Binary file not shown.

View File

@@ -1,52 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<DBN-PSQL>
<case-options enabled="true">
<option name="KEYWORD_CASE" value="lower" />
<option name="FUNCTION_CASE" value="lower" />
<option name="PARAMETER_CASE" value="lower" />
<option name="DATATYPE_CASE" value="lower" />
<option name="OBJECT_CASE" value="preserve" />
</case-options>
<formatting-settings enabled="false" />
</DBN-PSQL>
<DBN-SQL>
<case-options enabled="true">
<option name="KEYWORD_CASE" value="lower" />
<option name="FUNCTION_CASE" value="lower" />
<option name="PARAMETER_CASE" value="lower" />
<option name="DATATYPE_CASE" value="lower" />
<option name="OBJECT_CASE" value="preserve" />
</case-options>
<formatting-settings enabled="false">
<option name="STATEMENT_SPACING" value="one_line" />
<option name="CLAUSE_CHOP_DOWN" value="chop_down_if_statement_long" />
<option name="ITERATION_ELEMENTS_WRAPPING" value="chop_down_if_not_single" />
</formatting-settings>
</DBN-SQL>
<DBN-PSQL>
<case-options enabled="true">
<option name="KEYWORD_CASE" value="lower" />
<option name="FUNCTION_CASE" value="lower" />
<option name="PARAMETER_CASE" value="lower" />
<option name="DATATYPE_CASE" value="lower" />
<option name="OBJECT_CASE" value="preserve" />
</case-options>
<formatting-settings enabled="false" />
</DBN-PSQL>
<DBN-SQL>
<case-options enabled="true">
<option name="KEYWORD_CASE" value="lower" />
<option name="FUNCTION_CASE" value="lower" />
<option name="PARAMETER_CASE" value="lower" />
<option name="DATATYPE_CASE" value="lower" />
<option name="OBJECT_CASE" value="preserve" />
</case-options>
<formatting-settings enabled="false">
<option name="STATEMENT_SPACING" value="one_line" />
<option name="CLAUSE_CHOP_DOWN" value="chop_down_if_statement_long" />
<option name="ITERATION_ELEMENTS_WRAPPING" value="chop_down_if_not_single" />
</formatting-settings>
</DBN-SQL>
</code_scheme>
</component>

456
.idea/dbnavigator.xml generated
View File

@@ -1,456 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DBNavigator.Project.DataEditorManager">
<record-view-column-sorting-type value="BY_INDEX" />
<value-preview-text-wrapping value="true" />
<value-preview-pinned value="false" />
</component>
<component name="DBNavigator.Project.DataExportManager">
<export-instructions>
<create-header value="true" />
<quote-values-containing-separator value="true" />
<quote-all-values value="false" />
<value-separator value="" />
<file-name value="" />
<file-location value="" />
<scope value="GLOBAL" />
<destination value="FILE" />
<format value="EXCEL" />
<charset value="GBK" />
</export-instructions>
</component>
<component name="DBNavigator.Project.DatabaseBrowserManager">
<autoscroll-to-editor value="false" />
<autoscroll-from-editor value="true" />
<show-object-properties value="true" />
<loaded-nodes />
</component>
<component name="DBNavigator.Project.DatabaseFileManager">
<open-files />
</component>
<component name="DBNavigator.Project.EditorStateManager">
<last-used-providers />
</component>
<component name="DBNavigator.Project.MethodExecutionManager">
<method-browser />
<execution-history>
<group-entries value="true" />
<execution-inputs />
</execution-history>
<argument-values-cache />
</component>
<component name="DBNavigator.Project.ObjectDependencyManager">
<last-used-dependency-type value="INCOMING" />
</component>
<component name="DBNavigator.Project.ObjectQuickFilterManager">
<last-used-operator value="EQUAL" />
<filters />
</component>
<component name="DBNavigator.Project.ScriptExecutionManager" clear-outputs="true">
<recently-used-interfaces />
</component>
<component name="DBNavigator.Project.Settings">
<connections />
<browser-settings>
<general>
<display-mode value="TABBED" />
<navigation-history-size value="100" />
<show-object-details value="false" />
</general>
<filters>
<object-type-filter>
<object-type name="SCHEMA" enabled="true" />
<object-type name="USER" enabled="true" />
<object-type name="ROLE" enabled="true" />
<object-type name="PRIVILEGE" enabled="true" />
<object-type name="CHARSET" enabled="true" />
<object-type name="TABLE" enabled="true" />
<object-type name="VIEW" enabled="true" />
<object-type name="MATERIALIZED_VIEW" enabled="true" />
<object-type name="NESTED_TABLE" enabled="true" />
<object-type name="COLUMN" enabled="true" />
<object-type name="INDEX" enabled="true" />
<object-type name="CONSTRAINT" enabled="true" />
<object-type name="DATASET_TRIGGER" enabled="true" />
<object-type name="DATABASE_TRIGGER" enabled="true" />
<object-type name="SYNONYM" enabled="true" />
<object-type name="SEQUENCE" enabled="true" />
<object-type name="PROCEDURE" enabled="true" />
<object-type name="FUNCTION" enabled="true" />
<object-type name="PACKAGE" enabled="true" />
<object-type name="TYPE" enabled="true" />
<object-type name="TYPE_ATTRIBUTE" enabled="true" />
<object-type name="ARGUMENT" enabled="true" />
<object-type name="DIMENSION" enabled="true" />
<object-type name="CLUSTER" enabled="true" />
<object-type name="DBLINK" enabled="true" />
</object-type-filter>
</filters>
<sorting>
<object-type name="COLUMN" sorting-type="NAME" />
<object-type name="FUNCTION" sorting-type="NAME" />
<object-type name="PROCEDURE" sorting-type="NAME" />
<object-type name="ARGUMENT" sorting-type="POSITION" />
</sorting>
<default-editors>
<object-type name="VIEW" editor-type="SELECTION" />
<object-type name="PACKAGE" editor-type="SELECTION" />
<object-type name="TYPE" editor-type="SELECTION" />
</default-editors>
</browser-settings>
<navigation-settings>
<lookup-filters>
<lookup-objects>
<object-type name="SCHEMA" enabled="true" />
<object-type name="USER" enabled="false" />
<object-type name="ROLE" enabled="false" />
<object-type name="PRIVILEGE" enabled="false" />
<object-type name="CHARSET" enabled="false" />
<object-type name="TABLE" enabled="true" />
<object-type name="VIEW" enabled="true" />
<object-type name="MATERIALIZED VIEW" enabled="true" />
<object-type name="NESTED TABLE" enabled="false" />
<object-type name="COLUMN" enabled="false" />
<object-type name="INDEX" enabled="true" />
<object-type name="CONSTRAINT" enabled="true" />
<object-type name="DATASET TRIGGER" enabled="true" />
<object-type name="DATABASE TRIGGER" enabled="true" />
<object-type name="SYNONYM" enabled="false" />
<object-type name="SEQUENCE" enabled="true" />
<object-type name="PROCEDURE" enabled="true" />
<object-type name="FUNCTION" enabled="true" />
<object-type name="PACKAGE" enabled="true" />
<object-type name="TYPE" enabled="true" />
<object-type name="TYPE ATTRIBUTE" enabled="false" />
<object-type name="ARGUMENT" enabled="false" />
<object-type name="DIMENSION" enabled="false" />
<object-type name="CLUSTER" enabled="false" />
<object-type name="DBLINK" enabled="true" />
</lookup-objects>
<force-database-load value="false" />
<prompt-connection-selection value="true" />
<prompt-schema-selection value="true" />
</lookup-filters>
</navigation-settings>
<dataset-grid-settings>
<general>
<enable-zooming value="true" />
<enable-column-tooltip value="true" />
</general>
<sorting>
<nulls-first value="true" />
<max-sorting-columns value="4" />
</sorting>
<tracking-columns>
<columnNames value="" />
<visible value="true" />
<editable value="false" />
</tracking-columns>
</dataset-grid-settings>
<dataset-editor-settings>
<text-editor-popup>
<active value="false" />
<active-if-empty value="false" />
<data-length-threshold value="100" />
<popup-delay value="1000" />
</text-editor-popup>
<values-actions-popup>
<show-popup-button value="true" />
<element-count-threshold value="1000" />
<data-length-threshold value="250" />
</values-actions-popup>
<general>
<fetch-block-size value="100" />
<fetch-timeout value="30" />
<trim-whitespaces value="true" />
<convert-empty-strings-to-null value="true" />
<select-content-on-cell-edit value="true" />
<large-value-preview-active value="true" />
</general>
<filters>
<prompt-filter-dialog value="true" />
<default-filter-type value="BASIC" />
</filters>
<qualified-text-editor text-length-threshold="300">
<content-types>
<content-type name="Text" enabled="true" />
<content-type name="Properties" enabled="true" />
<content-type name="XML" enabled="true" />
<content-type name="DTD" enabled="true" />
<content-type name="HTML" enabled="true" />
<content-type name="XHTML" enabled="true" />
<content-type name="Java" enabled="true" />
<content-type name="SQL" enabled="true" />
<content-type name="PL/SQL" enabled="true" />
<content-type name="Groovy" enabled="true" />
<content-type name="AIDL" enabled="true" />
<content-type name="YAML" enabled="true" />
<content-type name="Manifest" enabled="true" />
</content-types>
</qualified-text-editor>
<record-navigation>
<navigation-target value="VIEWER" />
</record-navigation>
</dataset-editor-settings>
<code-editor-settings>
<general>
<show-object-navigation-gutter value="false" />
<show-spec-declaration-navigation-gutter value="true" />
<enable-spellchecking value="true" />
<enable-reference-spellchecking value="false" />
</general>
<confirmations>
<save-changes value="false" />
<revert-changes value="true" />
</confirmations>
</code-editor-settings>
<code-completion-settings>
<filters>
<basic-filter>
<filter-element type="RESERVED_WORD" id="keyword" selected="true" />
<filter-element type="RESERVED_WORD" id="function" selected="true" />
<filter-element type="RESERVED_WORD" id="parameter" selected="true" />
<filter-element type="RESERVED_WORD" id="datatype" selected="true" />
<filter-element type="RESERVED_WORD" id="exception" selected="true" />
<filter-element type="OBJECT" id="schema" selected="true" />
<filter-element type="OBJECT" id="role" selected="true" />
<filter-element type="OBJECT" id="user" selected="true" />
<filter-element type="OBJECT" id="privilege" selected="true" />
<user-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="false" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</user-schema>
<public-schema>
<filter-element type="OBJECT" id="table" selected="false" />
<filter-element type="OBJECT" id="view" selected="false" />
<filter-element type="OBJECT" id="materialized view" selected="false" />
<filter-element type="OBJECT" id="index" selected="false" />
<filter-element type="OBJECT" id="constraint" selected="false" />
<filter-element type="OBJECT" id="trigger" selected="false" />
<filter-element type="OBJECT" id="synonym" selected="false" />
<filter-element type="OBJECT" id="sequence" selected="false" />
<filter-element type="OBJECT" id="procedure" selected="false" />
<filter-element type="OBJECT" id="function" selected="false" />
<filter-element type="OBJECT" id="package" selected="false" />
<filter-element type="OBJECT" id="type" selected="false" />
<filter-element type="OBJECT" id="dimension" selected="false" />
<filter-element type="OBJECT" id="cluster" selected="false" />
<filter-element type="OBJECT" id="dblink" selected="false" />
</public-schema>
<any-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</any-schema>
</basic-filter>
<extended-filter>
<filter-element type="RESERVED_WORD" id="keyword" selected="true" />
<filter-element type="RESERVED_WORD" id="function" selected="true" />
<filter-element type="RESERVED_WORD" id="parameter" selected="true" />
<filter-element type="RESERVED_WORD" id="datatype" selected="true" />
<filter-element type="RESERVED_WORD" id="exception" selected="true" />
<filter-element type="OBJECT" id="schema" selected="true" />
<filter-element type="OBJECT" id="user" selected="true" />
<filter-element type="OBJECT" id="role" selected="true" />
<filter-element type="OBJECT" id="privilege" selected="true" />
<user-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</user-schema>
<public-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</public-schema>
<any-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</any-schema>
</extended-filter>
</filters>
<sorting enabled="true">
<sorting-element type="RESERVED_WORD" id="keyword" />
<sorting-element type="RESERVED_WORD" id="datatype" />
<sorting-element type="OBJECT" id="column" />
<sorting-element type="OBJECT" id="table" />
<sorting-element type="OBJECT" id="view" />
<sorting-element type="OBJECT" id="materialized view" />
<sorting-element type="OBJECT" id="index" />
<sorting-element type="OBJECT" id="constraint" />
<sorting-element type="OBJECT" id="trigger" />
<sorting-element type="OBJECT" id="synonym" />
<sorting-element type="OBJECT" id="sequence" />
<sorting-element type="OBJECT" id="procedure" />
<sorting-element type="OBJECT" id="function" />
<sorting-element type="OBJECT" id="package" />
<sorting-element type="OBJECT" id="type" />
<sorting-element type="OBJECT" id="dimension" />
<sorting-element type="OBJECT" id="cluster" />
<sorting-element type="OBJECT" id="dblink" />
<sorting-element type="OBJECT" id="schema" />
<sorting-element type="OBJECT" id="role" />
<sorting-element type="OBJECT" id="user" />
<sorting-element type="RESERVED_WORD" id="function" />
<sorting-element type="RESERVED_WORD" id="parameter" />
</sorting>
<format>
<enforce-code-style-case value="true" />
</format>
</code-completion-settings>
<execution-engine-settings>
<statement-execution>
<fetch-block-size value="100" />
<execution-timeout value="20" />
<debug-execution-timeout value="600" />
<focus-result value="false" />
<prompt-execution value="false" />
</statement-execution>
<script-execution>
<command-line-interfaces />
<execution-timeout value="300" />
</script-execution>
<method-execution>
<execution-timeout value="30" />
<debug-execution-timeout value="600" />
<parameter-history-size value="10" />
</method-execution>
</execution-engine-settings>
<operation-settings>
<transactions>
<uncommitted-changes>
<on-project-close value="ASK" />
<on-disconnect value="ASK" />
<on-autocommit-toggle value="ASK" />
</uncommitted-changes>
<multiple-uncommitted-changes>
<on-commit value="ASK" />
<on-rollback value="ASK" />
</multiple-uncommitted-changes>
</transactions>
<session-browser>
<disconnect-session value="ASK" />
<kill-session value="ASK" />
<reload-on-filter-change value="false" />
</session-browser>
<compiler>
<compile-type value="KEEP" />
<compile-dependencies value="ASK" />
<always-show-controls value="false" />
</compiler>
<debugger>
<debugger-type value="ASK" />
<use-generic-runners value="true" />
</debugger>
</operation-settings>
<ddl-file-settings>
<extensions>
<mapping file-type-id="VIEW" extensions="vw" />
<mapping file-type-id="TRIGGER" extensions="trg" />
<mapping file-type-id="PROCEDURE" extensions="prc" />
<mapping file-type-id="FUNCTION" extensions="fnc" />
<mapping file-type-id="PACKAGE" extensions="pkg" />
<mapping file-type-id="PACKAGE_SPEC" extensions="pks" />
<mapping file-type-id="PACKAGE_BODY" extensions="pkb" />
<mapping file-type-id="TYPE" extensions="tpe" />
<mapping file-type-id="TYPE_SPEC" extensions="tps" />
<mapping file-type-id="TYPE_BODY" extensions="tpb" />
</extensions>
<general>
<lookup-ddl-files value="true" />
<create-ddl-files value="false" />
<synchronize-ddl-files value="true" />
<use-qualified-names value="false" />
<make-scripts-rerunnable value="true" />
</general>
</ddl-file-settings>
<general-settings>
<regional-settings>
<date-format value="MEDIUM" />
<number-format value="UNGROUPED" />
<locale value="SYSTEM_DEFAULT" />
<use-custom-formats value="false" />
</regional-settings>
<environment>
<environment-types>
<environment-type id="development" name="Development" description="Development environment" color="-2430209/-12296320" readonly-code="false" readonly-data="false" />
<environment-type id="integration" name="Integration" description="Integration environment" color="-2621494/-12163514" readonly-code="true" readonly-data="false" />
<environment-type id="production" name="Production" description="Productive environment" color="-11574/-10271420" readonly-code="true" readonly-data="true" />
<environment-type id="other" name="Other" description="" color="-1576/-10724543" readonly-code="false" readonly-data="false" />
</environment-types>
<visibility-settings>
<connection-tabs value="true" />
<dialog-headers value="true" />
<object-editor-tabs value="true" />
<script-editor-tabs value="false" />
<execution-result-tabs value="true" />
</visibility-settings>
</environment>
</general-settings>
</component>
<component name="DBNavigator.Project.StatementExecutionManager">
<execution-variables />
</component>
</project>

6
.idea/encodings.xml generated
View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" native2AsciiForPropertiesFiles="true" defaultCharsetForPropertiesFiles="UTF-8" addBOMForNewFiles="with NO BOM">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>

19
.idea/gradle.xml generated
View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
<option value="$PROJECT_DIR$/lib" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>

View File

@@ -1,78 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<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="true" 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="0" 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="true" />
</PegdownExtensions>
<ParserOptions>
<option name="ADMONITION_EXT" value="false" />
<option name="ATTRIBUTES_EXT" value="false" />
<option name="COMMONMARK_LISTS" value="false" />
<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="true" />
<option name="GFM_TABLE_RENDERING" value="true" />
<option name="GITBOOK_URL_ENCODING" value="false" />
<option name="GITHUB_LISTS" value="true" />
<option name="GITHUB_WIKI_LINKS" value="true" />
<option name="HEADER_ID_NO_DUPED_DASHES" value="false" />
<option name="JEKYLL_FRONT_MATTER" value="false" />
<option name="NO_TEXT_ATTRIBUTES" value="false" />
<option name="PARSE_HTML_ANCHOR_ID" 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">
<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="false" 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="$ProjectFileDir$" targetDir="$ProjectFileDir$" cssDir="" scriptDir="" plainHtml="false" imageDir="" copyLinkedImages="false" imageUniquifyType="0" targetExt="" useTargetExt="false" noCssNoScripts="false" linkToExportedHtml="true" exportOnSettingsChange="true" regenerateOnProjectOpen="false" linkFormatType="HTTP_ABSOLUTE" />
<LinkMapSettings>
<textMaps />
</LinkMapSettings>
</component>
</project>

View File

@@ -1,3 +0,0 @@
<component name="MarkdownNavigator.ProfileManager">
<settings default="" pdf-export="" plain-text-search-scope="Project Files" />
</component>

44
.idea/misc.xml generated
View File

@@ -1,44 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="10">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
<item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
<item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="9">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
<item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
<item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
</list>
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" 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>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>

6
.idea/vcs.xml generated
View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

117
README.md
View File

@@ -3,16 +3,21 @@
![Image](app/src/main/ic_launcher-web.png)
[![Download](https://img.shields.io/badge/download-App-blue.svg)](https://raw.githubusercontent.com/jenly1314/ZXingLite/master/app/release/app-release.apk)
[![Jitpack](https://jitpack.io/v/jenly1314/ZXingLite.svg)](https://jitpack.io/#jenly1314/ZXingLite)
[![JCenter](https://img.shields.io/badge/JCenter-1.1.9-46C018.svg)](https://bintray.com/beta/#/jenly/maven/zxing-lite)
[![JitPack](https://jitpack.io/v/jenly1314/ZXingLite.svg)](https://jitpack.io/#jenly1314/ZXingLite)
[![CI](https://travis-ci.org/jenly1314/ZXingLite.svg?branch=master)](https://travis-ci.org/jenly1314/ZXingLite)
[![CircleCI](https://circleci.com/gh/jenly1314/ZXingLite.svg?style=svg)](https://circleci.com/gh/jenly1314/ZXingLite)
[![API](https://img.shields.io/badge/API-16%2B-blue.svg?style=flat)](https://android-arsenal.com/api?level=16)
[![License](https://img.shields.io/badge/license-Apche%202.0-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0)
[![Blog](https://img.shields.io/badge/blog-Jenly-9933CC.svg)](http://blog.csdn.net/jenly121)
[![QQGroup](https://img.shields.io/badge/QQGroup-20867961-blue.svg)](http://shang.qq.com/wpa/qunwpa?idkey=8fcc6a2f88552ea44b1411582c94fd124f7bb3ec227e2a400dbbfaad3dc2f5ad)
[![Blog](https://img.shields.io/badge/blog-Jenly-9933CC.svg)](https://jenly1314.github.io/)
[![QQGroup](https://img.shields.io/badge/QQGroup-20867961-blue.svg)](http://shang.qq.com/wpa/qunwpa?idkey=8fcc6a2f88552ea44b1.1.982c94fd124f7bb3ec227e2a400dbbfaad3dc2f5ad)
ZXingLite for Android 是ZXing的精简版基于ZXing库优化扫码和生成二维码/条形码功能,扫码界面完全支持自定义,也可一行代码使用默认实现的扫码功能。总之你想要的都在这里。
>简单如斯,你不试试? Come on~
### [AndroidX version](https://github.com/jenly1314/ZXingLite/tree/androidx)
## Gif 展示
![Image](GIF.gif)
@@ -36,6 +41,13 @@ ZXingLite for Android 是ZXing的精简版基于ZXing库优化扫码和生成
| laserStyle | enum | line | 扫描激光的样式 |
| gridColumn | integer | 20 | 网格扫描激光列数 |
| gridHeight | integer | 40dp | 网格扫描激光高度为0dp时表示动态铺满 |
| cornerRectWidth | dimension | 4dp | 扫描区边角的宽 |
| cornerRectHeight | dimension | 16dp | 扫描区边角的高 |
| scannerLineMoveDistance | dimension | 2dp | 扫描线每次移动距离 |
| scannerLineHeight | dimension | 5dp | 扫描线高度 |
| frameLineWidth | dimension | 1dp | 边框线宽度 |
| scannerAnimationDelay | integer | 15 | 扫描动画延迟间隔时间,单位:毫秒 |
| frameRatio | float | 0.625f | 扫码框与屏幕占比 |
## 引入
@@ -45,17 +57,21 @@ ZXingLite for Android 是ZXing的精简版基于ZXing库优化扫码和生成
<dependency>
<groupId>com.king.zxing</groupId>
<artifactId>zxing-lite</artifactId>
<version>1.1.2</version>
<version>1.1.9</version>
<type>pom</type>
</dependency>
```
### Gradle:
```gradle
implementation 'com.king.zxing:zxing-lite:1.1.2'
//AndroidX 版本
implementation 'com.king.zxing:zxing-lite:1.1.9-androidx'
//Android 版本
implementation 'com.king.zxing:zxing-lite:1.1.9'
```
### Lvy:
```lvy
<dependency org='com.king.zxing' name='zxing-lite' rev='1.1.2'>
<dependency org='com.king.zxing' name='zxing-lite' rev='1.1.9'>
<artifact name='$AID' ext='pom'></artifact>
</dependency>
```
@@ -71,13 +87,24 @@ allprojects {
## 引入的库:
```gradle
compileOnly 'com.android.support:appcompat-v7:28.0.0'
//AndroidX
api 'androidx.appcompat:appcompat:1.1.0'
api 'com.google.zxing:core:3.3.3'
//Android
api 'com.android.support:appcompat-v7:28.0.0'
api 'com.google.zxing:core:3.3.3'
```
## 示例
布局示例 可自定义布局布局内至少要保证有SurfaceView和ViewfinderView控件id可根据重写CaptureActivity 的 getPreviewViewId 和 getViewFinderViewId方法自定义
布局示例
> 可自定义布局覆写getLayoutId方法布局内至少要保证有SurfaceView和ViewfinderView控件id可根据覆写CaptureActivity 的 getSurfaceViewId 和 getViewfinderViewId方法自定义
> ivTorch为 v1.1.4版本新增的手电筒按钮如果想改ID可通过CaptureActivity中的getIvTorchId自定义ID
> 如果是从v1.1.4以前版本升级至v1.1.4以上版本请参考如下布局示例新增ivTorch也可忽略内置手电筒功能可直接将CaptureActivity中的getIvTorchId方法返回0
```Xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
@@ -91,10 +118,22 @@ api 'com.google.zxing:core:3.3.3'
android:id="@+id/viewfinderView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<ImageView
android:id="@+id/ivTorch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/zxl_torch_selector"
android:layout_marginTop="@dimen/torchMarginTop" />
</FrameLayout>
```
或在你的布局中添加
```Xml
<include layout="@layout/zxl_capture"/>
```
代码示例 (二维码/条形码)
```Java
//跳转的默认扫码界面
@@ -104,36 +143,80 @@ api 'com.google.zxing:core:3.3.3'
CodeUtils.createQRCode(content,600,logo);
//生成条形码
CodeUtils.createBarCode(content, BarcodeFormat.CODE_128,800,200);
//解析条形码/二维码
CodeUtils.parseCode(bitmapPath);
//解析二维码
CodeUtils.parseQRCode(bitmapPath);
```
如果直接使用CaptureActivity需在您项目的AndroidManifest中添加如下配置
```Xml
<activity
android:name="com.king.zxing.CaptureActivity"
android:screenOrientation="portrait"/>
android:screenOrientation="portrait"
android:theme="@style/CaptureTheme"/>
```
### 快速实现扫码有以下几种方式:
> 1、直接使用CaptureActivity或者CaptureFragment。(纯洁的扫码,无任何添加剂)
> 2、通过继承CaptureActivity或者CaptureFragment并自定义布局。适用于大多场景并无需关心扫码相关逻辑
> 2、通过继承CaptureActivity或者CaptureFragment并自定义布局。适用于大多场景并无需关心扫码相关逻辑自定义布局时需覆写getLayoutId方法
> 3、在你项目的Activity或者Fragment中创建创建一个CaptureHelper并在相应的生命周期中调用CaptureHelper的周期。适用于想在扫码界面写交互逻辑又因为项目架构或其它原因无法直接或间接继承CaptureActivity或CaptureFragment时使用
> 3、在你项目的Activity或者Fragment中创建一个CaptureHelper并在相应的生命周期中调用CaptureHelper的周期。适用于想在扫码界面写交互逻辑又因为项目架构或其它原因无法直接或间接继承CaptureActivity或CaptureFragment时使用
> 4、参照CaptureHelper写一个自定义的扫码帮助类其它步骤同方式3。扩展高级用法谨慎使用
### 其他
更多使用详情,请查看[app](app)中的源码使用示例或直接查看[API帮助文档](https://jenly1314.github.io/projects/ZXingLite/doc/)
需使用JDK8+编译在你项目中的build.gradle的android{}中添加配置:
```gradle
compileOptions {
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_1_8
}
```
更多使用详情,请查看[app](app)中的源码使用示例或直接查看[API帮助文档](https://jenly1314.github.io/projects/ZXingLite/1.x/doc/)
## 版本记录
#### v1.1.92020-4-28
* 修复1.1.8版本优化细节时不小心改出个Bug(fix #86)
#### v1.1.82020-4-27
* 统一日志管理
* 优化细节
#### v1.1.72020-3-29
* 优化一些默认参数配置
* 修复扫码界面开启闪光灯并切到后台时手电筒按钮状态未同步问题fix #81
#### v1.1.62019-12-27
* 生成条形码/二维码时支持自定义配置颜色
* 支持识别反色码增强识别率默认不支持需通过CaptureHelper.supportLuminanceInvert(true)开启)
#### v1.1.52019-12-16
* 优化Camera初始化相关策略减少出现卡顿的可能性
#### v1.1.42019-11-18
* 内置手电筒按钮,当光线太暗时,自动显示手电筒 (fix #58)
* 生成二维码时Logo支持自定义大小 (fix #62)
#### v1.1.32019-9-24
* 支持真实识别区域比例和识别区域偏移量可配置
* 对外暴露更多可配置参数
#### v1.1.22019-6-27
* 优化部分细节为迁移至AndroidX做准备
* 支持AndroidX对应版本
#### v1.1.12019-5-20
* 支持扫二维码过小时,自动缩放
* 支持垂直条形码识别增强条形码识别默认不支持需CaptureHelper.supportVerticalCode(true)开启)
* 支持识别垂直条形码(增强条形码识别,默认不支持,需通过CaptureHelper.supportVerticalCode(true)开启)
#### v1.1.02019-4-19
* 将扫码相关逻辑与界面分离ZXingLite使用更容易扩展
@@ -183,13 +266,15 @@ api 'com.google.zxing:core:3.3.3'
CSDN: <a title="CSDN博客" href="http://blog.csdn.net/jenly121" target="_blank">jenly121</a>
CNBlogs: <a title="博客园" href="https://www.cnblogs.com/jenly" target="_blank">jenly</a>
Github: <a title="Github开源项目" href="https://github.com/jenly1314" target="_blank">jenly1314</a>
加入QQ群: <a title="点击加入QQ群" href="http://shang.qq.com/wpa/qunwpa?idkey=8fcc6a2f88552ea44b1411582c94fd124f7bb3ec227e2a400dbbfaad3dc2f5ad" target="_blank">20867961</a>
加入QQ群: <a title="点击加入QQ群" href="http://shang.qq.com/wpa/qunwpa?idkey=8fcc6a2f88552ea44b1.1.982c94fd124f7bb3ec227e2a400dbbfaad3dc2f5ad" target="_blank">20867961</a>
<div>
<img src="https://jenly1314.github.io/image/jenly666.png">
<img src="https://jenly1314.github.io/image/qqgourp.png">
</div>

Binary file not shown.

View File

@@ -1 +1 @@
[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":11,"versionName":"1.1.2","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]
[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":25,"versionName":"1.1.9","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]

View File

@@ -5,6 +5,8 @@
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
@@ -14,7 +16,7 @@
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity"
android:screenOrientation="portrait">
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
@@ -23,21 +25,26 @@
</activity>
<activity
android:name="com.king.zxing.CaptureActivity"
android:screenOrientation="portrait"/>
android:screenOrientation="portrait"
android:theme="@style/CaptureTheme"/>
<activity
android:name=".EasyCaptureActivity"
android:screenOrientation="portrait"/>
android:screenOrientation="portrait"
android:theme="@style/CaptureTheme"/>
<activity
android:name=".CustomCaptureActivity"/>
android:name=".CustomCaptureActivity"
android:theme="@style/CaptureTheme"/>
<activity
android:name=".CaptureFragmentActivity"
android:screenOrientation="portrait"/>
android:screenOrientation="portrait"
android:theme="@style/CaptureTheme"/>
<activity
android:name=".CustomActivity"
android:screenOrientation="portrait"/>
android:screenOrientation="portrait"
android:theme="@style/CaptureTheme"/>
<activity
android:name=".CodeActivity"

View File

@@ -56,11 +56,16 @@ public class CodeActivity extends AppCompatActivity {
* @param content
*/
private void createQRCode(String content){
//生成二维码最好放子线程生成防止阻塞UI这里只是演示
Bitmap logo = BitmapFactory.decodeResource(getResources(),R.drawable.logo);
Bitmap bitmap = CodeUtils.createQRCode(content,600,logo);
//显示二维码
ivCode.setImageBitmap(bitmap);
new Thread(() -> {
//生成二维码相关放在子线程里面
Bitmap logo = BitmapFactory.decodeResource(getResources(),R.drawable.logo);
Bitmap bitmap = CodeUtils.createQRCode(content,600,logo);
runOnUiThread(()->{
//显示二维码
ivCode.setImageBitmap(bitmap);
});
}).start();
}
/**
@@ -68,13 +73,18 @@ public class CodeActivity extends AppCompatActivity {
* @param content
*/
private void createBarCode(String content){
//生成条形码最好放子线程生成防止阻塞UI这里只是演示
Bitmap bitmap = CodeUtils.createBarCode(content, BarcodeFormat.CODE_128,800,200,null,true);
//显示条形码
ivCode.setImageBitmap(bitmap);
new Thread(() -> {
//生成条形码相关放在子线程里面
Bitmap bitmap = CodeUtils.createBarCode(content, BarcodeFormat.CODE_128,800,200,null,true);
runOnUiThread(()->{
//显示条形码
ivCode.setImageBitmap(bitmap);
});
}).start();
}
public void onClick(View v){
switch (v.getId()){
case R.id.ivLeft:
@@ -82,4 +92,4 @@ public class CodeActivity extends AppCompatActivity {
break;
}
}
}
}

View File

@@ -1,10 +1,10 @@
package com.king.zxing.app;
import android.app.Activity;
import android.hardware.Camera;
import android.os.Bundle;
import android.app.Activity;
import android.support.v7.app.AppCompatActivity;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MotionEvent;
import android.view.SurfaceView;
@@ -13,7 +13,6 @@ import android.widget.TextView;
import android.widget.Toast;
import com.king.zxing.CaptureHelper;
import com.king.zxing.DecodeFormatManager;
import com.king.zxing.OnCaptureCallback;
import com.king.zxing.ViewfinderView;
import com.king.zxing.app.util.StatusBarUtils;
@@ -33,6 +32,8 @@ public class CustomActivity extends AppCompatActivity implements OnCaptureCallba
private ViewfinderView viewfinderView;
private View ivTorch;
@Override
public void onCreate(Bundle icicle) {
@@ -52,14 +53,18 @@ public class CustomActivity extends AppCompatActivity implements OnCaptureCallba
surfaceView = findViewById(R.id.surfaceView);
viewfinderView = findViewById(R.id.viewfinderView);
ivTorch = findViewById(R.id.ivFlash);
ivTorch.setVisibility(View.INVISIBLE);
isContinuousScan = getIntent().getBooleanExtra(MainActivity.KEY_IS_CONTINUOUS,false);
mCaptureHelper = new CaptureHelper(this,surfaceView,viewfinderView);
mCaptureHelper = new CaptureHelper(this,surfaceView,viewfinderView,ivTorch);
mCaptureHelper.setOnCaptureCallback(this);
mCaptureHelper.onCreate();
mCaptureHelper.vibrate(true)
.fullScreenScan(true)//全屏扫码
.supportVerticalCode(true)//支持扫垂直条码,建议有此需求时才使用。
.supportLuminanceInvert(true)//是否支持识别反色码(黑白反色的码),增加识别率
.continuousScan(isContinuousScan);
}
@@ -88,26 +93,6 @@ public class CustomActivity extends AppCompatActivity implements OnCaptureCallba
return super.onTouchEvent(event);
}
/**
* 关闭闪光灯(手电筒)
*/
private void offFlash(){
Camera camera = mCaptureHelper.getCameraManager().getOpenCamera().getCamera();
Camera.Parameters parameters = camera.getParameters();
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
camera.setParameters(parameters);
}
/**
* 开启闪光灯(手电筒)
*/
public void openFlash(){
Camera camera = mCaptureHelper.getCameraManager().getOpenCamera().getCamera();
Camera.Parameters parameters = camera.getParameters();
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(parameters);
}
/**
* 扫码结果回调
@@ -123,25 +108,12 @@ public class CustomActivity extends AppCompatActivity implements OnCaptureCallba
}
private void clickFlash(View v){
if(v.isSelected()){
offFlash();
v.setSelected(false);
}else{
openFlash();
v.setSelected(true);
}
}
public void onClick(View v){
switch (v.getId()){
case R.id.ivLeft:
onBackPressed();
break;
case R.id.ivFlash:
clickFlash(v);
break;
}
}
}
}

View File

@@ -15,19 +15,15 @@
*/
package com.king.zxing.app;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.google.zxing.DecodeHintType;
import com.king.zxing.CaptureActivity;
import com.king.zxing.app.util.StatusBarUtils;
import com.king.zxing.camera.CameraConfigurationUtils;
import com.king.zxing.camera.FrontLightMode;
/**
* 自定义继承CaptureActivity
@@ -35,8 +31,6 @@ import com.king.zxing.camera.CameraConfigurationUtils;
*/
public class CustomCaptureActivity extends CaptureActivity {
private ImageView ivFlash;
private boolean isContinuousScan;
@Override
public int getLayoutId() {
@@ -52,39 +46,20 @@ public class CustomCaptureActivity extends CaptureActivity {
TextView tvTitle = findViewById(R.id.tvTitle);
tvTitle.setText(getIntent().getStringExtra(MainActivity.KEY_TITLE));
ivFlash = findViewById(R.id.ivFlash);
if(!hasTorch()){
ivFlash.setVisibility(View.GONE);
}
isContinuousScan = getIntent().getBooleanExtra(MainActivity.KEY_IS_CONTINUOUS,false);
//获取CaptureHelper里面有扫码相关的配置设置
getCaptureHelper().playBeep(false)//播放音效
.vibrate(true)//震动
// .decodeFormats(DecodeFormatManager.QR_CODE_FORMATS)//设置只识别二维码会提升速度
.supportVerticalCode(true)//支持扫垂直条码,建议有此需求时才使用。
.continuousScan(isContinuousScan);//是否连扫
}
/**
* 开启或关闭闪光灯(手电筒)
* @param on {@code true}表示开启,{@code false}表示关闭
*/
public void setTorch(boolean on){
Camera camera = getCameraManager().getOpenCamera().getCamera();
Camera.Parameters parameters = camera.getParameters();
CameraConfigurationUtils.setTorch(parameters,on);
camera.setParameters(parameters);
}
/**
* 检测是否支持闪光灯(手电筒)
* @return
*/
public boolean hasTorch(){
return getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
// .decodeFormats(DecodeFormatManager.QR_CODE_FORMATS)//设置只识别二维码会提升速度
// .framingRectRatio(0.9f)//设置识别区域比例范围建议在0.625 ~ 1.0之间。非全屏识别时才有效
// .framingRectVerticalOffset(0)//设置识别区域垂直方向偏移量,非全屏识别时才有效
// .framingRectHorizontalOffset(0)//设置识别区域水平方向偏移量,非全屏识别时才有效
.frontLightMode(FrontLightMode.AUTO)//设置闪光灯模式
.tooDarkLux(45f)//设置光线太暗时,自动触发开启闪光灯的照度值
.brightEnoughLux(100f)//设置光线足够明亮时,自动触发关闭闪光灯的照度值
.continuousScan(isContinuousScan)//是否连扫
.supportLuminanceInvert(true);//是否支持识别反色码(黑白反色的码),增加识别率
}
@@ -102,21 +77,11 @@ public class CustomCaptureActivity extends CaptureActivity {
return super.onResultCallback(result);
}
private void clickFlash(View v){
boolean isSelected = v.isSelected();
setTorch(!isSelected);
v.setSelected(!isSelected);
}
public void onClick(View v){
switch (v.getId()){
case R.id.ivLeft:
onBackPressed();
break;
case R.id.ivFlash:
clickFlash(v);
break;
}
}
}
}

View File

@@ -46,9 +46,9 @@ import pub.devrel.easypermissions.EasyPermissions;
*
* 1、直接使用CaptureActivity或者CaptureFragment。(纯洁的扫码,无任何添加剂)
*
* 2、通过继承CaptureActivity或者CaptureFragment并自定义布局。适用于大多场景并无需关心扫码相关逻辑
* 2、通过继承CaptureActivity或者CaptureFragment并自定义布局。适用于大多场景并无需关心扫码相关逻辑自定义布局时需覆写getLayoutId方法
*
* 3、在你项目的Activity或者Fragment中创建创建一个CaptureHelper并在相应的生命周期中调用CaptureHelper的周期。适用于想在扫码界面写交互逻辑又因为项目架构或其它原因无法直接或间接继承CaptureActivity或CaptureFragment时使用
* 3、在你项目的Activity或者Fragment中创建一个CaptureHelper并在相应的生命周期中调用CaptureHelper的周期。适用于想在扫码界面写交互逻辑又因为项目架构或其它原因无法直接或间接继承CaptureActivity或CaptureFragment时使用
*
* 4、参照CaptureHelper写一个自定义的扫码帮助类其它步骤同方式3。扩展高级用法谨慎使用
*
@@ -94,7 +94,7 @@ public class MainActivity extends AppCompatActivity implements EasyPermissions.P
}
private void parsePhoto(Intent data){
final String path = UriUtils.INSTANCE.getImagePath(this,data);
final String path = UriUtils.getImagePath(this,data);
Log.d("Jenly","path:" + path);
if(TextUtils.isEmpty(path)){
return;
@@ -243,4 +243,4 @@ public class MainActivity extends AppCompatActivity implements EasyPermissions.P
}
}
}
}

View File

@@ -19,7 +19,6 @@ import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.annotation.FloatRange;
import android.support.v7.widget.Toolbar;
import android.view.View;
@@ -33,10 +32,13 @@ import com.king.zxing.app.R;
/**
* @author Jenly <a href="mailto:jenly1314@gmail.com">Jenly</a>
*/
public enum StatusBarUtils {
INSTANCE;
public final class StatusBarUtils {
public static void immersiveStatusBar(Activity activity,Toolbar toolbar) {
private StatusBarUtils(){
throw new AssertionError();
}
public static void immersiveStatusBar(Activity activity, Toolbar toolbar) {
immersiveStatusBar(activity,toolbar,0.0f);
}

View File

@@ -1,6 +1,5 @@
package com.king.zxing.app.util;
import android.annotation.TargetApi;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
@@ -14,13 +13,16 @@ import android.util.Log;
/**
* @author Jenly <a href="mailto:jenly1314@gmail.com">Jenly</a>
*/
public enum UriUtils {
INSTANCE;
public final class UriUtils {
private UriUtils(){
throw new AssertionError();
}
/**
* 获取图片
*/
public String getImagePath(Context context,Intent data) {
public static String getImagePath(Context context,Intent data) {
String imagePath = null;
Uri uri = data.getData();
//获取系統版本
@@ -54,7 +56,7 @@ public enum UriUtils {
/**
* 通过uri和selection来获取真实的图片路径,从相册获取图片时要用
*/
private String getImagePath(Context context,Uri uri, String selection) {
private static String getImagePath(Context context,Uri uri, String selection) {
String path = null;
Cursor cursor = context.getContentResolver().query(uri, null, selection, null, null);
if (cursor != null) {
@@ -66,4 +68,4 @@ public enum UriUtils {
return path;
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 809 B

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 712 B

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -14,7 +14,9 @@
android:background="@color/colorPrimary"
android:layout_height="wrap_content"
app:contentInsetLeft="0dp"
app:contentInsetStart="0dp">
app:contentInsetStart="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/tvTitle"
android:layout_width="match_parent"
@@ -32,7 +34,7 @@
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="6dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="6dp"
android:text="默认扫码"
app:layout_constraintLeft_toLeftOf="parent"

View File

@@ -31,7 +31,6 @@
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginTop="160dp"
style="@style/OnClick"/>
android:layout_marginTop="160dp" />
<include layout="@layout/toolbar_capture"/>
</android.support.constraint.ConstraintLayout>

View File

@@ -22,7 +22,7 @@
app:labelTextLocation="bottom"
app:laserStyle="grid"/>
<ImageView
android:id="@+id/ivFlash"
android:id="@+id/ivTorch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/flash_selected_selector"
@@ -30,7 +30,6 @@
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginTop="160dp"
style="@style/OnClick"/>
android:layout_marginTop="160dp" />
<include layout="@layout/toolbar_capture"/>
</android.support.constraint.ConstraintLayout>

View File

@@ -3,10 +3,7 @@
buildscript {
apply from: 'versions.gradle'
repositories {
google()
jcenter()
}
addRepos(repositories)
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
classpath 'com.novoda:bintray-release:0.9'
@@ -17,9 +14,7 @@ buildscript {
}
allprojects {
repositories {
addRepos(repositories)
}
addRepos(repositories)
}
task clean(type: Delete) {

View File

@@ -42,6 +42,6 @@ dependencies {
androidTestImplementation deps.test.runner
androidTestImplementation deps.test.espresso
compileOnly deps.support.appcompat
api deps.support.appcompat
api deps.zxing
}

View File

@@ -19,3 +19,16 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
#ZXingLite
-dontwarn com.king.zxing.**
-keep class com.king.zxing.**{ *;}
-keepattributes InnerClasses
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
#ZXing
-dontwarn com.google.zxing.**
-keep class com.google.zxing.**{ *;}

View File

@@ -36,8 +36,17 @@ import com.king.zxing.camera.FrontLightMode;
*/
final class AmbientLightManager implements SensorEventListener {
private static final float TOO_DARK_LUX = 45.0f;
private static final float BRIGHT_ENOUGH_LUX = 450.0f;
protected static final float TOO_DARK_LUX = 45.0f;
protected static final float BRIGHT_ENOUGH_LUX = 100.0f;
/**
* 光线太暗时默认照度45 lux
*/
private float tooDarkLux = TOO_DARK_LUX;
/**
* 光线足够亮时默认照度450 lux
*/
private float brightEnoughLux = BRIGHT_ENOUGH_LUX;
private final Context context;
private CameraManager cameraManager;
@@ -72,14 +81,22 @@ final class AmbientLightManager implements SensorEventListener {
public void onSensorChanged(SensorEvent sensorEvent) {
float ambientLightLux = sensorEvent.values[0];
if (cameraManager != null) {
if (ambientLightLux <= TOO_DARK_LUX) {
cameraManager.setTorch(true);
} else if (ambientLightLux >= BRIGHT_ENOUGH_LUX) {
cameraManager.setTorch(false);
if (ambientLightLux <= tooDarkLux) {
cameraManager.sensorChanged(true,ambientLightLux);
} else if (ambientLightLux >= brightEnoughLux) {
cameraManager.sensorChanged(false,ambientLightLux);
}
}
}
public void setTooDarkLux(float tooDarkLux){
this.tooDarkLux = tooDarkLux;
}
public void setBrightEnoughLux(float brightEnoughLux){
this.brightEnoughLux = brightEnoughLux;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// do nothing

View File

@@ -26,7 +26,8 @@ import android.media.MediaPlayer;
import android.os.Build;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.util.Log;
import com.king.zxing.util.LogUtils;
import java.io.Closeable;
import java.io.IOException;
@@ -36,8 +37,6 @@ import java.io.IOException;
*/
public final class BeepManager implements MediaPlayer.OnErrorListener, Closeable {
private static final String TAG = BeepManager.class.getSimpleName();
private static final float BEEP_VOLUME = 0.10f;
private static final long VIBRATE_DURATION = 200L;
@@ -106,7 +105,7 @@ public final class BeepManager implements MediaPlayer.OnErrorListener, Closeable
mediaPlayer.prepare();
return mediaPlayer;
} catch (IOException ioe) {
Log.w(TAG, ioe);
LogUtils.w( ioe);
mediaPlayer.release();
return null;
}

View File

@@ -15,22 +15,24 @@
*/
package com.king.zxing;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import com.king.zxing.camera.CameraManager;
public class CaptureActivity extends Activity implements OnCaptureCallback{
public class CaptureActivity extends AppCompatActivity implements OnCaptureCallback{
public static final String KEY_RESULT = Intents.Scan.RESULT;
private SurfaceView surfaceView;
private ViewfinderView viewfinderView;
private View ivTorch;
private CaptureHelper mCaptureHelper;
@@ -42,6 +44,7 @@ public class CaptureActivity extends Activity implements OnCaptureCallback{
setContentView(layoutId);
}
initUI();
mCaptureHelper.onCreate();
}
/**
@@ -49,10 +52,21 @@ public class CaptureActivity extends Activity implements OnCaptureCallback{
*/
public void initUI(){
surfaceView = findViewById(getSurfaceViewId());
viewfinderView = findViewById(getViewfinderViewId());
mCaptureHelper = new CaptureHelper(this,surfaceView,viewfinderView);
int viewfinderViewId = getViewfinderViewId();
if(viewfinderViewId != 0){
viewfinderView = findViewById(viewfinderViewId);
}
int ivTorchId = getIvTorchId();
if(ivTorchId != 0){
ivTorch = findViewById(ivTorchId);
ivTorch.setVisibility(View.INVISIBLE);
}
initCaptureHelper();
}
public void initCaptureHelper(){
mCaptureHelper = new CaptureHelper(this,surfaceView,viewfinderView,ivTorch);
mCaptureHelper.setOnCaptureCallback(this);
mCaptureHelper.onCreate();
}
/**
@@ -73,8 +87,8 @@ public class CaptureActivity extends Activity implements OnCaptureCallback{
}
/**
* {@link ViewfinderView} 的 id
* @return
* {@link #viewfinderView} 的 ID
* @return 默认返回{@code R.id.viewfinderView}, 如果不需要扫码框可以返回0
*/
public int getViewfinderViewId(){
return R.id.viewfinderView;
@@ -82,13 +96,21 @@ public class CaptureActivity extends Activity implements OnCaptureCallback{
/**
* 预览界面{@link #surfaceView} 的id
* 预览界面{@link #surfaceView} 的ID
* @return
*/
public int getSurfaceViewId(){
return R.id.surfaceView;
}
/**
* 获取 {@link #ivTorch} 的ID
* @return 默认返回{@code R.id.ivTorch}, 如果不需要手电筒按钮可以返回0
*/
public int getIvTorchId(){
return R.id.ivTorch;
}
/**
* Get {@link CaptureHelper}
* @return {@link #mCaptureHelper}
@@ -98,9 +120,10 @@ public class CaptureActivity extends Activity implements OnCaptureCallback{
}
/**
* Get {@link CameraManager}
* Get {@link CameraManager} use {@link #getCaptureHelper()#getCameraManager()}
* @return {@link #mCaptureHelper#getCameraManager()}
*/
@Deprecated
public CameraManager getCameraManager(){
return mCaptureHelper.getCameraManager();
}

View File

@@ -37,13 +37,14 @@ public class CaptureFragment extends Fragment implements OnCaptureCallback {
private SurfaceView surfaceView;
private ViewfinderView viewfinderView;
private View ivTorch;
private CaptureHelper mCaptureHelper;
public static CaptureFragment newInstance() {
Bundle args = new Bundle();
CaptureFragment fragment = new CaptureFragment();
fragment.setArguments(args);
return fragment;
@@ -65,8 +66,20 @@ public class CaptureFragment extends Fragment implements OnCaptureCallback {
*/
public void initUI(){
surfaceView = mRootView.findViewById(getSurfaceViewId());
viewfinderView = mRootView.findViewById(getViewfinderViewId());
mCaptureHelper = new CaptureHelper(this,surfaceView,viewfinderView);
int viewfinderViewId = getViewfinderViewId();
if(viewfinderViewId != 0){
viewfinderView = mRootView.findViewById(viewfinderViewId);
}
int ivTorchId = getIvTorchId();
if(ivTorchId != 0){
ivTorch = mRootView.findViewById(ivTorchId);
ivTorch.setVisibility(View.INVISIBLE);
}
initCaptureHelper();
}
public void initCaptureHelper(){
mCaptureHelper = new CaptureHelper(this,surfaceView,viewfinderView,ivTorch);
mCaptureHelper.setOnCaptureCallback(this);
}
@@ -89,13 +102,12 @@ public class CaptureFragment extends Fragment implements OnCaptureCallback {
/**
* {@link ViewfinderView} 的 id
* @return
* @return 默认返回{@code R.id.viewfinderView}, 如果不需要扫码框可以返回0
*/
public int getViewfinderViewId(){
return R.id.viewfinderView;
}
/**
* 预览界面{@link #surfaceView} 的id
* @return
@@ -104,6 +116,14 @@ public class CaptureFragment extends Fragment implements OnCaptureCallback {
return R.id.surfaceView;
}
/**
* 获取 {@link #ivTorch} 的ID
* @return 默认返回{@code R.id.ivTorch}, 如果不需要手电筒按钮可以返回0
*/
public int getIvTorchId(){
return R.id.ivTorch;
}
/**
* Get {@link CaptureHelper}
* @return {@link #mCaptureHelper}
@@ -113,9 +133,10 @@ public class CaptureFragment extends Fragment implements OnCaptureCallback {
}
/**
* Get {@link CameraManager}
* Get {@link CameraManager} use {@link #getCaptureHelper()#getCameraManager()}
* @return {@link #mCaptureHelper#getCameraManager()}
*/
@Deprecated
public CameraManager getCameraManager(){
return mCaptureHelper.getCameraManager();
}
@@ -167,4 +188,4 @@ public class CaptureFragment extends Fragment implements OnCaptureCallback {
return false;
}
}
}

View File

@@ -32,7 +32,6 @@ public class CaptureHandler extends Handler implements ResultPointCallback {
private final DecodeThread decodeThread;
private State state;
private final CameraManager cameraManager;
private final Activity activity;
private final ViewfinderView viewfinderView;
/**
* 是否支持垂直的条形码
@@ -49,6 +48,11 @@ public class CaptureHandler extends Handler implements ResultPointCallback {
*/
private boolean isSupportAutoZoom;
/**
*
*/
private boolean isSupportLuminanceInvert;
private enum State {
PREVIEW,
@@ -61,7 +65,6 @@ public class CaptureHandler extends Handler implements ResultPointCallback {
Map<DecodeHintType,Object> baseHints,
String characterSet,
CameraManager cameraManager) {
this.activity = activity;
this.viewfinderView = viewfinderView;
this.onCaptureListener = onCaptureListener;
decodeThread = new DecodeThread(activity,cameraManager,this, decodeFormats, baseHints, characterSet, this);
@@ -110,7 +113,7 @@ public class CaptureHandler extends Handler implements ResultPointCallback {
quit.sendToTarget();
try {
// Wait at most half a second; should be enough time, and onPause() will timeout quickly
decodeThread.join(500L);
decodeThread.join(100L);
} catch (InterruptedException e) {
// continue
}
@@ -124,7 +127,9 @@ public class CaptureHandler extends Handler implements ResultPointCallback {
if (state == State.SUCCESS) {
state = State.PREVIEW;
cameraManager.requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
viewfinderView.drawViewfinder();
if(viewfinderView!= null){
viewfinderView.drawViewfinder();
}
}
}
@@ -198,4 +203,12 @@ public class CaptureHandler extends Handler implements ResultPointCallback {
public void setSupportAutoZoom(boolean supportAutoZoom) {
isSupportAutoZoom = supportAutoZoom;
}
public boolean isSupportLuminanceInvert() {
return isSupportLuminanceInvert;
}
public void setSupportLuminanceInvert(boolean supportLuminanceInvert) {
isSupportLuminanceInvert = supportLuminanceInvert;
}
}

View File

@@ -17,20 +17,24 @@ package com.king.zxing;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.graphics.RectF;
import android.hardware.Camera;
import android.support.annotation.FloatRange;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.DecodeHintType;
import com.google.zxing.Result;
import com.king.zxing.camera.CameraManager;
import com.king.zxing.camera.FrontLightMode;
import com.king.zxing.util.LogUtils;
import java.io.IOException;
import java.util.ArrayList;
@@ -42,9 +46,7 @@ import java.util.Map;
/**
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
*/
public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,CaptureManager {
public static final String TAG = CaptureHelper.class.getSimpleName();
public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,CaptureManager, SurfaceHolder.Callback {
private Activity activity;
@@ -58,9 +60,10 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
private AmbientLightManager ambientLightManager;
private SurfaceView surfaceView;
private ViewfinderView viewfinderView;
private SurfaceHolder surfaceHolder;
private SurfaceHolder.Callback callback;
private View ivTorch;
private Collection<BarcodeFormat> decodeFormats;
private Map<DecodeHintType,Object> decodeHints;
@@ -82,6 +85,11 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
*/
private boolean isSupportAutoZoom = true;
/**
* 是否支持识别颜色反转色的码,黑白颜色反转,默认不支持
*/
private boolean isSupportLuminanceInvert = false;
/**
* 是否支持连扫,默认不支持
*/
@@ -114,67 +122,98 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
*/
private boolean isFullScreenScan;
/**
* 识别区域比例范围建议在0.625 ~ 1.0之间默认0.9
*/
private float framingRectRatio = 0.9f;
/**
* 识别区域垂直方向偏移量
*/
private int framingRectVerticalOffset;
/**
* 识别区域水平方向偏移量
*/
private int framingRectHorizontalOffset;
/**
* 光线太暗,当光线亮度太暗,亮度低于此值时,显示手电筒按钮
*/
private float tooDarkLux = AmbientLightManager.TOO_DARK_LUX;
/**
* 光线足够明亮,当光线亮度足够明亮,亮度高于此值时,隐藏手电筒按钮
*/
private float brightEnoughLux = AmbientLightManager.BRIGHT_ENOUGH_LUX;
/**
* 扫码回调
*/
private OnCaptureCallback onCaptureCallback;
private boolean hasCameraFlash;
/**
* use {@link #CaptureHelper(Fragment, SurfaceView, ViewfinderView, View)}
* @param fragment
* @param surfaceView
* @param viewfinderView
*/
@Deprecated
public CaptureHelper(Fragment fragment, SurfaceView surfaceView, ViewfinderView viewfinderView){
this(fragment.getActivity(),surfaceView,viewfinderView);
this(fragment,surfaceView,viewfinderView,null);
}
public CaptureHelper(Activity activity,SurfaceView surfaceView,ViewfinderView viewfinderView){
this.activity = activity;
this.viewfinderView = viewfinderView;
surfaceHolder = surfaceView.getHolder();
hasSurface = false;
public CaptureHelper(Fragment fragment, SurfaceView surfaceView, ViewfinderView viewfinderView,View ivTorch){
this(fragment.getActivity(),surfaceView,viewfinderView,ivTorch);
}
/**
* use {@link #CaptureHelper(Activity, SurfaceView, ViewfinderView, View)}
* @param activity
* @param surfaceView
* @param viewfinderView
*/
@Deprecated
public CaptureHelper(Activity activity,SurfaceView surfaceView,ViewfinderView viewfinderView){
this(activity,surfaceView,viewfinderView,null);
}
/**
*
* @param activity
* @param surfaceView
* @param viewfinderView
* @param ivTorch
*/
public CaptureHelper(Activity activity,SurfaceView surfaceView,ViewfinderView viewfinderView,View ivTorch){
this.activity = activity;
this.surfaceView = surfaceView;
this.viewfinderView = viewfinderView;
this.ivTorch = ivTorch;
}
@Override
public void onCreate(){
surfaceHolder = surfaceView.getHolder();
hasSurface = false;
inactivityTimer = new InactivityTimer(activity);
beepManager = new BeepManager(activity);
ambientLightManager = new AmbientLightManager(activity);
cameraManager = new CameraManager(activity);
cameraManager.setFullScreenScan(isFullScreenScan);
callback = new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (holder == null) {
Log.e(TAG, "*** WARNING *** surfaceCreated() gave us a null surface!");
}
if (!hasSurface) {
hasSurface = true;
initCamera(holder);
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
hasSurface = false;
}
};
onCaptureListener = new OnCaptureListener() {
@Override
public void onHandleDecode(Result result, Bitmap barcode, float scaleFactor) {
inactivityTimer.onActivity();
beepManager.playBeepSoundAndVibrate();
onResult(result);
}
hasCameraFlash = activity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
initCameraManager();
onCaptureListener = (result, barcode, scaleFactor) -> {
inactivityTimer.onActivity();
beepManager.playBeepSoundAndVibrate();
onResult(result,barcode,scaleFactor);
};
//设置是否播放音效和震动
beepManager.setPlayBeep(isPlayBeep);
beepManager.setVibrate(isVibrate);
//设置闪光灯的太暗时和足够亮时的照度值
ambientLightManager.setTooDarkLux(tooDarkLux);
ambientLightManager.setBrightEnoughLux(brightEnoughLux);
}
@@ -182,17 +221,15 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
@Override
public void onResume(){
beepManager.updatePrefs();
ambientLightManager.start(cameraManager);
inactivityTimer.onResume();
surfaceHolder.addCallback(callback);
if (hasSurface) {
initCamera(surfaceHolder);
} else {
surfaceHolder.addCallback(callback);
surfaceHolder.addCallback(this);
}
ambientLightManager.start(cameraManager);
}
@@ -207,7 +244,11 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
beepManager.close();
cameraManager.closeDriver();
if (!hasSurface) {
surfaceHolder.removeCallback(callback);
surfaceHolder.removeCallback(this);
}
if(ivTorch != null && ivTorch.getVisibility() == View.VISIBLE){
ivTorch.setSelected(false);
ivTorch.setVisibility(View.INVISIBLE);
}
}
@@ -252,6 +293,35 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
return false;
}
private void initCameraManager(){
cameraManager = new CameraManager(activity);
cameraManager.setFullScreenScan(isFullScreenScan);
cameraManager.setFramingRectRatio(framingRectRatio);
cameraManager.setFramingRectVerticalOffset(framingRectVerticalOffset);
cameraManager.setFramingRectHorizontalOffset(framingRectHorizontalOffset);
if(ivTorch !=null && hasCameraFlash){
ivTorch.setOnClickListener(v -> {
if(cameraManager!=null){
cameraManager.setTorch(!ivTorch.isSelected());
}
});
cameraManager.setOnSensorListener((torch, tooDark, ambientLightLux) -> {
if(tooDark){
if(ivTorch.getVisibility() != View.VISIBLE){
ivTorch.setVisibility(View.VISIBLE);
}
}else if(!torch){
if(ivTorch.getVisibility() == View.VISIBLE){
ivTorch.setVisibility(View.INVISIBLE);
}
}
});
cameraManager.setOnTorchListener(torch -> ivTorch.setSelected(torch));
}
}
/**
* 初始化Camera
* @param surfaceHolder
@@ -261,7 +331,7 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
throw new IllegalStateException("No SurfaceHolder provided");
}
if (cameraManager.isOpen()) {
Log.w(TAG, "initCamera() while already open -- late SurfaceView callback?");
LogUtils.w("initCamera() while already open -- late SurfaceView callback?");
return;
}
try {
@@ -272,16 +342,38 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
captureHandler.setSupportVerticalCode(isSupportVerticalCode);
captureHandler.setReturnBitmap(isReturnBitmap);
captureHandler.setSupportAutoZoom(isSupportAutoZoom);
captureHandler.setSupportLuminanceInvert(isSupportLuminanceInvert);
}
} catch (IOException ioe) {
Log.w(TAG, ioe);
LogUtils.w( ioe);
} catch (RuntimeException e) {
// Barcode Scanner has seen crashes in the wild of this variety:
// java.?lang.?RuntimeException: Fail to connect to camera service
Log.w(TAG, "Unexpected error initializing camera", e);
LogUtils.w( "Unexpected error initializing camera", e);
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (holder == null) {
LogUtils.w( "*** WARNING *** surfaceCreated() gave us a null surface!");
}
if (!hasSurface) {
hasSurface = true;
initCamera(holder);
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
hasSurface = false;
}
/**
* 处理变焦缩放
* @param isZoomIn
@@ -300,7 +392,7 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
params.setZoom(zoom);
camera.setParameters(params);
} else {
Log.i(TAG, "zoom not supported");
LogUtils.i( "zoom not supported");
}
}
@@ -309,6 +401,7 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
* @param event
* @param camera
*/
@Deprecated
private void focusOnTouch(MotionEvent event,Camera camera) {
Camera.Parameters params = camera.getParameters();
@@ -332,13 +425,10 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
params.setFocusMode(Camera.Parameters.FOCUS_MODE_MACRO);
camera.setParameters(params);
camera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
Camera.Parameters params = camera.getParameters();
params.setFocusMode(currentFocusMode);
camera.setParameters(params);
}
camera.autoFocus((success, camera1) -> {
Camera.Parameters params1 = camera1.getParameters();
params1.setFocusMode(currentFocusMode);
camera1.setParameters(params1);
});
}
@@ -403,6 +493,17 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
}
/**
* 接收扫码结果
* @param result
* @param barcode
* @param scaleFactor
*/
public void onResult(Result result, Bitmap barcode, float scaleFactor){
onResult(result);
}
/**';, mnb
*
* 接收扫码结果,想支持连扫时,可将{@link #continuousScan(boolean)}设置为{@code true}
* 如果{@link #isContinuousScan}支持连扫,则默认重启扫码和解码器;当连扫逻辑太复杂时,
* 请将{@link #autoRestartPreviewAndDecode(boolean)}设置为{@code false},并手动调用{@link #restartPreviewAndDecode()}
@@ -420,19 +521,16 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
return;
}
if(isPlayBeep){//如果播放音效,则稍微延迟一点,给予播放音效时间
captureHandler.postDelayed(new Runnable() {
@Override
public void run() {
//如果设置了回调并且onCallback返回为true则表示拦截
if(onCaptureCallback!=null && onCaptureCallback.onResultCallback(text)){
return;
}
Intent intent = new Intent();
intent.putExtra(Intents.Scan.RESULT,text);
activity.setResult(Activity.RESULT_OK,intent);
activity.finish();
if(isPlayBeep && captureHandler != null){//如果播放音效,则稍微延迟一点,给予播放音效时间
captureHandler.postDelayed(() -> {
//如果设置了回调并且onCallback返回为true则表示拦截
if(onCaptureCallback!=null && onCaptureCallback.onResultCallback(text)){
return;
}
Intent intent = new Intent();
intent.putExtra(Intents.Scan.RESULT,text);
activity.setResult(Activity.RESULT_OK,intent);
activity.finish();
},100);
return;
}
@@ -559,6 +657,49 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
return this;
}
/**
* 设置闪光灯模式。当设置模式为:{@link FrontLightMode#AUTO}时,如果满意默认的照度值范围,
* 可通过{@link #tooDarkLux(float)}和{@link #brightEnoughLux(float)}来自定义照度范围,
* 控制自动触发开启和关闭闪光灯。
* 当设置模式非{@link FrontLightMode#AUTO}时,传感器不会检测,则不使用手电筒
*
* @param mode 默认:{@link FrontLightMode#AUTO}
* @return
*/
public CaptureHelper frontLightMode(FrontLightMode mode) {
FrontLightMode.put(activity,mode);
if(ivTorch!=null && mode != FrontLightMode.AUTO){
ivTorch.setVisibility(View.INVISIBLE);
}
return this;
}
/**
* 设置光线太暗时,自动显示手电筒按钮
* @param tooDarkLux 默认:{@link AmbientLightManager#TOO_DARK_LUX}
* @return
*/
public CaptureHelper tooDarkLux(float tooDarkLux) {
this.tooDarkLux = tooDarkLux;
if(ambientLightManager != null){
ambientLightManager.setTooDarkLux(tooDarkLux);
}
return this;
}
/**
* 设置光线足够明亮时,自动隐藏手电筒按钮
* @param brightEnoughLux 默认:{@link AmbientLightManager#BRIGHT_ENOUGH_LUX}
* @return
*/
public CaptureHelper brightEnoughLux(float brightEnoughLux) {
this.brightEnoughLux = brightEnoughLux;
if(ambientLightManager != null){
ambientLightManager.setTooDarkLux(tooDarkLux);
}
return this;
}
/**
* 设置返回扫码原图
* @param returnBitmap 默认为false当返回true表示扫码就结果会返回扫码原图相应的会增加性能消耗。
@@ -586,9 +727,22 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
return this;
}
/**
* 是否支持识别反色码,黑白颜色反转
* @param supportLuminanceInvert 默认为false当返回true时表示支持会增加识别率但相应的也会增加性能消耗。
* @return
*/
public CaptureHelper supportLuminanceInvert(boolean supportLuminanceInvert) {
isSupportLuminanceInvert = supportLuminanceInvert;
if(captureHandler!=null){
captureHandler.setSupportLuminanceInvert(isSupportLuminanceInvert);
}
return this;
}
/**
* 设置是否支持全屏扫码识别
* @param fullScreenScan
* @param fullScreenScan 默认为false
* @return
*/
public CaptureHelper fullScreenScan(boolean fullScreenScan) {
@@ -599,6 +753,46 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
return this;
}
/**
* 设置识别区域比例范围建议在0.625 ~ 1.0之间。非全屏识别时才有效
* 0.625 即与默认推荐显示区域一致1.0表示与宽度一致
* @param framingRectRatio 默认0.9
* @return
*/
public CaptureHelper framingRectRatio(@FloatRange(from = 0.0f ,to = 1.0f) float framingRectRatio) {
this.framingRectRatio = framingRectRatio;
if(cameraManager!=null){
cameraManager.setFramingRectRatio(framingRectRatio);
}
return this;
}
/**
* 设置识别区域垂直方向偏移量,非全屏识别时才有效
* @param framingRectVerticalOffset 默认0表示不偏移
* @return
*/
public CaptureHelper framingRectVerticalOffset(int framingRectVerticalOffset) {
this.framingRectVerticalOffset = framingRectVerticalOffset;
if(cameraManager!=null){
cameraManager.setFramingRectVerticalOffset(framingRectVerticalOffset);
}
return this;
}
/**
* 设置识别区域水平方向偏移量,非全屏识别时才有效
* @param framingRectHorizontalOffset 默认0表示不偏移
* @return
*/
public CaptureHelper framingRectHorizontalOffset(int framingRectHorizontalOffset) {
this.framingRectHorizontalOffset = framingRectHorizontalOffset;
if(cameraManager!=null){
cameraManager.setFramingRectHorizontalOffset(framingRectHorizontalOffset);
}
return this;
}
/**
* 设置扫码回调
@@ -645,4 +839,4 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
public InactivityTimer getInactivityTimer() {
return inactivityTimer;
}
}
}

View File

@@ -19,13 +19,11 @@ package com.king.zxing;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.PointF;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;
@@ -33,22 +31,19 @@ import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.NotFoundException;
import com.google.zxing.PlanarYUVLuminanceSource;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.ResultPoint;
import com.google.zxing.common.GlobalHistogramBinarizer;
import com.google.zxing.common.HybridBinarizer;
import com.king.zxing.camera.CameraManager;
import com.king.zxing.util.LogUtils;
import java.io.ByteArrayOutputStream;
import java.util.Map;
final class DecodeHandler extends Handler {
private static final String TAG = DecodeHandler.class.getSimpleName();
private final Context context;
private final CameraManager cameraManager;
private final CaptureHandler handler;
@@ -102,37 +97,56 @@ final class DecodeHandler extends Handler {
PlanarYUVLuminanceSource source = buildPlanarYUVLuminanceSource(data,width,height,isScreenPortrait);
if (source != null) {
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
try {
rawResult = multiFormatReader.decodeWithState(bitmap);
} catch (Exception e) {
BinaryBitmap bitmap1 = new BinaryBitmap(new GlobalHistogramBinarizer(source));
try{
rawResult = multiFormatReader.decodeWithState(bitmap1);
}catch (Exception e1){
if(isSupportVerticalCode){
source = buildPlanarYUVLuminanceSource(data,width,height,!isScreenPortrait);
if(source!=null){
BinaryBitmap bitmap2 = new BinaryBitmap(new HybridBinarizer(source));
try{
rawResult = multiFormatReader.decodeWithState(bitmap2);
}catch (Exception e2){
}
}
boolean isReDecode;
try {
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
rawResult = multiFormatReader.decodeWithState(bitmap);
isReDecode = false;
} catch (Exception e) {
isReDecode = true;
}
if(isReDecode && handler.isSupportLuminanceInvert()){
try {
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source.invert()));
rawResult = multiFormatReader.decodeWithState(bitmap);
isReDecode = false;
} catch (Exception e) {
isReDecode = true;
}
}
if(isReDecode){
try{
BinaryBitmap bitmap = new BinaryBitmap(new GlobalHistogramBinarizer(source));
rawResult = multiFormatReader.decodeWithState(bitmap);
isReDecode = false;
}catch (Exception e){
isReDecode = true;
}
}
if(isReDecode && isSupportVerticalCode){
source = buildPlanarYUVLuminanceSource(data,width,height,!isScreenPortrait);
if(source!=null){
try{
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
rawResult = multiFormatReader.decodeWithState(bitmap);
}catch (Exception e){
}
}
} finally {
multiFormatReader.reset();
}
multiFormatReader.reset();
}
if (rawResult != null) {
// Don't log the barcode contents for security.
long end = System.currentTimeMillis();
Log.d(TAG, "Found barcode in " + (end - start) + " ms");
LogUtils.d( "Found barcode in " + (end - start) + " ms");
BarcodeFormat barcodeFormat = rawResult.getBarcodeFormat();
if(handler!=null && handler.isSupportAutoZoom() && barcodeFormat == BarcodeFormat.QR_CODE){
@@ -157,7 +171,6 @@ final class DecodeHandler extends Handler {
}
}
}
if (handler != null) {
@@ -211,7 +224,7 @@ final class DecodeHandler extends Handler {
return true;
}
if(length<width/5){
if(length < width/ 5){
Camera camera = cameraManager.getOpenCamera().getCamera();
if(camera!=null){
@@ -224,7 +237,7 @@ final class DecodeHandler extends Handler {
lastZoomTime = System.currentTimeMillis();
return true;
} else {
Log.i(TAG, "Zoom not supported");
LogUtils.i( "Zoom not supported");
}
}

View File

@@ -21,13 +21,13 @@ import com.google.zxing.BarcodeFormat;
import com.google.zxing.DecodeHintType;
import com.google.zxing.ResultPointCallback;
import com.king.zxing.camera.CameraManager;
import com.king.zxing.util.LogUtils;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.util.Log;
import java.util.Collection;
import java.util.EnumMap;
@@ -98,7 +98,7 @@ final class DecodeThread extends Thread {
hints.put(DecodeHintType.CHARACTER_SET, characterSet);
}
hints.put(DecodeHintType.NEED_RESULT_POINT_CALLBACK, resultPointCallback);
Log.i("DecodeThread", "Hints: " + hints);
LogUtils.i( "Hints: " + hints);
}
Handler getHandler() {

View File

@@ -24,7 +24,8 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncTask;
import android.os.BatteryManager;
import android.util.Log;
import com.king.zxing.util.LogUtils;
import java.lang.ref.WeakReference;
import java.util.concurrent.RejectedExecutionException;
@@ -34,8 +35,6 @@ import java.util.concurrent.RejectedExecutionException;
*/
final class InactivityTimer {
private static final String TAG = InactivityTimer.class.getSimpleName();
private static final long INACTIVITY_DELAY_MS = 5 * 60 * 1000L;
private final Activity activity;
@@ -50,29 +49,29 @@ final class InactivityTimer {
onActivity();
}
synchronized void onActivity() {
void onActivity() {
cancel();
inactivityTask = new InactivityAsyncTask(activity);
try {
inactivityTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} catch (RejectedExecutionException ree) {
Log.w(TAG, "Couldn't schedule inactivity task; ignoring");
LogUtils.w( "Couldn't schedule inactivity task; ignoring");
}
}
synchronized void onPause() {
void onPause() {
cancel();
if (registered) {
activity.unregisterReceiver(powerStatusReceiver);
registered = false;
} else {
Log.w(TAG, "PowerStatusReceiver was never registered?");
LogUtils.w( "PowerStatusReceiver was never registered?");
}
}
synchronized void onResume() {
void onResume() {
if (registered) {
Log.w(TAG, "PowerStatusReceiver was already registered?");
LogUtils.w( "PowerStatusReceiver was already registered?");
} else {
activity.registerReceiver(powerStatusReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
registered = true;
@@ -80,7 +79,7 @@ final class InactivityTimer {
onActivity();
}
private synchronized void cancel() {
private void cancel() {
AsyncTask<?,?,?> task = inactivityTask;
if (task != null) {
task.cancel(true);
@@ -130,7 +129,7 @@ final class InactivityTimer {
protected Object doInBackground(Object... objects) {
try {
Thread.sleep(INACTIVITY_DELAY_MS);
Log.i(TAG, "Finishing activity due to inactivity");
LogUtils.i( "Finishing activity due to inactivity");
Activity activity = weakReference.get();
if(activity!=null){
activity.finish();

View File

@@ -17,17 +17,11 @@ package com.king.zxing;
*/
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
@@ -41,7 +35,6 @@ import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
@@ -58,52 +51,141 @@ import java.util.List;
*/
public final class ViewfinderView extends View {
private static final long ANIMATION_DELAY = 15L;
private static final int CURRENT_POINT_OPACITY = 0xA0;
private static final int MAX_RESULT_POINTS = 20;
private static final int POINT_SIZE = 20;
private static final int CORNER_RECT_WIDTH = 8; //扫描区边角的宽
private static final int CORNER_RECT_HEIGHT = 40; //扫描区边角的高
private static final int SCANNER_LINE_MOVE_DISTANCE = 6; //扫描线移动距离
private static final int SCANNER_LINE_HEIGHT = 10; //扫描线宽度
/**
* 画笔
*/
private Paint paint;
/**
* 文本画笔
*/
private TextPaint textPaint;
/**
* 扫码框外面遮罩颜色
*/
private int maskColor;
//扫描区域边框颜色
/**
* 扫描区域边框颜色
*/
private int frameColor;
//扫描线颜色
/**
* 扫描线颜色
*/
private int laserColor;
//四角颜色
/**
* 扫码框四角颜色
*/
private int cornerColor;
/**
* 结果点颜色
*/
private int resultPointColor;
/**
* 提示文本与扫码框的边距
*/
private float labelTextPadding;
/**
* 提示文本的位置
*/
private TextLocation labelTextLocation;
//扫描区域提示文本
/**
* 扫描区域提示文本
*/
private String labelText;
//扫描区域提示文本颜色
/**
* 扫描区域提示文本颜色
*/
private int labelTextColor;
/**
* 提示文本字体大小
*/
private float labelTextSize;
/**
* 扫描线开始位置
*/
public int scannerStart = 0;
/**
* 扫描线结束位置
*/
public int scannerEnd = 0;
/**
* 是否显示结果点
*/
private boolean isShowResultPoint;
/**
* 屏幕宽
*/
private int screenWidth;
/**
* 屏幕高
*/
private int screenHeight;
//扫码框宽
/**
* 扫码框宽
*/
private int frameWidth;
//扫码框宽
/**
* 扫码框高
*/
private int frameHeight;
//扫描激光线风格
/**
* 扫描激光线风格
*/
private LaserStyle laserStyle;
/**
* 网格列数
*/
private int gridColumn;
/**
* 网格高度
*/
private int gridHeight;
/**
* 扫码框
*/
private Rect frame;
/**
* 扫描区边角的宽
*/
private int cornerRectWidth;
/**
* 扫描区边角的高
*/
private int cornerRectHeight;
/**
* 扫描线每次移动距离
*/
private int scannerLineMoveDistance;
/**
* 扫描线高度
*/
private int scannerLineHeight;
/**
* 边框线宽度
*/
private int frameLineWidth;
/**
* 扫描动画延迟间隔时间 默认15毫秒
*/
private int scannerAnimationDelay;
/**
* 扫码框占比
*/
private float frameRatio;
private List<ResultPoint> possibleResultPoints;
private List<ResultPoint> lastPossibleResultPoints;
@@ -188,6 +270,13 @@ public final class ViewfinderView extends View {
gridColumn = array.getInt(R.styleable.ViewfinderView_gridColumn,20);
gridHeight = (int)array.getDimension(R.styleable.ViewfinderView_gridHeight,TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,40,getResources().getDisplayMetrics()));
cornerRectWidth = (int)array.getDimension(R.styleable.ViewfinderView_cornerRectWidth,TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,4,getResources().getDisplayMetrics()));
cornerRectHeight = (int)array.getDimension(R.styleable.ViewfinderView_cornerRectHeight,TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,16,getResources().getDisplayMetrics()));
scannerLineMoveDistance = (int)array.getDimension(R.styleable.ViewfinderView_scannerLineMoveDistance,TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,2,getResources().getDisplayMetrics()));
scannerLineHeight = (int)array.getDimension(R.styleable.ViewfinderView_scannerLineHeight,TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,5,getResources().getDisplayMetrics()));
frameLineWidth = (int)array.getDimension(R.styleable.ViewfinderView_frameLineWidth,TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,getResources().getDisplayMetrics()));
scannerAnimationDelay = array.getInteger(R.styleable.ViewfinderView_scannerAnimationDelay,15);
frameRatio = array.getFloat(R.styleable.ViewfinderView_frameRatio,0.625f);
array.recycle();
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
@@ -199,7 +288,7 @@ public final class ViewfinderView extends View {
screenWidth = getDisplayMetrics().widthPixels;
screenHeight = getDisplayMetrics().heightPixels;
int size = (int)(Math.min(screenWidth,screenHeight) * 0.625f);
int size = (int)(Math.min(screenWidth,screenHeight) * frameRatio);
if(frameWidth<=0 || frameWidth > screenWidth){
frameWidth = size;
@@ -240,7 +329,6 @@ public final class ViewfinderView extends View {
frame = new Rect(leftOffset, topOffset, leftOffset + frameWidth, topOffset + frameHeight);
}
@SuppressLint("DrawAllocation")
@Override
public void onDraw(Canvas canvas) {
@@ -250,7 +338,7 @@ public final class ViewfinderView extends View {
if(scannerStart == 0 || scannerEnd == 0) {
scannerStart = frame.top;
scannerEnd = frame.bottom - SCANNER_LINE_HEIGHT;
scannerEnd = frame.bottom - scannerLineHeight;
}
int width = canvas.getWidth();
@@ -270,7 +358,7 @@ public final class ViewfinderView extends View {
drawResultPoint(canvas,frame);
// Request another update at the animation interval, but only repaint the laser line,
// not the entire viewfinder mask.
postInvalidateDelayed(ANIMATION_DELAY,
postInvalidateDelayed(scannerAnimationDelay,
frame.left - POINT_SIZE,
frame.top - POINT_SIZE,
frame.right + POINT_SIZE,
@@ -307,17 +395,17 @@ public final class ViewfinderView extends View {
private void drawCorner(Canvas canvas, Rect frame) {
paint.setColor(cornerColor);
//左上
canvas.drawRect(frame.left, frame.top, frame.left + CORNER_RECT_WIDTH, frame.top + CORNER_RECT_HEIGHT, paint);
canvas.drawRect(frame.left, frame.top, frame.left + CORNER_RECT_HEIGHT, frame.top + CORNER_RECT_WIDTH, paint);
canvas.drawRect(frame.left, frame.top, frame.left + cornerRectWidth, frame.top + cornerRectHeight, paint);
canvas.drawRect(frame.left, frame.top, frame.left + cornerRectHeight, frame.top + cornerRectWidth, paint);
//右上
canvas.drawRect(frame.right - CORNER_RECT_WIDTH, frame.top, frame.right, frame.top + CORNER_RECT_HEIGHT, paint);
canvas.drawRect(frame.right - CORNER_RECT_HEIGHT, frame.top, frame.right, frame.top + CORNER_RECT_WIDTH, paint);
canvas.drawRect(frame.right - cornerRectWidth, frame.top, frame.right, frame.top + cornerRectHeight, paint);
canvas.drawRect(frame.right - cornerRectHeight, frame.top, frame.right, frame.top + cornerRectWidth, paint);
//左下
canvas.drawRect(frame.left, frame.bottom - CORNER_RECT_WIDTH, frame.left + CORNER_RECT_HEIGHT, frame.bottom, paint);
canvas.drawRect(frame.left, frame.bottom - CORNER_RECT_HEIGHT, frame.left + CORNER_RECT_WIDTH, frame.bottom, paint);
canvas.drawRect(frame.left, frame.bottom - cornerRectWidth, frame.left + cornerRectHeight, frame.bottom, paint);
canvas.drawRect(frame.left, frame.bottom - cornerRectHeight, frame.left + cornerRectWidth, frame.bottom, paint);
//右下
canvas.drawRect(frame.right - CORNER_RECT_WIDTH, frame.bottom - CORNER_RECT_HEIGHT, frame.right, frame.bottom, paint);
canvas.drawRect(frame.right - CORNER_RECT_HEIGHT, frame.bottom - CORNER_RECT_WIDTH, frame.right, frame.bottom, paint);
canvas.drawRect(frame.right - cornerRectWidth, frame.bottom - cornerRectHeight, frame.right, frame.bottom, paint);
canvas.drawRect(frame.right - cornerRectHeight, frame.bottom - cornerRectWidth, frame.right, frame.bottom, paint);
}
/**
@@ -349,7 +437,7 @@ public final class ViewfinderView extends View {
//线性渐变
LinearGradient linearGradient = new LinearGradient(
frame.left, scannerStart,
frame.left, scannerStart + SCANNER_LINE_HEIGHT,
frame.left, scannerStart + scannerLineHeight,
shadeColor(laserColor),
laserColor,
Shader.TileMode.MIRROR);
@@ -357,9 +445,9 @@ public final class ViewfinderView extends View {
paint.setShader(linearGradient);
if(scannerStart <= scannerEnd) {
//椭圆
RectF rectF = new RectF(frame.left + 2 * SCANNER_LINE_HEIGHT, scannerStart, frame.right - 2 * SCANNER_LINE_HEIGHT, scannerStart + SCANNER_LINE_HEIGHT);
RectF rectF = new RectF(frame.left + 2 * scannerLineHeight, scannerStart, frame.right - 2 * scannerLineHeight, scannerStart + scannerLineHeight);
canvas.drawOval(rectF, paint);
scannerStart += SCANNER_LINE_MOVE_DISTANCE;
scannerStart += scannerLineMoveDistance;
} else {
scannerStart = frame.top;
}
@@ -395,7 +483,7 @@ public final class ViewfinderView extends View {
}
if(scannerStart<scannerEnd){
scannerStart += SCANNER_LINE_MOVE_DISTANCE;
scannerStart += scannerLineMoveDistance;
} else {
scannerStart = frame.top;
}
@@ -420,10 +508,10 @@ public final class ViewfinderView extends View {
*/
private void drawFrame(Canvas canvas, Rect frame) {
paint.setColor(frameColor);
canvas.drawRect(frame.left, frame.top, frame.right + 1, frame.top + 2, paint);
canvas.drawRect(frame.left, frame.top + 2, frame.left + 2, frame.bottom - 1, paint);
canvas.drawRect(frame.right - 1, frame.top, frame.right + 1, frame.bottom - 1, paint);
canvas.drawRect(frame.left, frame.bottom - 1, frame.right + 1, frame.bottom + 1, paint);
canvas.drawRect(frame.left, frame.top, frame.right, frame.top + frameLineWidth, paint);
canvas.drawRect(frame.left, frame.top, frame.left + frameLineWidth, frame.bottom, paint);
canvas.drawRect(frame.right - frameLineWidth, frame.top, frame.right, frame.bottom, paint);
canvas.drawRect(frame.left, frame.bottom - frameLineWidth, frame.right, frame.bottom, paint);
}
/**
@@ -436,9 +524,9 @@ public final class ViewfinderView extends View {
private void drawExterior(Canvas canvas, Rect frame, int width, int height) {
paint.setColor(maskColor);
canvas.drawRect(0, 0, width, frame.top, paint);
canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint);
canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, paint);
canvas.drawRect(0, frame.bottom + 1, width, height, paint);
canvas.drawRect(0, frame.top, frame.left, frame.bottom, paint);
canvas.drawRect(frame.right, frame.top, width, frame.bottom, paint);
canvas.drawRect(0, frame.bottom, width, height, paint);
}
/**

View File

@@ -20,7 +20,6 @@ import android.content.SharedPreferences;
import android.hardware.Camera;
import android.os.AsyncTask;
import android.preference.PreferenceManager;
import android.util.Log;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -28,12 +27,11 @@ import java.util.Collection;
import java.util.concurrent.RejectedExecutionException;
import com.king.zxing.Preferences;
import com.king.zxing.util.LogUtils;
@SuppressWarnings("deprecation") // camera APIs
final class AutoFocusManager implements Camera.AutoFocusCallback {
private static final String TAG = AutoFocusManager.class.getSimpleName();
private static final long AUTO_FOCUS_INTERVAL_MS = 1200L;
private static final Collection<String> FOCUS_MODES_CALLING_AF;
static {
@@ -55,7 +53,7 @@ final class AutoFocusManager implements Camera.AutoFocusCallback {
useAutoFocus =
sharedPrefs.getBoolean(Preferences.KEY_AUTO_FOCUS, true) &&
FOCUS_MODES_CALLING_AF.contains(currentFocusMode);
Log.i(TAG, "Current focus mode '" + currentFocusMode + "'; use auto focus? " + useAutoFocus);
LogUtils.i( "Current focus mode '" + currentFocusMode + "'; use auto focus? " + useAutoFocus);
start();
}
@@ -72,7 +70,7 @@ final class AutoFocusManager implements Camera.AutoFocusCallback {
newTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
outstandingTask = newTask;
} catch (RejectedExecutionException ree) {
Log.w(TAG, "Could not request auto focus", ree);
LogUtils.w( "Could not request auto focus", ree);
}
}
}
@@ -86,7 +84,7 @@ final class AutoFocusManager implements Camera.AutoFocusCallback {
focusing = true;
} catch (RuntimeException re) {
// Have heard RuntimeException reported in Android 4.0.x+; continue?
Log.w(TAG, "Unexpected exception while focusing", re);
LogUtils.w( "Unexpected exception while focusing", re);
// Try again later to keep cycle going
autoFocusAgainLater();
}
@@ -112,7 +110,7 @@ final class AutoFocusManager implements Camera.AutoFocusCallback {
camera.cancelAutoFocus();
} catch (RuntimeException re) {
// Have heard RuntimeException reported in Android 4.0.x+; continue?
Log.w(TAG, "Unexpected exception while cancelling focusing", re);
LogUtils.w( "Unexpected exception while cancelling focusing", re);
}
}
}

View File

@@ -22,7 +22,6 @@ import android.content.SharedPreferences;
import android.graphics.Point;
import android.hardware.Camera;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.WindowManager;
@@ -30,6 +29,7 @@ import android.view.WindowManager;
import com.king.zxing.Preferences;
import com.king.zxing.camera.open.CameraFacing;
import com.king.zxing.camera.open.OpenCamera;
import com.king.zxing.util.LogUtils;
/**
* A class which deals with reading, parsing, and setting the camera parameters which are used to
@@ -38,8 +38,6 @@ import com.king.zxing.camera.open.OpenCamera;
@SuppressWarnings("deprecation") // camera APIs
final class CameraConfigurationManager {
private static final String TAG = "CameraConfiguration";
private final Context context;
private int cwNeededRotation;
private int cwRotationFromDisplayToCamera;
@@ -83,15 +81,15 @@ final class CameraConfigurationManager {
throw new IllegalArgumentException("Bad rotation: " + displayRotation);
}
}
Log.i(TAG, "Display at: " + cwRotationFromNaturalToDisplay);
LogUtils.i( "Display at: " + cwRotationFromNaturalToDisplay);
int cwRotationFromNaturalToCamera = camera.getOrientation();
Log.i(TAG, "Camera at: " + cwRotationFromNaturalToCamera);
LogUtils.i( "Camera at: " + cwRotationFromNaturalToCamera);
// Still not 100% sure about this. But acts like we need to flip this:
if (camera.getFacing() == CameraFacing.FRONT) {
cwRotationFromNaturalToCamera = (360 - cwRotationFromNaturalToCamera) % 360;
Log.i(TAG, "Front camera overriden to: " + cwRotationFromNaturalToCamera);
LogUtils.i( "Front camera overriden to: " + cwRotationFromNaturalToCamera);
}
/*
@@ -103,30 +101,30 @@ final class CameraConfigurationManager {
overrideRotationString = prefs.getString(PreferencesActivity.KEY_FORCE_CAMERA_ORIENTATION, null);
}
if (overrideRotationString != null && !"-".equals(overrideRotationString)) {
Log.i(TAG, "Overriding camera manually to " + overrideRotationString);
LogUtils.i( "Overriding camera manually to " + overrideRotationString);
cwRotationFromNaturalToCamera = Integer.parseInt(overrideRotationString);
}
*/
cwRotationFromDisplayToCamera = (360 + cwRotationFromNaturalToCamera - cwRotationFromNaturalToDisplay) % 360;
Log.i(TAG, "Final display orientation: " + cwRotationFromDisplayToCamera);
LogUtils.i( "Final display orientation: " + cwRotationFromDisplayToCamera);
if (camera.getFacing() == CameraFacing.FRONT) {
Log.i(TAG, "Compensating rotation for front camera");
LogUtils.i( "Compensating rotation for front camera");
cwNeededRotation = (360 - cwRotationFromDisplayToCamera) % 360;
} else {
cwNeededRotation = cwRotationFromDisplayToCamera;
}
Log.i(TAG, "Clockwise rotation from display to camera: " + cwNeededRotation);
LogUtils.i( "Clockwise rotation from display to camera: " + cwNeededRotation);
Point theScreenResolution = new Point();
display.getSize(theScreenResolution);
screenResolution = theScreenResolution;
Log.i(TAG, "Screen resolution in current orientation: " + screenResolution);
LogUtils.i( "Screen resolution in current orientation: " + screenResolution);
cameraResolution = CameraConfigurationUtils.findBestPreviewSizeValue(parameters, screenResolution);
Log.i(TAG, "Camera resolution: " + cameraResolution);
LogUtils.i( "Camera resolution: " + cameraResolution);
bestPreviewSize = CameraConfigurationUtils.findBestPreviewSizeValue(parameters, screenResolution);
Log.i(TAG, "Best available preview size: " + bestPreviewSize);
LogUtils.i( "Best available preview size: " + bestPreviewSize);
boolean isScreenPortrait = screenResolution.x < screenResolution.y;
boolean isPreviewSizePortrait = bestPreviewSize.x < bestPreviewSize.y;
@@ -136,7 +134,7 @@ final class CameraConfigurationManager {
} else {
previewSizeOnScreen = new Point(bestPreviewSize.y, bestPreviewSize.x);
}
Log.i(TAG, "Preview size on screen: " + previewSizeOnScreen);
LogUtils.i( "Preview size on screen: " + previewSizeOnScreen);
}
void setDesiredCameraParameters(OpenCamera camera, boolean safeMode) {
@@ -145,14 +143,14 @@ final class CameraConfigurationManager {
Camera.Parameters parameters = theCamera.getParameters();
if (parameters == null) {
Log.w(TAG, "Device error: no camera parameters are available. Proceeding without configuration.");
LogUtils.w( "Device error: no camera parameters are available. Proceeding without configuration.");
return;
}
Log.i(TAG, "Initial camera parameters: " + parameters.flatten());
LogUtils.i( "Initial camera parameters: " + parameters.flatten());
if (safeMode) {
Log.w(TAG, "In camera config safe mode -- most settings will not be honored");
LogUtils.w( "In camera config safe mode -- most settings will not be honored");
}
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
@@ -199,7 +197,7 @@ final class CameraConfigurationManager {
Camera.Parameters afterParameters = theCamera.getParameters();
Camera.Size afterSize = afterParameters.getPreviewSize();
if (afterSize != null && (bestPreviewSize.x != afterSize.width || bestPreviewSize.y != afterSize.height)) {
Log.w(TAG, "Camera said it supported preview size " + bestPreviewSize.x + 'x' + bestPreviewSize.y +
LogUtils.w( "Camera said it supported preview size " + bestPreviewSize.x + 'x' + bestPreviewSize.y +
", but after setting it, preview size is " + afterSize.width + 'x' + afterSize.height);
bestPreviewSize.x = afterSize.width;
bestPreviewSize.y = afterSize.height;

View File

@@ -20,12 +20,12 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.Camera;
import android.os.Build;
import android.util.Log;
import com.king.zxing.util.LogUtils;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
@@ -38,8 +38,6 @@ import java.util.regex.Pattern;
@SuppressWarnings("deprecation") // camera APIs
public final class CameraConfigurationUtils {
private static final String TAG = "CameraConfiguration";
private static final Pattern SEMICOLON = Pattern.compile(";");
private static final int MIN_PREVIEW_PIXELS = 480 * 320; // normal screen
@@ -81,7 +79,7 @@ public final class CameraConfigurationUtils {
}
if (focusMode != null) {
if (focusMode.equals(parameters.getFocusMode())) {
Log.i(TAG, "Focus mode already set to " + focusMode);
LogUtils.d( "Focus mode already set to " + focusMode);
} else {
parameters.setFocusMode(focusMode);
}
@@ -103,9 +101,9 @@ public final class CameraConfigurationUtils {
}
if (flashMode != null) {
if (flashMode.equals(parameters.getFlashMode())) {
Log.i(TAG, "Flash mode already set to " + flashMode);
LogUtils.d( "Flash mode already set to " + flashMode);
} else {
Log.i(TAG, "Setting flash mode to " + flashMode);
LogUtils.d( "Setting flash mode to " + flashMode);
parameters.setFlashMode(flashMode);
}
}
@@ -123,13 +121,13 @@ public final class CameraConfigurationUtils {
// Clamp value:
compensationSteps = Math.max(Math.min(compensationSteps, maxExposure), minExposure);
if (parameters.getExposureCompensation() == compensationSteps) {
Log.i(TAG, "Exposure compensation already set to " + compensationSteps + " / " + actualCompensation);
LogUtils.d( "Exposure compensation already set to " + compensationSteps + " / " + actualCompensation);
} else {
Log.i(TAG, "Setting exposure compensation to " + compensationSteps + " / " + actualCompensation);
LogUtils.d( "Setting exposure compensation to " + compensationSteps + " / " + actualCompensation);
parameters.setExposureCompensation(compensationSteps);
}
} else {
Log.i(TAG, "Camera does not support exposure compensation");
LogUtils.d( "Camera does not support exposure compensation");
}
}
@@ -139,7 +137,7 @@ public final class CameraConfigurationUtils {
public static void setBestPreviewFPS(Camera.Parameters parameters, int minFPS, int maxFPS) {
List<int[]> supportedPreviewFpsRanges = parameters.getSupportedPreviewFpsRange();
Log.i(TAG, "Supported FPS ranges: " + toString(supportedPreviewFpsRanges));
LogUtils.d( "Supported FPS ranges: " + toString(supportedPreviewFpsRanges));
if (supportedPreviewFpsRanges != null && !supportedPreviewFpsRanges.isEmpty()) {
int[] suitableFPSRange = null;
for (int[] fpsRange : supportedPreviewFpsRanges) {
@@ -151,14 +149,14 @@ public final class CameraConfigurationUtils {
}
}
if (suitableFPSRange == null) {
Log.i(TAG, "No suitable FPS range?");
LogUtils.d( "No suitable FPS range?");
} else {
int[] currentFpsRange = new int[2];
parameters.getPreviewFpsRange(currentFpsRange);
if (Arrays.equals(currentFpsRange, suitableFPSRange)) {
Log.i(TAG, "FPS range already set to " + Arrays.toString(suitableFPSRange));
LogUtils.d( "FPS range already set to " + Arrays.toString(suitableFPSRange));
} else {
Log.i(TAG, "Setting FPS range to " + Arrays.toString(suitableFPSRange));
LogUtils.d( "Setting FPS range to " + Arrays.toString(suitableFPSRange));
parameters.setPreviewFpsRange(suitableFPSRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
suitableFPSRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
}
@@ -168,23 +166,23 @@ public final class CameraConfigurationUtils {
public static void setFocusArea(Camera.Parameters parameters) {
if (parameters.getMaxNumFocusAreas() > 0) {
Log.i(TAG, "Old focus areas: " + toString(parameters.getFocusAreas()));
LogUtils.d( "Old focus areas: " + toString(parameters.getFocusAreas()));
List<Camera.Area> middleArea = buildMiddleArea(AREA_PER_1000);
Log.i(TAG, "Setting focus area to : " + toString(middleArea));
LogUtils.d( "Setting focus area to : " + toString(middleArea));
parameters.setFocusAreas(middleArea);
} else {
Log.i(TAG, "Device does not support focus areas");
LogUtils.d( "Device does not support focus areas");
}
}
public static void setMetering(Camera.Parameters parameters) {
if (parameters.getMaxNumMeteringAreas() > 0) {
Log.i(TAG, "Old metering areas: " + parameters.getMeteringAreas());
LogUtils.d( "Old metering areas: " + parameters.getMeteringAreas());
List<Camera.Area> middleArea = buildMiddleArea(AREA_PER_1000);
Log.i(TAG, "Setting metering area to : " + toString(middleArea));
LogUtils.d( "Setting metering area to : " + toString(middleArea));
parameters.setMeteringAreas(middleArea);
} else {
Log.i(TAG, "Device does not support metering areas");
LogUtils.d( "Device does not support metering areas");
}
}
@@ -196,19 +194,19 @@ public final class CameraConfigurationUtils {
public static void setVideoStabilization(Camera.Parameters parameters) {
if (parameters.isVideoStabilizationSupported()) {
if (parameters.getVideoStabilization()) {
Log.i(TAG, "Video stabilization already enabled");
LogUtils.d( "Video stabilization already enabled");
} else {
Log.i(TAG, "Enabling video stabilization...");
LogUtils.d( "Enabling video stabilization...");
parameters.setVideoStabilization(true);
}
} else {
Log.i(TAG, "This device does not support video stabilization");
LogUtils.d( "This device does not support video stabilization");
}
}
public static void setBarcodeSceneMode(Camera.Parameters parameters) {
if (Camera.Parameters.SCENE_MODE_BARCODE.equals(parameters.getSceneMode())) {
Log.i(TAG, "Barcode scene mode already set");
LogUtils.d( "Barcode scene mode already set");
return;
}
String sceneMode = findSettableValue("scene mode",
@@ -226,22 +224,22 @@ public final class CameraConfigurationUtils {
return;
}
if (parameters.getZoom() == zoom) {
Log.i(TAG, "Zoom is already set to " + zoom);
LogUtils.d( "Zoom is already set to " + zoom);
} else {
Log.i(TAG, "Setting zoom to " + zoom);
LogUtils.d( "Setting zoom to " + zoom);
parameters.setZoom(zoom);
}
} else {
Log.i(TAG, "Zoom is not supported");
LogUtils.d( "Zoom is not supported");
}
}
private static Integer indexOfClosestZoom(Camera.Parameters parameters, double targetZoomRatio) {
List<Integer> ratios = parameters.getZoomRatios();
Log.i(TAG, "Zoom ratios: " + ratios);
LogUtils.d( "Zoom ratios: " + ratios);
int maxZoom = parameters.getMaxZoom();
if (ratios == null || ratios.isEmpty() || ratios.size() != maxZoom + 1) {
Log.w(TAG, "Invalid zoom ratios!");
LogUtils.w( "Invalid zoom ratios!");
return null;
}
double target100 = 100.0 * targetZoomRatio;
@@ -254,13 +252,13 @@ public final class CameraConfigurationUtils {
closestIndex = i;
}
}
Log.i(TAG, "Chose zoom ratio of " + (ratios.get(closestIndex) / 100.0));
LogUtils.d( "Chose zoom ratio of " + (ratios.get(closestIndex) / 100.0));
return closestIndex;
}
public static void setInvertColor(Camera.Parameters parameters) {
if (Camera.Parameters.EFFECT_NEGATIVE.equals(parameters.getColorEffect())) {
Log.i(TAG, "Negative effect already set");
LogUtils.d( "Negative effect already set");
return;
}
String colorMode = findSettableValue("color effect",
@@ -275,7 +273,7 @@ public final class CameraConfigurationUtils {
List<Camera.Size> rawSupportedSizes = parameters.getSupportedPreviewSizes();
if (rawSupportedSizes == null) {
Log.w(TAG, "Device returned no supported preview sizes; using default");
LogUtils.w( "Device returned no supported preview sizes; using default");
Camera.Size defaultSize = parameters.getPreviewSize();
if (defaultSize == null) {
throw new IllegalStateException("Parameters contained no preview size!");
@@ -284,12 +282,12 @@ public final class CameraConfigurationUtils {
}
if (Log.isLoggable(TAG, Log.INFO)) {
if (LogUtils.isShowLog()) {
StringBuilder previewSizesString = new StringBuilder();
for (Camera.Size size : rawSupportedSizes) {
previewSizesString.append(size.width).append('x').append(size.height).append(' ');
}
Log.i(TAG, "Supported preview sizes: " + previewSizesString);
LogUtils.d( "Supported preview sizes: " + previewSizesString);
}
double screenAspectRatio;
@@ -298,7 +296,7 @@ public final class CameraConfigurationUtils {
}else{
screenAspectRatio = screenResolution.y / (double) screenResolution.x;
}
Log.i(TAG, "screenAspectRatio: " + screenAspectRatio);
LogUtils.d( "screenAspectRatio: " + screenAspectRatio);
// Find a suitable size, with max resolution
int maxResolution = 0;
@@ -314,19 +312,19 @@ public final class CameraConfigurationUtils {
boolean isCandidatePortrait = realWidth < realHeight;
int maybeFlippedWidth = isCandidatePortrait ? realWidth: realHeight ;
int maybeFlippedHeight = isCandidatePortrait ? realHeight : realWidth;
Log.i(TAG, String.format("maybeFlipped:%d * %d",maybeFlippedWidth,maybeFlippedHeight));
LogUtils.d( String.format("maybeFlipped:%d * %d",maybeFlippedWidth,maybeFlippedHeight));
double aspectRatio = maybeFlippedWidth / (double) maybeFlippedHeight;
Log.i(TAG, "aspectRatio: " + aspectRatio);
LogUtils.d( "aspectRatio: " + aspectRatio);
double distortion = Math.abs(aspectRatio - screenAspectRatio);
Log.i(TAG, "distortion: " + distortion);
LogUtils.d( "distortion: " + distortion);
if (distortion > MAX_ASPECT_DISTORTION) {
continue;
}
if (maybeFlippedWidth == screenResolution.x && maybeFlippedHeight == screenResolution.y) {
Point exactPoint = new Point(realWidth, realHeight);
Log.i(TAG, "Found preview size exactly matching screen size: " + exactPoint);
LogUtils.d( "Found preview size exactly matching screen size: " + exactPoint);
return exactPoint;
}
@@ -342,7 +340,7 @@ public final class CameraConfigurationUtils {
// the CPU is much more powerful.
if (maxResPreviewSize != null) {
Point largestSize = new Point(maxResPreviewSize.width, maxResPreviewSize.height);
Log.i(TAG, "Using largest suitable preview size: " + largestSize);
LogUtils.d( "Using largest suitable preview size: " + largestSize);
return largestSize;
}
@@ -352,24 +350,24 @@ public final class CameraConfigurationUtils {
throw new IllegalStateException("Parameters contained no preview size!");
}
Point defaultSize = new Point(defaultPreview.width, defaultPreview.height);
Log.i(TAG, "No suitable preview sizes, using default: " + defaultSize);
LogUtils.d( "No suitable preview sizes, using default: " + defaultSize);
return defaultSize;
}
private static String findSettableValue(String name,
Collection<String> supportedValues,
String... desiredValues) {
Log.i(TAG, "Requesting " + name + " value from among: " + Arrays.toString(desiredValues));
Log.i(TAG, "Supported " + name + " values: " + supportedValues);
LogUtils.d( "Requesting " + name + " value from among: " + Arrays.toString(desiredValues));
LogUtils.d( "Supported " + name + " values: " + supportedValues);
if (supportedValues != null) {
for (String desiredValue : desiredValues) {
if (supportedValues.contains(desiredValue)) {
Log.i(TAG, "Can set " + name + " to: " + desiredValue);
LogUtils.d( "Can set " + name + " to: " + desiredValue);
return desiredValue;
}
}
}
Log.i(TAG, "No supported values match");
LogUtils.d( "No supported values match");
return null;
}

View File

@@ -21,13 +21,14 @@ import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.Camera;
import android.media.FaceDetector;
import android.os.Handler;
import android.util.Log;
import android.support.annotation.FloatRange;
import android.view.SurfaceHolder;
import com.google.zxing.PlanarYUVLuminanceSource;
import com.king.zxing.camera.open.OpenCamera;
import com.king.zxing.camera.open.OpenCameraInterface;
import com.king.zxing.util.LogUtils;
import java.io.IOException;
@@ -41,8 +42,6 @@ import java.io.IOException;
@SuppressWarnings("deprecation") // camera APIs
public final class CameraManager {
private static final String TAG = CameraManager.class.getSimpleName();
private static final int MIN_FRAME_WIDTH = 240;
private static final int MIN_FRAME_HEIGHT = 240;
private static final int MAX_FRAME_WIDTH = 1200; // = 5/8 * 1920
@@ -61,12 +60,21 @@ public final class CameraManager {
private int requestedFramingRectHeight;
private boolean isFullScreenScan;
private float framingRectRatio;
private int framingRectVerticalOffset;
private int framingRectHorizontalOffset;
/**
* Preview frames are delivered here, which we pass on to the registered handler. Make sure to
* clear the handler so it will only receive one message.
*/
private final PreviewCallback previewCallback;
private OnTorchListener onTorchListener;
private OnSensorListener onSensorListener;
private boolean isTorch;
public CameraManager(Context context) {
this.context = context.getApplicationContext();
this.configManager = new CameraConfigurationManager(context);
@@ -79,7 +87,7 @@ public final class CameraManager {
* @param holder The surface object which the camera will draw preview frames into.
* @throws IOException Indicates the camera driver failed to open.
*/
public synchronized void openDriver(SurfaceHolder holder) throws IOException {
public void openDriver(SurfaceHolder holder) throws IOException {
OpenCamera theCamera = camera;
if (theCamera == null) {
theCamera = OpenCameraInterface.open(requestedCameraId);
@@ -106,8 +114,8 @@ public final class CameraManager {
configManager.setDesiredCameraParameters(theCamera, false);
} catch (RuntimeException re) {
// Driver failed
Log.w(TAG, "Camera rejected parameters. Setting only minimal safe-mode parameters");
Log.i(TAG, "Resetting to saved camera params: " + parametersFlattened);
LogUtils.w( "Camera rejected parameters. Setting only minimal safe-mode parameters");
LogUtils.i( "Resetting to saved camera params: " + parametersFlattened);
// Reset:
if (parametersFlattened != null) {
parameters = cameraObject.getParameters();
@@ -117,7 +125,7 @@ public final class CameraManager {
configManager.setDesiredCameraParameters(theCamera, true);
} catch (RuntimeException re2) {
// Well, darn. Give up
Log.w(TAG, "Camera rejected even safe-mode parameters! No configuration");
LogUtils.w( "Camera rejected even safe-mode parameters! No configuration");
}
}
}
@@ -136,7 +144,7 @@ public final class CameraManager {
/**
* Closes the camera driver if still in use.
*/
public synchronized void closeDriver() {
public void closeDriver() {
if (camera != null) {
camera.getCamera().release();
camera = null;
@@ -145,12 +153,16 @@ public final class CameraManager {
framingRect = null;
framingRectInPreview = null;
}
isTorch = false;
if(onTorchListener!=null){
onTorchListener.onTorchChanged(false);
}
}
/**
* Asks the camera hardware to begin drawing preview frames to the screen.
*/
public synchronized void startPreview() {
public void startPreview() {
OpenCamera theCamera = camera;
if (theCamera != null && !previewing) {
theCamera.getCamera().startPreview();
@@ -162,7 +174,7 @@ public final class CameraManager {
/**
* Tells the camera to stop drawing preview frames.
*/
public synchronized void stopPreview() {
public void stopPreview() {
if (autoFocusManager != null) {
autoFocusManager.stop();
autoFocusManager = null;
@@ -172,6 +184,7 @@ public final class CameraManager {
previewCallback.setHandler(null, 0);
previewing = false;
}
}
/**
@@ -187,14 +200,22 @@ public final class CameraManager {
autoFocusManager.stop();
autoFocusManager = null;
}
this.isTorch = newSetting;
configManager.setTorch(theCamera.getCamera(), newSetting);
if (wasAutoFocusManager) {
autoFocusManager = new AutoFocusManager(context, theCamera.getCamera());
autoFocusManager.start();
}
if(onTorchListener!=null){
onTorchListener.onTorchChanged(newSetting);
}
}
}
/**
* A single preview frame will be returned to the handler supplied. The data will arrive as byte[]
* in the message.obj field, with width and height encoded as message.arg1 and message.arg2,
@@ -235,10 +256,10 @@ public final class CameraManager {
if(isFullScreenScan){
framingRect = new Rect(0,0,width,height);
}else{
int size = Math.min(width,height);
int size = (int)(Math.min(width,height) * framingRectRatio);
int leftOffset = (width - size) / 2;
int topOffset = (height - size) / 2;
int leftOffset = (width - size) / 2 + framingRectHorizontalOffset;
int topOffset = (height - size) / 2 + framingRectVerticalOffset;
framingRect = new Rect(leftOffset, topOffset, leftOffset + size, topOffset + size);
}
@@ -284,14 +305,22 @@ public final class CameraManager {
return framingRectInPreview;
}
public boolean isFullScreenScan() {
return isFullScreenScan;
}
public void setFullScreenScan(boolean fullScreenScan) {
isFullScreenScan = fullScreenScan;
}
public void setFramingRectRatio(@FloatRange(from = 0.0f ,to = 1.0f) float framingRectRatio) {
this.framingRectRatio = framingRectRatio;
}
public void setFramingRectVerticalOffset(int framingRectVerticalOffset) {
this.framingRectVerticalOffset = framingRectVerticalOffset;
}
public void setFramingRectHorizontalOffset(int framingRectHorizontalOffset) {
this.framingRectHorizontalOffset = framingRectHorizontalOffset;
}
public Point getCameraResolution() {
return configManager.getCameraResolution();
}
@@ -329,7 +358,7 @@ public final class CameraManager {
int leftOffset = (screenResolution.x - width) / 2;
int topOffset = (screenResolution.y - height) / 2;
framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
Log.d(TAG, "Calculated manual framing rect: " + framingRect);
LogUtils.d( "Calculated manual framing rect: " + framingRect);
framingRectInPreview = null;
} else {
requestedFramingRectWidth = width;
@@ -355,12 +384,57 @@ public final class CameraManager {
if(isFullScreenScan){
return new PlanarYUVLuminanceSource(data,width,height,0,0,width,height,false);
}
int size = Math.min(width,height);
int left = (width-size)/2;
int top = (height-size)/2;
int size = (int)(Math.min(width,height) * framingRectRatio);
int left = (width-size)/2 + framingRectHorizontalOffset;
int top = (height-size)/2 + framingRectVerticalOffset;
// Go ahead and assume it's YUV rather than die.
return new PlanarYUVLuminanceSource(data, width, height, left, top,
size, size, false);
}
/**
* 提供闪光灯监听
* @param listener
*/
public void setOnTorchListener(OnTorchListener listener){
this.onTorchListener = listener;
}
/**
* 传感器光线照度监听
* @param listener
*/
public void setOnSensorListener(OnSensorListener listener){
this.onSensorListener = listener;
}
public void sensorChanged(boolean tooDark,float ambientLightLux){
if(onSensorListener!=null){
onSensorListener.onSensorChanged(isTorch,tooDark,ambientLightLux);
}
}
public interface OnTorchListener{
/**
* 当闪光灯状态改变时触发
* @param torch true表示开启、false表示关闭
*/
void onTorchChanged(boolean torch);
}
/**
* 传感器灯光亮度监听
*/
public interface OnSensorListener{
/**
*
* @param torch 闪光灯是否开启
* @param tooDark 传感器检测到的光线亮度,是否太暗
* @param ambientLightLux 光线照度
*/
void onSensorChanged(boolean torch,boolean tooDark,float ambientLightLux);
}
}

View File

@@ -16,7 +16,9 @@ package com.king.zxing.camera;
*/
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import com.king.zxing.Preferences;
@@ -33,11 +35,16 @@ public enum FrontLightMode {
OFF;
private static FrontLightMode parse(String modeString) {
return modeString == null ? OFF : valueOf(modeString);
return modeString == null ? AUTO : valueOf(modeString);
}
public static FrontLightMode readPref(SharedPreferences sharedPrefs) {
return parse(sharedPrefs.getString(Preferences.KEY_FRONT_LIGHT_MODE, OFF.toString()));
return parse(sharedPrefs.getString(Preferences.KEY_FRONT_LIGHT_MODE, AUTO.toString()));
}
public static void put(Context context, FrontLightMode mode) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
prefs.edit().putString(Preferences.KEY_FRONT_LIGHT_MODE, mode.toString()).commit();
}
}

View File

@@ -21,13 +21,12 @@ import android.graphics.Point;
import android.hardware.Camera;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import com.king.zxing.util.LogUtils;
@SuppressWarnings("deprecation") // camera APIs
final class PreviewCallback implements Camera.PreviewCallback {
private static final String TAG = PreviewCallback.class.getSimpleName();
private final CameraConfigurationManager configManager;
private Handler previewHandler;
private int previewMessage;
@@ -51,7 +50,7 @@ final class PreviewCallback implements Camera.PreviewCallback {
message.sendToTarget();
previewHandler = null;
} else {
Log.d(TAG, "Got preview callback, but no handler or resolution available");
LogUtils.d( "Got preview callback, but no handler or resolution available");
}
}

View File

@@ -18,7 +18,8 @@ package com.king.zxing.camera.open;
import android.hardware.Camera;
import android.util.Log;
import com.king.zxing.util.LogUtils;
/**
* Abstraction over the {@link Camera} API that helps open them and return their metadata.
@@ -26,8 +27,6 @@ import android.util.Log;
@SuppressWarnings("deprecation") // camera APIs
public final class OpenCameraInterface {
private static final String TAG = OpenCameraInterface.class.getName();
/**
* For {@link #open(int)}, means no preference for which camera to open.
*/
@@ -48,11 +47,11 @@ public final class OpenCameraInterface {
int numCameras = Camera.getNumberOfCameras();
if (numCameras == 0) {
Log.w(TAG, "No cameras!");
LogUtils.w( "No cameras!");
return null;
}
if (cameraId >= numCameras) {
Log.w(TAG, "Requested camera does not exist: " + cameraId);
LogUtils.w( "Requested camera does not exist: " + cameraId);
return null;
}
@@ -67,12 +66,12 @@ public final class OpenCameraInterface {
cameraId++;
}
if (cameraId == numCameras) {
Log.i(TAG, "No camera facing " + CameraFacing.BACK + "; returning camera #0");
LogUtils.i("No camera facing " + CameraFacing.BACK + "; returning camera #0");
cameraId = 0;
}
}
Log.i(TAG, "Opening camera #" + cameraId);
LogUtils.i("Opening camera #" + cameraId);
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, cameraInfo);
Camera camera = Camera.open(cameraId);

View File

@@ -21,6 +21,7 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.annotation.ColorInt;
import android.support.annotation.FloatRange;
import android.support.annotation.NonNull;
import android.text.TextPaint;
import android.text.TextUtils;
@@ -31,7 +32,6 @@ import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.NotFoundException;
import com.google.zxing.RGBLuminanceSource;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
@@ -51,7 +51,10 @@ import java.util.Vector;
/**
* @author Jenly <a href="mailto:jenly1314@gmail.com">Jenly</a>
*/
public class CodeUtils {
public final class CodeUtils {
public static final int DEFAULT_REQ_WIDTH = 450;
public static final int DEFAULT_REQ_HEIGHT = 800;
private CodeUtils(){
throw new AssertionError();
@@ -59,8 +62,8 @@ public class CodeUtils {
/**
* 生成二维码
* @param content
* @param heightPix
* @param content 二维码的内容
* @param heightPix 二维码的高
* @return
*/
public static Bitmap createQRCode(String content, int heightPix) {
@@ -69,12 +72,47 @@ public class CodeUtils {
/**
* 生成二维码
* @param content
* @param heightPix
* @param logo
* @param content 二维码的内容
* @param heightPix 二维码的高
* @param codeColor 二维码的颜色
* @return
*/
public static Bitmap createQRCode(String content, int heightPix,int codeColor) {
return createQRCode(content,heightPix,null,codeColor);
}
/**
* 生成我二维码
* @param content 二维码的内容
* @param heightPix 二维码的高
* @param logo logo大小默认占二维码的20%
* @return
*/
public static Bitmap createQRCode(String content, int heightPix, Bitmap logo) {
return createQRCode(content,heightPix,logo,Color.BLACK);
}
/**
* 生成我二维码
* @param content 二维码的内容
* @param heightPix 二维码的高
* @param logo logo大小默认占二维码的20%
* @param codeColor 二维码的颜色
* @return
*/
public static Bitmap createQRCode(String content, int heightPix, Bitmap logo,int codeColor) {
return createQRCode(content,heightPix,logo,0.2f,codeColor);
}
/**
* 生成二维码
* @param content 二维码的内容
* @param heightPix 二维码的高
* @param logo 二维码中间的logo
* @param ratio logo所占比例 因为二维码的最大容错率为30%所以建议ratio的范围小于0.3
* @return
*/
public static Bitmap createQRCode(String content, int heightPix, Bitmap logo,@FloatRange(from = 0.0f,to = 1.0f)float ratio) {
//配置参数
Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put( EncodeHintType.CHARACTER_SET, "utf-8");
@@ -82,18 +120,44 @@ public class CodeUtils {
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
//设置空白边距的宽度
hints.put(EncodeHintType.MARGIN, 1); //default is 4
return createQRCode(content,heightPix,logo,hints);
return createQRCode(content,heightPix,logo,ratio,hints);
}
/**
* 生成二维码
* @param content
* @param heightPix
* @param logo
* @param hints
* @param content 二维码的内容
* @param heightPix 二维码的高
* @param logo 二维码中间的logo
* @param ratio logo所占比例 因为二维码的最大容错率为30%所以建议ratio的范围小于0.3
* @param codeColor 二维码的颜色
* @return
*/
public static Bitmap createQRCode(String content, int heightPix, Bitmap logo,Map<EncodeHintType,?> hints) {
public static Bitmap createQRCode(String content, int heightPix, Bitmap logo,@FloatRange(from = 0.0f,to = 1.0f)float ratio,int codeColor) {
//配置参数
Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put( EncodeHintType.CHARACTER_SET, "utf-8");
//容错级别
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
//设置空白边距的宽度
hints.put(EncodeHintType.MARGIN, 1); //default is 1
return createQRCode(content,heightPix,logo,ratio,hints,codeColor);
}
public static Bitmap createQRCode(String content, int heightPix, Bitmap logo,@FloatRange(from = 0.0f,to = 1.0f)float ratio,Map<EncodeHintType,?> hints) {
return createQRCode(content,heightPix,logo,ratio,hints,Color.BLACK);
}
/**
* 生成二维码
* @param content 二维码的内容
* @param heightPix 二维码的高
* @param logo 二维码中间的logo
* @param ratio logo所占比例 因为二维码的最大容错率为30%所以建议ratio的范围小于0.3
* @param hints
* @param codeColor 二维码的颜色
* @return
*/
public static Bitmap createQRCode(String content, int heightPix, Bitmap logo,@FloatRange(from = 0.0f,to = 1.0f)float ratio,Map<EncodeHintType,?> hints,int codeColor) {
try {
// 图像数据转换,使用了矩阵转换
@@ -104,9 +168,9 @@ public class CodeUtils {
for (int y = 0; y < heightPix; y++) {
for (int x = 0; x < heightPix; x++) {
if (bitMatrix.get(x, y)) {
pixels[y * heightPix + x] = 0xff000000;
pixels[y * heightPix + x] = codeColor;
} else {
pixels[y * heightPix + x] = 0xffffffff;
pixels[y * heightPix + x] = Color.WHITE;
}
}
}
@@ -116,12 +180,12 @@ public class CodeUtils {
bitmap.setPixels(pixels, 0, heightPix, 0, 0, heightPix, heightPix);
if (logo != null) {
bitmap = addLogo(bitmap, logo);
bitmap = addLogo(bitmap, logo,ratio);
}
return bitmap;
} catch (WriterException e) {
e.printStackTrace();
LogUtils.w(e.getMessage());
}
return null;
@@ -129,8 +193,12 @@ public class CodeUtils {
/**
* 在二维码中间添加Logo图案
* @param src
* @param logo
* @param ratio logo所占比例 因为二维码的最大容错率为30%所以建议ratio的范围小于0.3
* @return
*/
private static Bitmap addLogo(Bitmap src, Bitmap logo) {
private static Bitmap addLogo(Bitmap src, Bitmap logo,@FloatRange(from = 0.0f,to = 1.0f) float ratio) {
if (src == null) {
return null;
}
@@ -153,8 +221,8 @@ public class CodeUtils {
return src;
}
//logo大小为二维码整体大小的1/6
float scaleFactor = srcWidth * 1.0f / 6 / logoWidth;
//logo大小为二维码整体大小
float scaleFactor = srcWidth * ratio / logoWidth;
Bitmap bitmap = Bitmap.createBitmap(srcWidth, srcHeight, Bitmap.Config.ARGB_8888);
try {
Canvas canvas = new Canvas(bitmap);
@@ -165,7 +233,7 @@ public class CodeUtils {
canvas.restore();
} catch (Exception e) {
bitmap = null;
e.printStackTrace();
LogUtils.w(e.getMessage());
}
return bitmap;
@@ -179,6 +247,7 @@ public class CodeUtils {
public static String parseQRCode(String bitmapPath) {
Map<DecodeHintType, Object> hints = new HashMap<>();
hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
return parseQRCode(bitmapPath,hints);
}
@@ -189,35 +258,87 @@ public class CodeUtils {
* @return
*/
public static String parseQRCode(String bitmapPath, Map<DecodeHintType,?> hints){
try {
QRCodeReader reader = new QRCodeReader();
Result result = null;
RGBLuminanceSource source = getRGBLuminanceSource(compressBitmap(bitmapPath));
if (source != null) {
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
try {
result = reader.decode(bitmap,hints);
} catch (Exception e) {
//解析失败则通过GlobalHistogramBinarizer 再试一次
BinaryBitmap bitmap1 = new BinaryBitmap(new GlobalHistogramBinarizer(source));
try {
result = reader.decode(bitmap1);
} catch (NotFoundException ne) {
}
} finally {
reader.reset();
}
}
Result result = parseQRCodeResult(bitmapPath,hints);
if(result != null){
return result.getText();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 解析二维码图片
* @param bitmapPath
* @param hints
* @return
*/
public static Result parseQRCodeResult(String bitmapPath, Map<DecodeHintType,?> hints){
return parseQRCodeResult(bitmapPath,DEFAULT_REQ_WIDTH,DEFAULT_REQ_HEIGHT,hints);
}
/**
* 解析二维码图片
* @param bitmapPath
* @param reqWidth
* @param reqHeight
* @param hints
* @return
*/
public static Result parseQRCodeResult(String bitmapPath,int reqWidth,int reqHeight,Map<DecodeHintType,?> hints){
Result result = null;
try{
QRCodeReader reader = new QRCodeReader();
RGBLuminanceSource source = getRGBLuminanceSource(compressBitmap(bitmapPath,reqWidth,reqHeight));
if (source != null) {
boolean isReDecode;
try {
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
result = reader.decode(bitmap,hints);
isReDecode = false;
} catch (Exception e) {
isReDecode = true;
}
if(isReDecode){
try {
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source.invert()));
result = reader.decode(bitmap,hints);
isReDecode = false;
} catch (Exception e) {
isReDecode = true;
}
}
if(isReDecode){
try{
BinaryBitmap bitmap = new BinaryBitmap(new GlobalHistogramBinarizer(source));
result = reader.decode(bitmap,hints);
isReDecode = false;
}catch (Exception e){
isReDecode = true;
}
}
if(isReDecode && source.isRotateSupported()){
try{
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source.rotateCounterClockwise()));
result = reader.decode(bitmap,hints);
}catch (Exception e){
}
}
reader.reset();
}
}catch (Exception e){
LogUtils.w(e.getMessage());
}
return result;
}
/**
* 解析一维码/二维码图片
* @param bitmapPath
@@ -233,6 +354,7 @@ public class CodeUtils {
decodeFormats.addAll(DecodeFormatManager.AZTEC_FORMATS);
decodeFormats.addAll(DecodeFormatManager.PDF417_FORMATS);
hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
hints.put(DecodeHintType.TRY_HARDER,Boolean.TRUE);
hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats);
return parseCode(bitmapPath,hints);
@@ -245,34 +367,88 @@ public class CodeUtils {
* @return
*/
public static String parseCode(String bitmapPath, Map<DecodeHintType,Object> hints){
try {
MultiFormatReader reader = new MultiFormatReader();
reader.setHints(hints);
Result result = null;
RGBLuminanceSource source = getRGBLuminanceSource(compressBitmap(bitmapPath));
if (source != null) {
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
try {
result = reader.decodeWithState(bitmap);
} catch (Exception e) {//解析失败则通过GlobalHistogramBinarizer 再试一次
BinaryBitmap bitmap1 = new BinaryBitmap(new GlobalHistogramBinarizer(source));
try {
result = reader.decodeWithState(bitmap1);
} catch (Exception ne) {
}
} finally {
reader.reset();
}
}
Result result = parseCodeResult(bitmapPath,hints);
if(result != null){
return result.getText();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 解析一维码/二维码图片
* @param bitmapPath
* @param hints 解析编码类型
* @return
*/
public static Result parseCodeResult(String bitmapPath, Map<DecodeHintType,Object> hints){
return parseCodeResult(bitmapPath,DEFAULT_REQ_WIDTH,DEFAULT_REQ_HEIGHT,hints);
}
/**
* 解析一维码/二维码图片
* @param bitmapPath
* @param reqWidth
* @param reqHeight
* @param hints 解析编码类型
* @return
*/
public static Result parseCodeResult(String bitmapPath,int reqWidth,int reqHeight, Map<DecodeHintType,Object> hints){
Result result = null;
try{
MultiFormatReader reader = new MultiFormatReader();
reader.setHints(hints);
RGBLuminanceSource source = getRGBLuminanceSource(compressBitmap(bitmapPath,reqWidth,reqHeight));
if (source != null) {
boolean isReDecode;
try {
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
result = reader.decodeWithState(bitmap);
isReDecode = false;
} catch (Exception e) {
isReDecode = true;
}
if(isReDecode){
try {
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source.invert()));
result = reader.decodeWithState(bitmap);
isReDecode = false;
} catch (Exception e) {
isReDecode = true;
}
}
if(isReDecode){
try{
BinaryBitmap bitmap = new BinaryBitmap(new GlobalHistogramBinarizer(source));
result = reader.decodeWithState(bitmap);
isReDecode = false;
}catch (Exception e){
isReDecode = true;
}
}
if(isReDecode && source.isRotateSupported()){
try{
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source.rotateCounterClockwise()));
result = reader.decodeWithState(bitmap);
}catch (Exception e){
}
}
reader.reset();
}
}catch (Exception e){
LogUtils.w(e.getMessage());
}
return result;
}
/**
@@ -280,31 +456,33 @@ public class CodeUtils {
* @param path
* @return
*/
private static Bitmap compressBitmap(String path){
private static Bitmap compressBitmap(String path,int reqWidth,int reqHeight){
BitmapFactory.Options newOpts = new BitmapFactory.Options();
// 开始读入图片此时把options.inJustDecodeBounds 设回true了
newOpts.inJustDecodeBounds = true;//获取原始图片大小
BitmapFactory.decodeFile(path, newOpts);// 此时返回bm为空
int w = newOpts.outWidth;
int h = newOpts.outHeight;
float width = 800f;
float height = 480f;
// 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
int be = 1;// be=1表示不缩放
if (w > h && w > width) {// 如果宽度大的话根据宽度固定大小缩放
be = (int) (newOpts.outWidth / width);
} else if (w < h && h > height) {// 如果高度高的话根据宽度固定大小缩放
be = (int) (newOpts.outHeight / height);
float width = newOpts.outWidth;
float height = newOpts.outHeight;
// 缩放比,由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
int wSize = 1;// wSize=1表示不缩放
if (width > reqWidth) {// 如果宽度大的话根据宽度固定大小缩放
wSize = (int) (width / reqWidth);
}
if (be <= 0)
be = 1;
newOpts.inSampleSize = be;// 设置缩放比例
int hSize = 1;// wSize=1表示不缩放
if (height > reqHeight) {// 如果高度高的话根据宽度固定大小缩放
hSize = (int) (height / reqHeight);
}
int size = Math.max(wSize,hSize);
if (size <= 0)
size = 1;
newOpts.inSampleSize = size;// 设置缩放比例
// 重新读入图片注意此时已经把options.inJustDecodeBounds 设回false了
newOpts.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(path, newOpts);
}
/**
* 获取RGBLuminanceSource
* @param bitmap
@@ -320,6 +498,17 @@ public class CodeUtils {
}
/**
* 生成条形码
* @param content
* @param desiredWidth
* @param desiredHeight
* @return
*/
public static Bitmap createBarCode(String content, int desiredWidth, int desiredHeight) {
return createBarCode(content,BarcodeFormat.CODE_128,desiredWidth,desiredHeight,null);
}
/**
* 生成条形码
* @param content
@@ -330,7 +519,23 @@ public class CodeUtils {
*/
public static Bitmap createBarCode(String content,BarcodeFormat format, int desiredWidth, int desiredHeight) {
return createBarCode(content,format,desiredWidth,desiredHeight,null);
}
public static Bitmap createBarCode(String content, int desiredWidth, int desiredHeight, boolean isShowText) {
return createBarCode(content,BarcodeFormat.CODE_128,desiredWidth,desiredHeight,null,isShowText,40,Color.BLACK);
}
/**
* 生成条形码
* @param content
* @param desiredWidth
* @param desiredHeight
* @param isShowText
* @param codeColor
* @return
*/
public static Bitmap createBarCode(String content, int desiredWidth, int desiredHeight, boolean isShowText,@ColorInt int codeColor) {
return createBarCode(content,BarcodeFormat.CODE_128,desiredWidth,desiredHeight,null,isShowText,40,codeColor);
}
/**
@@ -360,6 +565,34 @@ public class CodeUtils {
return createBarCode(content,format,desiredWidth,desiredHeight,hints,isShowText,40,Color.BLACK);
}
/**
* 生成条形码
* @param content
* @param format
* @param desiredWidth
* @param desiredHeight
* @param isShowText
* @param codeColor
* @return
*/
public static Bitmap createBarCode(String content, BarcodeFormat format, int desiredWidth, int desiredHeight, boolean isShowText,@ColorInt int codeColor) {
return createBarCode(content,format,desiredWidth,desiredHeight,null,isShowText,40,codeColor);
}
/**
* 生成条形码
* @param content
* @param format
* @param desiredWidth
* @param desiredHeight
* @param hints
* @param isShowText
* @return
*/
public static Bitmap createBarCode(String content, BarcodeFormat format, int desiredWidth, int desiredHeight, Map<EncodeHintType,?> hints, boolean isShowText,@ColorInt int codeColor) {
return createBarCode(content,format,desiredWidth,desiredHeight,hints,isShowText,40,codeColor);
}
/**
* 生成条形码
* @param content
@@ -369,15 +602,15 @@ public class CodeUtils {
* @param hints
* @param isShowText
* @param textSize
* @param textColor
* @param codeColor
* @return
*/
public static Bitmap createBarCode(String content,BarcodeFormat format, int desiredWidth, int desiredHeight,Map<EncodeHintType,?> hints,boolean isShowText,int textSize,@ColorInt int textColor) {
public static Bitmap createBarCode(String content,BarcodeFormat format, int desiredWidth, int desiredHeight,Map<EncodeHintType,?> hints,boolean isShowText,int textSize,@ColorInt int codeColor) {
if(TextUtils.isEmpty(content)){
return null;
}
final int WHITE = 0xFFFFFFFF;
final int BLACK = 0xFF000000;
final int WHITE = Color.WHITE;
final int BLACK = codeColor;
MultiFormatWriter writer = new MultiFormatWriter();
try {
@@ -398,11 +631,11 @@ public class CodeUtils {
Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
if(isShowText){
return addCode(bitmap,content,textSize,textColor,textSize/2);
return addCode(bitmap,content,textSize,codeColor,textSize/2);
}
return bitmap;
} catch (WriterException e) {
e.printStackTrace();
LogUtils.w(e.getMessage());
}
return null;
}
@@ -445,10 +678,10 @@ public class CodeUtils {
canvas.restore();
} catch (Exception e) {
bitmap = null;
e.printStackTrace();
LogUtils.w(e.getMessage());
}
return bitmap;
}
}
}

View File

@@ -0,0 +1,316 @@
/*
Copyright © 2015, 2016 Jenly Yu <a href="mailto:jenly1314@gmail.com">Jenly</a>
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.king.zxing.util;
import android.util.Log;
/**
* @author Jenly <a href="mailto:jenly1314@gmail.com">Jenly</a>
*/
public class LogUtils {
public static final String TAG = "ZXingLite";
public static final String COLON = ":";
public static final String VERTICAL = "|";
/** 是否显示Log日志 */
private static boolean isShowLog = true;
/** Log日志优先权 */
private static int priority = 1;
/**
* Priority constant for the println method;use System.out.println
*/
public static final int PRINTLN = 1;
/**
* Priority constant for the println method; use Log.v.
*/
public static final int VERBOSE = 2;
/**
* Priority constant for the println method; use Log.d.
*/
public static final int DEBUG = 3;
/**
* Priority constant for the println method; use Log.i.
*/
public static final int INFO = 4;
/**
* Priority constant for the println method; use Log.w.
*/
public static final int WARN = 5;
/**
* Priority constant for the println method; use Log.e.
*/
public static final int ERROR = 6;
/**
* Priority constant for the println method.use Log.wtf.
*/
public static final int ASSERT = 7;
public static final String TAG_FORMAT = "%s.%s(L:%d)";
private LogUtils(){
throw new AssertionError();
}
public static void setShowLog(boolean isShowLog) {
LogUtils.isShowLog = isShowLog;
}
public static boolean isShowLog() {
return isShowLog;
}
public static int getPriority() {
return priority;
}
public static void setPriority(int priority) {
LogUtils.priority = priority;
}
/**
* 根据堆栈生成TAG
* @return TAG|className.methodName(L:lineNumber)
*/
private static String generateTag(StackTraceElement caller) {
String tag = TAG_FORMAT;
String callerClazzName = caller.getClassName();
callerClazzName = callerClazzName.substring(callerClazzName.lastIndexOf(".") + 1);
tag = String.format(tag,new Object[] { callerClazzName, caller.getMethodName(),Integer.valueOf(caller.getLineNumber()) });
return new StringBuilder().append(TAG).append(VERTICAL).append(tag).toString();
}
/**
* 获取堆栈
* @param n
* n=0 VMStack
* n=1 Thread
* n=3 CurrentStack
* n=4 CallerStack
* ...
* @return
*/
public static StackTraceElement getStackTraceElement(int n) {
return Thread.currentThread().getStackTrace()[n];
}
/**
* 获取调用方的堆栈TAG
* @return
*/
private static String getCallerStackLogTag(){
return generateTag(getStackTraceElement(5));
}
/**
*
* @param t
* @return
*/
private static String getStackTraceString(Throwable t){
return Log.getStackTraceString(t);
}
// -----------------------------------Log.v
/**
* Log.v
* @param msg
*/
public static void v(String msg) {
if (isShowLog && priority <= VERBOSE)
Log.v(getCallerStackLogTag(), String.valueOf(msg));
}
public static void v(Throwable t) {
if (isShowLog && priority <= VERBOSE)
Log.v(getCallerStackLogTag(), getStackTraceString(t));
}
public static void v(String msg,Throwable t) {
if (isShowLog && priority <= VERBOSE)
Log.v(getCallerStackLogTag(), String.valueOf(msg), t);
}
// -----------------------------------Log.d
/**
* Log.d
* @param msg
*/
public static void d(String msg) {
if (isShowLog && priority <= DEBUG)
Log.d(getCallerStackLogTag(), String.valueOf(msg));
}
public static void d(Throwable t) {
if (isShowLog && priority <= DEBUG)
Log.d(getCallerStackLogTag(), getStackTraceString(t));
}
public static void d(String msg,Throwable t) {
if (isShowLog && priority <= DEBUG)
Log.d(getCallerStackLogTag(), String.valueOf(msg), t);
}
// -----------------------------------Log.i
/**
* Log.i
* @param msg
*/
public static void i(String msg) {
if (isShowLog && priority <= INFO)
Log.i(getCallerStackLogTag(), String.valueOf(msg));
}
public static void i(Throwable t) {
if (isShowLog && priority <= INFO)
Log.i(getCallerStackLogTag(), getStackTraceString(t));
}
public static void i(String msg,Throwable t) {
if (isShowLog && priority <= INFO)
Log.i(getCallerStackLogTag(), String.valueOf(msg), t);
}
// -----------------------------------Log.w
/**
* Log.w
* @param msg
*/
public static void w(String msg) {
if (isShowLog && priority <= WARN)
Log.w(getCallerStackLogTag(), String.valueOf(msg));
}
public static void w(Throwable t) {
if (isShowLog && priority <= WARN)
Log.w(getCallerStackLogTag(), getStackTraceString(t));
}
public static void w(String msg,Throwable t) {
if (isShowLog && priority <= WARN)
Log.w(getCallerStackLogTag(), String.valueOf(msg), t);
}
// -----------------------------------Log.e
/**
* Log.e
* @param msg
*/
public static void e(String msg) {
if (isShowLog && priority <= ERROR)
Log.e(getCallerStackLogTag(), String.valueOf(msg));
}
public static void e(Throwable t) {
if (isShowLog && priority <= ERROR)
Log.e(getCallerStackLogTag(), getStackTraceString(t));
}
public static void e(String msg,Throwable t) {
if (isShowLog && priority <= ERROR)
Log.e(getCallerStackLogTag(), String.valueOf(msg), t);
}
// -----------------------------------Log.wtf
/**
* Log.wtf
* @param msg
*/
public static void wtf(String msg) {
if (isShowLog && priority <= ASSERT)
Log.wtf(getCallerStackLogTag(), String.valueOf(msg));
}
public static void wtf(Throwable t) {
if (isShowLog && priority <= ASSERT)
Log.wtf(getCallerStackLogTag(), getStackTraceString(t));
}
public static void wtf(String msg,Throwable t) {
if (isShowLog && priority <= ASSERT)
Log.wtf(getCallerStackLogTag(), String.valueOf(msg), t);
}
// -----------------------------------System.out.print
/**
* System.out.print
*
* @param msg
*/
public static void print(String msg) {
if (isShowLog && priority <= PRINTLN)
System.out.print(msg);
}
public static void print(Object obj) {
if (isShowLog && priority <= PRINTLN)
System.out.print(obj);
}
// -----------------------------------System.out.printf
/**
* System.out.printf
*
* @param msg
*/
public static void printf(String msg) {
if (isShowLog && priority <= PRINTLN)
System.out.printf(msg);
}
// -----------------------------------System.out.println
/**
* System.out.println
*
* @param msg
*/
public static void println(String msg) {
if (isShowLog && priority <= PRINTLN)
System.out.println(msg);
}
public static void println(Object obj) {
if (isShowLog && priority <= PRINTLN)
System.out.println(obj);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/zxl_torch_on"/>
<item android:drawable="@drawable/zxl_torch_off"/>
</selector>

View File

@@ -23,5 +23,11 @@
android:id="@+id/viewfinderView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<ImageView
android:id="@+id/ivTorch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/zxl_torch_selector"
android:layout_marginTop="@dimen/torchMarginTop" />
</FrameLayout>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="CaptureTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="colorPrimary">@android:color/black</item>
<item name="colorPrimaryDark">@android:color/black</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
</resources>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="CaptureTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="colorPrimary">@android:color/black</item>
<item name="colorPrimaryDark">@android:color/black</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:statusBarColor">@color/capture_status_bar_color</item>
<item name="android:navigationBarColor">@color/capture_navigation_bar_color</item>
</style>
</resources>

View File

@@ -23,6 +23,14 @@
<enum name="line" value="1"/>
<enum name="grid" value="2"/>
</attr>
<attr name="cornerRectWidth" format="dimension"/>
<attr name="cornerRectHeight" format="dimension"/>
<attr name="scannerLineMoveDistance" format="dimension"/>
<attr name="scannerLineHeight" format="dimension"/>
<attr name="frameLineWidth" format="dimension"/>
<attr name="scannerAnimationDelay" format="integer"/>
<attr name="frameRatio" format="float"/>
</declare-styleable>
</resources>

View File

@@ -8,4 +8,7 @@
<color name="viewfinder_result_point_color">#C0FFBD21</color>
<color name="viewfinder_text_color">#FFC0C0C0</color>
<color name="capture_status_bar_color">#00000000</color>
<color name="capture_navigation_bar_color">#00000000</color>
</resources>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="torchMarginTop">80dp</dimen>
</resources>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="CaptureTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="colorPrimary">@android:color/black</item>
<item name="colorPrimaryDark">@android:color/black</item>
</style>
</resources>

View File

@@ -1,7 +1,7 @@
//App
def app_version = [:]
app_version.versionCode = 11
app_version.versionName = "1.1.2"
app_version.versionCode = 25 //androidx 26
app_version.versionName = "1.1.9"
ext.app_version = app_version
//build version