android:name=“com.google.firebase.ml.vision.DEPENDENCIES”
android:value=“barcode” />
6.打开activity_main.xml并添加TextureView,我们将使用它来传输摄像机输入:
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout
xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:tools=“http://schemas.android.com/tools”
xmlns:app=“http://schemas.android.com/apk/res-auto”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
tools:context=“.MainActivity”>
<TextureView
android:id=“@+id/texture_view”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
app:layout_constraintTop_toTopOf=“parent”
app:layout_constraintBottom_toBottomOf=“parent”
app:layout_constraintStart_toStartOf=“parent”
app:layout_constraintEnd_toEndOf=“parent” />
</androidx.constraintlayout.widget.ConstraintLayout>
7.作为项目设置的最后一步,我们需要检查用户是否已授予摄像头许可。所以,你可以转到MainActivity.kt文件并添加以下代码:
class MainActivity : AppCompatActivity() {
companion object {
private const val REQUEST_CAMERA_PERMISSION = 10
}
private lateinit var textureView: TextureView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
textureView = findViewById(R.id.texture_view)
// Request camera permissions
if (isCameraPermissionGranted()) {
textureView.post { startCamera() }
} else {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), REQUEST_CAMERA_PERMISSION)
}
}
private fun startCamera() {
// We will implement this in next steps.
}
private fun isCameraPermissionGranted(): Boolean {
val selfPermission = ContextCompat.checkSelfPermission(baseContext, Manifest.permission.CAMERA)
return selfPermission == PackageManager.PERMISSION_GRANTED
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
if (requestCode == REQUEST_CAMERA_PERMISSION) {
if (isCameraPermissionGranted()) {
textureView.post { startCamera() }
} else {
Toast.makeText(this, “Camera permission is required.”, Toast.LENGTH_SHORT).show()
finish()
}
}
}
}
CameraX有一个称为用例的抽象,使您可以与设备的摄像头进行交互。当前有以下用例:
-
预览:允许您访问摄像机输入流,可用于在TextureView中显示摄像机流。
-
图像分析:允许您分析摄像机输入的每一帧。我们将使用此用例执行图像分析,以使用Firebase ML Kit检测帧中的二维码。
-
图像捕获:捕获和保存照片。
1.如上所述,要在屏幕上显示摄像机流,我们需要使用“ 预览”用例。当创建Preview用例的实例时,我们需要传递PreviewConfig作为构造函数参数。因此,我们需要在startCamera()函数中添加以下代码:
val previewConfig = PreviewConfig.Builder()
// We want to show input from back camera of the device
.setLensFacing(CameraX.LensFacing.BACK)
.build()
val preview = Preview(previewConfig)
2.预览用例提供了一个SurfaceTexture供显示。为了在我们的中显示摄像机流textureView,我们需要使用setOnPreviewOutputUpdateListener()方法将侦听器添加到预览实例:
// …
preview.setOnPreviewOutputUpdateListener { previewOutput ->
textureView.surfaceTexture = previewOutput.surfaceTexture
}
3.当CameraX观察到生命周期来管理摄像机资源时,我们需要使用绑定我们的用例CameraX.bindToLifecycle,所以要将startCamera()函数写入MainActivity中:
private fun startCamera() {
val previewConfig = PreviewConfig.Builder()
// We want to show input from back camera of the device
.setLensFacing(CameraX.LensFacing.BACK)
.build()
val preview = Preview(previewConfig)
preview.setOnPreviewOutputUpdateListener { previewOutput ->
textureView.surfaceTexture = previewOutput.surfaceTexture
}
CameraX.bindToLifecycle(this as LifecycleOwner, preview)
}
现在,我们需要使用ImageAnalysis用例从摄像机输入中检测二维码。为此,我们需要创建一个名为Image的类,该类QrCodeAnalyzer实现ImageAnalysis.Analyzer接口。ImageAnalysis.Analyzer具有名为analyze(ImageProxy image, int rotationDegrees)的功能,在这里我们将添加与QR码检测相关的代码。
1.创建QrCodeAnalyzer并添加回调以在检测到二维码时获取通知:
class QrCodeAnalyzer(
private val onQrCodesDetected: (qrCodes: List) -> Unit
) : ImageAnalysis.Analyzer {
override fun analyze(image: ImageProxy, rotationDegrees: Int) {
// …
}
}
2.获取FirebaseVisionBarcodeDetector的实例:
val options = FirebaseVisionBarcodeDetectorOptions.Builder()
// We want to only detect QR codes.
.setBarcodeFormats(FirebaseVisionBarcode.FORMAT_QR_CODE)
.build()
val detector = FirebaseVision.getInstance().getVisionBarcodeDetector(options)
3.从框架创建FirebaseVisionImage:
val rotation = rotationDegreesToFirebaseRotation(rotationDegrees)
val visionImage = FirebaseVisionImage.fromMediaImage(image.image!!, rotation)
在这一步中,我们还需要通过添加以下函数将ImageAnalysis.Analyzer的旋转度转换为firebase的旋转度:
private fun rotationDegreesToFirebaseRotation(rotationDegrees: Int): Int {
return when (rotationDegrees) {
0 -> FirebaseVisionImageMetadata.ROTATION_0
90 -> FirebaseVisionImageMetadata.ROTATION_90
180 -> FirebaseVisionImageMetadata.ROTATION_180
270 -> FirebaseVisionImageMetadata.ROTATION_270
else -> throw IllegalArgumentException(“Not supported”)
}
}
(4)传递visionImage到detector并通知onQrCodesDetected与检测到的二维码列表:
detector.detectInImage(visionImage)
.addOnSuccessListener { barcodes ->
onQrCodesDetected(barcodes)
}
.addOnFailureListener {
Log.e(“QrCodeAnalyzer”, “something went wrong”, it)
(5)使用MainActivity中startCamera()函数的QrCodeAnalyzer功能:
private fun startCamera() {
// …
val imageAnalysisConfig = ImageAnalysisConfig.Builder()
.build()
val imageAnalysis = ImageAnalysis(imageAnalysisConfig)
val qrCodeAnalyzer = QrCodeAnalyzer { qrCodes ->
qrCodes.forEach {
Log.d(“MainActivity”, “QR Code detected: ${it.rawValue}.”)
}
}
imageAnalysis.analyzer = qrCodeAnalyzer
// We need to bind preview and imageAnalysis use cases
CameraX.bindToLifecycle(this as LifecycleOwner, preview, imageAnalysis)
}
尾声
最后,我再重复一次,如果你想成为一个优秀的 Android 开发人员,请集中精力,对基础和重要的事情做深度研究。
对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。 整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。
最后想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。
当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。
进阶学习视频
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!
师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。
当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。
进阶学习视频
[外链图片转存中…(img-7zY2cYYb-1715067419718)]
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
[外链图片转存中…(img-9kIaJVfR-1715067419721)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!