Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Sign in / Register
Toggle navigation
S
Scan QR Code Barcode Reader
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wanglei
Scan QR Code Barcode Reader
Commits
b3568d25
Commit
b3568d25
authored
Dec 24, 2024
by
wanglei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
...
parent
865913ca
Pipeline
#1426
failed with stages
Changes
7
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
164 additions
and
6 deletions
+164
-6
CameraUtils.kt
app/src/main/java/com/base/scanqr/qr/CameraUtils.kt
+63
-0
MainActivity.kt
app/src/main/java/com/base/scanqr/ui/main/MainActivity.kt
+5
-0
ScanFragment.kt
app/src/main/java/com/base/scanqr/ui/main/ScanFragment.kt
+76
-0
IntentUtils.kt
app/src/main/java/com/base/scanqr/utils/IntentUtils.kt
+9
-1
fragment_scan.xml
app/src/main/res/layout/fragment_scan.xml
+11
-5
shandian_off.png
app/src/main/res/mipmap-xxhdpi/shandian_off.png
+0
-0
shnadian_on.png
app/src/main/res/mipmap-xxhdpi/shnadian_on.png
+0
-0
No files found.
app/src/main/java/com/base/scanqr/qr/CameraUtils.kt
View file @
b3568d25
...
...
@@ -6,15 +6,18 @@ import androidx.camera.core.Camera
import
androidx.camera.core.CameraSelector
import
androidx.camera.core.ImageAnalysis
import
androidx.camera.core.Preview
import
androidx.camera.core.ZoomState
import
androidx.camera.lifecycle.ProcessCameraProvider
import
androidx.camera.view.PreviewView
import
androidx.core.content.ContextCompat
import
androidx.lifecycle.LiveData
import
java.util.concurrent.ExecutorService
import
java.util.concurrent.Executors
import
kotlin.math.abs
import
kotlin.math.max
import
kotlin.math.min
class
CameraUtils
(
val
activity
:
AppCompatActivity
,
)
{
...
...
@@ -27,6 +30,9 @@ class CameraUtils(
private
var
cameraProvider
:
ProcessCameraProvider
?
=
null
private
var
imageAnalyzer
:
ImageAnalysis
?
=
null
var
cameraReadyCallBack
:
(()
->
Unit
)?
=
null
init
{
cameraExecutor
=
Executors
.
newSingleThreadExecutor
()
}
...
...
@@ -97,6 +103,7 @@ class CameraUtils(
}
catch
(
exc
:
Exception
)
{
exc
.
printStackTrace
()
}
cameraReadyCallBack
?.
invoke
()
}
/**
...
...
@@ -142,6 +149,62 @@ class CameraUtils(
return
AspectRatio
.
RATIO_16_9
}
/**
* 打开闪光灯
*/
fun
turnOnFlash
()
{
val
cameraControl
=
camera
?.
cameraControl
cameraControl
?.
enableTorch
(
true
)
}
/**
* 关闭闪光
*/
fun
turnOffFlash
()
{
val
cameraControl
=
camera
?.
cameraControl
cameraControl
?.
enableTorch
(
false
)
}
/**
* 获取闪光状态
*/
fun
getFlashState
():
LiveData
<
Int
>?
{
return
camera
?.
cameraInfo
?.
torchState
}
/**
* 是否支持变焦
*/
fun
isZoomSupported
():
Boolean
{
val
zoomState
:
ZoomState
?
=
camera
?.
cameraInfo
?.
zoomState
?.
getValue
()
if
(
zoomState
!=
null
&&
!
java
.
lang
.
Float
.
isNaN
(
zoomState
.
minZoomRatio
)
&&
!
java
.
lang
.
Float
.
isNaN
(
zoomState
.
maxZoomRatio
))
{
// 相机支持变焦
return
true
}
return
false
}
/**
* 获取变焦范围
*/
fun
getZoomRange
():
Pair
<
Float
,
Float
>
{
val
zoomState
:
ZoomState
?
=
camera
?.
cameraInfo
?.
zoomState
?.
getValue
()
if
(
zoomState
!=
null
)
{
val
minZoomRatio
=
zoomState
.
minZoomRatio
val
maxZoomRatio
=
zoomState
.
maxZoomRatio
return
Pair
(
minZoomRatio
,
maxZoomRatio
)
}
return
Pair
(
0f
,
100f
)
}
/**
* 设置变焦值
*/
fun
setZoomRate
(
ratio
:
Float
)
{
val
cameraControl
=
camera
?.
cameraControl
cameraControl
?.
setZoomRatio
(
ratio
)
}
companion
object
{
private
const
val
RATIO_4_3_VALUE
=
4.0
/
3.0
private
const
val
RATIO_16_9_VALUE
=
16.0
/
9.0
...
...
app/src/main/java/com/base/scanqr/ui/main/MainActivity.kt
View file @
b3568d25
...
...
@@ -109,6 +109,11 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl
naviFragment
(
this
.
id
)
}
override
fun
onDestroy
()
{
super
.
onDestroy
()
cameraUtils
?.
onDestroy
()
}
override
fun
configSystemBar
()
{
super
.
configSystemBar
()
immersionBar
{
...
...
app/src/main/java/com/base/scanqr/ui/main/ScanFragment.kt
View file @
b3568d25
...
...
@@ -2,9 +2,16 @@ package com.base.scanqr.ui.main
import
android.Manifest
import
android.content.pm.PackageManager
import
android.hardware.camera2.CameraMetadata.FLASH_MODE_OFF
import
android.view.View
import
android.widget.SeekBar
import
androidx.camera.core.ImageCapture.FLASH_MODE_ON
import
com.base.scanqr.R
import
com.base.scanqr.base.BaseFragment
import
com.base.scanqr.databinding.FragmentScanBinding
import
com.base.scanqr.qr.QRImageAnalyzer
import
com.base.scanqr.utils.IntentUtils.intentSafPickImage
import
com.base.scanqr.utils.LogEx
import
com.base.scanqr.utils.PermissionUtils.checkCameraPermission
import
com.gyf.immersionbar.ktx.immersionBar
import
java.util.concurrent.atomic.AtomicBoolean
...
...
@@ -13,6 +20,7 @@ import java.util.concurrent.atomic.AtomicBoolean
class
ScanFragment
:
BaseFragment
<
FragmentScanBinding
>(
FragmentScanBinding
::
inflate
)
{
private
var
zoomPair
=
Pair
(
0f
,
100f
)
override
fun
initView
()
{
super
.
initView
()
}
...
...
@@ -33,10 +41,42 @@ class ScanFragment : BaseFragment<FragmentScanBinding>(FragmentScanBinding::infl
private
fun
initCamera
()
{
if
(
cameraInit
.
get
())
return
val
hasFlash
=
requireContext
().
packageManager
.
hasSystemFeature
(
PackageManager
.
FEATURE_CAMERA_FLASH
)
if
(!
hasFlash
)
{
binding
.
flFlash
.
visibility
=
View
.
GONE
}
val
qrImageAnalyzer
=
QRImageAnalyzer
()
val
activity
=
requireActivity
()
as
MainActivity
?
activity
?:
return
activity
.
cameraUtils
?.
startBind
(
binding
.
previewView
,
qrImageAnalyzer
)
activity
.
cameraUtils
?.
cameraReadyCallBack
=
{
//变焦
if
(
activity
.
cameraUtils
?.
isZoomSupported
()
!=
true
)
{
binding
.
llZoom
.
visibility
=
View
.
GONE
}
else
{
zoomPair
=
activity
.
cameraUtils
?.
getZoomRange
()
?:
Pair
(
0f
,
100f
)
LogEx
.
logDebug
(
TAG
,
"zoomPair=${zoomPair.first} ${zoomPair.second}"
)
binding
.
seekbar
.
max
=
((
zoomPair
.
second
-
zoomPair
.
first
)
*
10
).
toInt
()
}
//闪光灯
activity
.
cameraUtils
?.
getFlashState
()
?.
observe
(
this
)
{
state
->
if
(
state
==
FLASH_MODE_OFF
)
{
binding
.
ivFlash
.
setImageResource
(
R
.
mipmap
.
shnadian_on
)
binding
.
flFlash
.
setOnClickListener
{
activity
.
cameraUtils
?.
turnOnFlash
()
}
}
if
(
state
==
FLASH_MODE_ON
)
{
binding
.
ivFlash
.
setImageResource
(
R
.
mipmap
.
shandian_off
)
binding
.
flFlash
.
setOnClickListener
{
activity
.
cameraUtils
?.
turnOffFlash
()
}
}
}
}
cameraInit
.
set
(
true
)
}
...
...
@@ -54,6 +94,42 @@ class ScanFragment : BaseFragment<FragmentScanBinding>(FragmentScanBinding::infl
override
fun
initListener
()
{
super
.
initListener
()
binding
.
flImage
.
setOnClickListener
{
val
activity
=
requireActivity
()
as
MainActivity
?
val
intent
=
intentSafPickImage
()
activity
?.
launcher
?.
launch
(
intent
)
}
binding
.
flFlash
.
setOnClickListener
{
val
activity
=
requireActivity
()
as
MainActivity
?
activity
?.
cameraUtils
?.
turnOnFlash
()
}
binding
.
seekbar
.
setOnSeekBarChangeListener
(
object
:
SeekBar
.
OnSeekBarChangeListener
{
override
fun
onProgressChanged
(
seekBar
:
SeekBar
,
progress
:
Int
,
fromUser
:
Boolean
)
{
if
(
fromUser
)
{
val
zoom
=
(
zoomPair
.
first
+
seekBar
.
progress
/
10f
)
val
activity
=
requireActivity
()
as
MainActivity
?
activity
?.
cameraUtils
?.
setZoomRate
(
zoom
)
}
}
override
fun
onStartTrackingTouch
(
seekBar
:
SeekBar
)
{
}
override
fun
onStopTrackingTouch
(
seekBar
:
SeekBar
)
{
}
})
binding
.
flReduce
.
setOnClickListener
{
val
activity
=
requireActivity
()
as
MainActivity
?
activity
?.
cameraUtils
?.
setZoomRate
(
zoomPair
.
first
)
binding
.
seekbar
.
progress
=
0
}
binding
.
flAdd
.
setOnClickListener
{
val
activity
=
requireActivity
()
as
MainActivity
?
activity
?.
cameraUtils
?.
setZoomRate
(
zoomPair
.
second
)
binding
.
seekbar
.
progress
=
binding
.
seekbar
.
max
}
}
...
...
app/src/main/java/com/base/scanqr/utils/IntentUtils.kt
View file @
b3568d25
...
...
@@ -43,7 +43,7 @@ object IntentUtils {
return
Intent
()
}
fun
intentShareText
(
text
:
String
):
Intent
{
fun
intentShareText
(
text
:
String
):
Intent
{
val
sendIntent
=
Intent
()
sendIntent
.
action
=
Intent
.
ACTION_SEND
sendIntent
.
putExtra
(
Intent
.
EXTRA_TEXT
,
text
)
// 添加要分享的文本
...
...
@@ -53,4 +53,12 @@ object IntentUtils {
val
shareIntent
=
Intent
.
createChooser
(
sendIntent
,
null
)
return
shareIntent
}
fun
intentSafPickImage
():
Intent
{
val
intent
=
Intent
(
Intent
.
ACTION_OPEN_DOCUMENT
)
intent
.
addCategory
(
Intent
.
CATEGORY_OPENABLE
)
intent
.
setType
(
"image/*"
)
return
intent
}
}
\ No newline at end of file
app/src/main/res/layout/fragment_scan.xml
View file @
b3568d25
...
...
@@ -28,6 +28,7 @@
<LinearLayout
android:id=
"@+id/ll_zoom"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_marginHorizontal=
"16dp"
...
...
@@ -39,7 +40,7 @@
app:layout_constraintStart_toStartOf=
"parent"
>
<FrameLayout
android:id=
"@+id/fl
Add
"
android:id=
"@+id/fl
Reduce
"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_vertical"
...
...
@@ -53,12 +54,13 @@
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:src=
"@mipmap/jia"
android:src=
"@mipmap/jia
n
"
tools:ignore=
"ContentDescription"
/>
</FrameLayout>
<androidx.appcompat.widget.AppCompatSeekBar
android:id=
"@+id/seekbar"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_vertical"
...
...
@@ -70,7 +72,7 @@
tools:progress=
"50"
/>
<FrameLayout
android:id=
"@+id/fl
Reduce
"
android:id=
"@+id/fl
Add
"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_vertical"
...
...
@@ -84,11 +86,12 @@
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:src=
"@mipmap/jia
n
"
android:src=
"@mipmap/jia"
tools:ignore=
"ContentDescription"
/>
</FrameLayout>
</LinearLayout>
<LinearLayout
...
...
@@ -103,6 +106,7 @@
app:layout_constraintStart_toStartOf=
"parent"
>
<FrameLayout
android:id=
"@+id/fl_image"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:paddingHorizontal=
"16dp"
...
...
@@ -117,16 +121,18 @@
</FrameLayout>
<FrameLayout
android:id=
"@+id/fl_flash"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:paddingHorizontal=
"16dp"
android:paddingVertical=
"10dp"
>
<ImageView
android:id=
"@+id/iv_flash"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:src=
"@mipmap/shandian"
android:src=
"@mipmap/shandian
_off
"
tools:ignore=
"ContentDescription"
/>
</FrameLayout>
...
...
app/src/main/res/mipmap-xxhdpi/shandian.png
→
app/src/main/res/mipmap-xxhdpi/shandian
_off
.png
View file @
b3568d25
File moved
app/src/main/res/mipmap-xxhdpi/shnadian_n.png
→
app/src/main/res/mipmap-xxhdpi/shnadian_
o
n.png
View file @
b3568d25
File moved
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment