Commit b3568d25 authored by wanglei's avatar wanglei

...

parent 865913ca
Pipeline #1426 failed with stages
...@@ -6,15 +6,18 @@ import androidx.camera.core.Camera ...@@ -6,15 +6,18 @@ import androidx.camera.core.Camera
import androidx.camera.core.CameraSelector import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageAnalysis import androidx.camera.core.ImageAnalysis
import androidx.camera.core.Preview import androidx.camera.core.Preview
import androidx.camera.core.ZoomState
import androidx.camera.lifecycle.ProcessCameraProvider import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.view.PreviewView import androidx.camera.view.PreviewView
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.lifecycle.LiveData
import java.util.concurrent.ExecutorService import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors import java.util.concurrent.Executors
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
class CameraUtils( class CameraUtils(
val activity: AppCompatActivity, val activity: AppCompatActivity,
) { ) {
...@@ -27,6 +30,9 @@ class CameraUtils( ...@@ -27,6 +30,9 @@ class CameraUtils(
private var cameraProvider: ProcessCameraProvider? = null private var cameraProvider: ProcessCameraProvider? = null
private var imageAnalyzer: ImageAnalysis? = null private var imageAnalyzer: ImageAnalysis? = null
var cameraReadyCallBack: (() -> Unit)? = null
init { init {
cameraExecutor = Executors.newSingleThreadExecutor() cameraExecutor = Executors.newSingleThreadExecutor()
} }
...@@ -97,6 +103,7 @@ class CameraUtils( ...@@ -97,6 +103,7 @@ class CameraUtils(
} catch (exc: Exception) { } catch (exc: Exception) {
exc.printStackTrace() exc.printStackTrace()
} }
cameraReadyCallBack?.invoke()
} }
/** /**
...@@ -142,6 +149,62 @@ class CameraUtils( ...@@ -142,6 +149,62 @@ class CameraUtils(
return AspectRatio.RATIO_16_9 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 { companion object {
private const val RATIO_4_3_VALUE = 4.0 / 3.0 private const val RATIO_4_3_VALUE = 4.0 / 3.0
private const val RATIO_16_9_VALUE = 16.0 / 9.0 private const val RATIO_16_9_VALUE = 16.0 / 9.0
......
...@@ -109,6 +109,11 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl ...@@ -109,6 +109,11 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl
naviFragment(this.id) naviFragment(this.id)
} }
override fun onDestroy() {
super.onDestroy()
cameraUtils?.onDestroy()
}
override fun configSystemBar() { override fun configSystemBar() {
super.configSystemBar() super.configSystemBar()
immersionBar { immersionBar {
......
...@@ -2,9 +2,16 @@ package com.base.scanqr.ui.main ...@@ -2,9 +2,16 @@ package com.base.scanqr.ui.main
import android.Manifest import android.Manifest
import android.content.pm.PackageManager 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.base.BaseFragment
import com.base.scanqr.databinding.FragmentScanBinding import com.base.scanqr.databinding.FragmentScanBinding
import com.base.scanqr.qr.QRImageAnalyzer 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.base.scanqr.utils.PermissionUtils.checkCameraPermission
import com.gyf.immersionbar.ktx.immersionBar import com.gyf.immersionbar.ktx.immersionBar
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
...@@ -13,6 +20,7 @@ import java.util.concurrent.atomic.AtomicBoolean ...@@ -13,6 +20,7 @@ import java.util.concurrent.atomic.AtomicBoolean
class ScanFragment : BaseFragment<FragmentScanBinding>(FragmentScanBinding::inflate) { class ScanFragment : BaseFragment<FragmentScanBinding>(FragmentScanBinding::inflate) {
private var zoomPair = Pair(0f, 100f)
override fun initView() { override fun initView() {
super.initView() super.initView()
} }
...@@ -33,10 +41,42 @@ class ScanFragment : BaseFragment<FragmentScanBinding>(FragmentScanBinding::infl ...@@ -33,10 +41,42 @@ class ScanFragment : BaseFragment<FragmentScanBinding>(FragmentScanBinding::infl
private fun initCamera() { private fun initCamera() {
if (cameraInit.get()) return if (cameraInit.get()) return
val hasFlash = requireContext().packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH) val hasFlash = requireContext().packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)
if (!hasFlash) {
binding.flFlash.visibility = View.GONE
}
val qrImageAnalyzer = QRImageAnalyzer() val qrImageAnalyzer = QRImageAnalyzer()
val activity = requireActivity() as MainActivity? val activity = requireActivity() as MainActivity?
activity ?: return activity ?: return
activity.cameraUtils?.startBind(binding.previewView, qrImageAnalyzer) 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) cameraInit.set(true)
} }
...@@ -54,6 +94,42 @@ class ScanFragment : BaseFragment<FragmentScanBinding>(FragmentScanBinding::infl ...@@ -54,6 +94,42 @@ class ScanFragment : BaseFragment<FragmentScanBinding>(FragmentScanBinding::infl
override fun initListener() { override fun initListener() {
super.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
}
} }
......
...@@ -43,7 +43,7 @@ object IntentUtils { ...@@ -43,7 +43,7 @@ object IntentUtils {
return Intent() return Intent()
} }
fun intentShareText( text: String): Intent { fun intentShareText(text: String): Intent {
val sendIntent = Intent() val sendIntent = Intent()
sendIntent.action = Intent.ACTION_SEND sendIntent.action = Intent.ACTION_SEND
sendIntent.putExtra(Intent.EXTRA_TEXT, text) // 添加要分享的文本 sendIntent.putExtra(Intent.EXTRA_TEXT, text) // 添加要分享的文本
...@@ -53,4 +53,12 @@ object IntentUtils { ...@@ -53,4 +53,12 @@ object IntentUtils {
val shareIntent = Intent.createChooser(sendIntent, null) val shareIntent = Intent.createChooser(sendIntent, null)
return shareIntent 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
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
<LinearLayout <LinearLayout
android:id="@+id/ll_zoom"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp" android:layout_marginHorizontal="16dp"
...@@ -39,7 +40,7 @@ ...@@ -39,7 +40,7 @@
app:layout_constraintStart_toStartOf="parent"> app:layout_constraintStart_toStartOf="parent">
<FrameLayout <FrameLayout
android:id="@+id/flAdd" android:id="@+id/flReduce"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
...@@ -53,12 +54,13 @@ ...@@ -53,12 +54,13 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:src="@mipmap/jia" android:src="@mipmap/jian"
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription" />
</FrameLayout> </FrameLayout>
<androidx.appcompat.widget.AppCompatSeekBar <androidx.appcompat.widget.AppCompatSeekBar
android:id="@+id/seekbar"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
...@@ -70,7 +72,7 @@ ...@@ -70,7 +72,7 @@
tools:progress="50" /> tools:progress="50" />
<FrameLayout <FrameLayout
android:id="@+id/flReduce" android:id="@+id/flAdd"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
...@@ -84,11 +86,12 @@ ...@@ -84,11 +86,12 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:src="@mipmap/jian" android:src="@mipmap/jia"
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription" />
</FrameLayout> </FrameLayout>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
...@@ -103,6 +106,7 @@ ...@@ -103,6 +106,7 @@
app:layout_constraintStart_toStartOf="parent"> app:layout_constraintStart_toStartOf="parent">
<FrameLayout <FrameLayout
android:id="@+id/fl_image"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingHorizontal="16dp" android:paddingHorizontal="16dp"
...@@ -117,16 +121,18 @@ ...@@ -117,16 +121,18 @@
</FrameLayout> </FrameLayout>
<FrameLayout <FrameLayout
android:id="@+id/fl_flash"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingHorizontal="16dp" android:paddingHorizontal="16dp"
android:paddingVertical="10dp"> android:paddingVertical="10dp">
<ImageView <ImageView
android:id="@+id/iv_flash"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:src="@mipmap/shandian" android:src="@mipmap/shandian_off"
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription" />
</FrameLayout> </FrameLayout>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment