内容简介:在今年的Google I/O大会上,Google新推出了CameraX支持包,按照官方的说法, 这个包的作用是google在几年前推出了Camera2 API用于取代Camera1, 大部分开发者还是喜欢使用Camera1的api,一是因为api太难用,二是要兼容5.0之前的s设备,这次推出的CameraX支持包不仅消除各种使用上的障碍,还与大受好评的archecture component 包的Lifecycle结合,自动管理相机的生命周期,开发者不在需要去关心什么时候打开相机,什么时候释放相机。甚至联系
在今年的Google I/O大会上,Google新推出了CameraX支持包,按照官方的说法, 这个包的作用是
help you make camera app development easier
google在几年前推出了Camera2 API用于取代Camera1, 大部分开发者还是喜欢使用Camera1的api,一是因为api太难用,二是要兼容5.0之前的s设备,这次推出的CameraX支持包不仅消除各种使用上的障碍,还与大受好评的archecture component 包的Lifecycle结合,自动管理相机的生命周期,开发者不在需要去关心什么时候打开相机,什么时候释放相机。甚至联系各个手机厂商提供统一的api调用使用美颜等接口。
关于cameraX的介绍本文不在赘述,将使用cameraX实现一个小功能:使用最少的代码实现二维码解码,在这个demo中将会使用到CameraX中三大功能中的两个:
- preview
- analysis
创建app
创建app,声明相机权限
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="github.hotstu.camerax.qrcodec"> <uses-permission android:name="android.permission.CAMERA"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme" tools:ignore="GoogleAppIndexingWarning"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> </manifest> 复制代码
添加相关依赖
implementation 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.5' def camerax_version = "1.0.0-alpha02" implementation "androidx.camera:camera-core:${camerax_version}" // If you want to use Camera2 extensions. implementation "androidx.camera:camera-camera2:${camerax_version}" implementation 'com.google.zxing:core:3.3.2' 复制代码
注意,这里有个坑, 因为camerax还没有发布正式版,而它依赖的 androidx.core:core:1.1.0-rc1
中 AppcompatActivity
居然不是 LifeCycleOwner
,,然而camerax依赖 LifeCycleOwner
才能管理生命周期,所以要祭出在support liabary时代解决依赖冲突的黄金代码:
subprojects { configurations.all { resolutionStrategy { force "androidx.core:core:1.0.2" } } } 复制代码
编写代码实现摄像头预览
val previewConfig = PreviewConfig.Builder().apply { setTargetAspectRatio(Rational(1, 1)) setTargetResolution(Size(640, 640)) }.build() val preview = Preview(previewConfig) preview.setOnPreviewOutputUpdateListener { textureView.surfaceTexture = it.surfaceTexture } CameraX.bindToLifecycle(this@MainActivity, preview) 复制代码
编写代码实现数据分析回调
数据分析可以指定回调的线程
val analysisConfig = ImageAnalysisConfig.Builder().apply { setImageReaderMode(ImageAnalysis.ImageReaderMode.ACQUIRE_LATEST_IMAGE) val analyzerThread = HandlerThread("BarcodeAnalyzer").apply { start() } setCallbackHandler(Handler(analyzerThread.looper)) }.build() val analysis = ImageAnalysis(analysisConfig) analysis.analyzer = QRcodeAnalyzer() CameraX.bindToLifecycle(this@MainActivity, analysis) 复制代码
同时绑定预览和分析,并且搞定权限申请
class MainActivity : AppCompatActivity() { @SuppressLint("CheckResult") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val previewConfig = PreviewConfig.Builder().apply { setTargetAspectRatio(Rational(1, 1)) setTargetResolution(Size(640, 640)) }.build() val analysisConfig = ImageAnalysisConfig.Builder().apply { setImageReaderMode(ImageAnalysis.ImageReaderMode.ACQUIRE_LATEST_IMAGE) val analyzerThread = HandlerThread("BarcodeAnalyzer").apply { start() } setCallbackHandler(Handler(analyzerThread.looper)) }.build() val rxPermissions = RxPermissions(this) val preview = Preview(previewConfig) val analysis = ImageAnalysis(analysisConfig) preview.setOnPreviewOutputUpdateListener { textureView.surfaceTexture = it.surfaceTexture } analysis.analyzer = QRcodeAnalyzer() rxPermissions.request(android.Manifest.permission.CAMERA) .subscribe { CameraX.bindToLifecycle(this@MainActivity, preview, analysis) } } } 复制代码
实现QRcodeAnalyzer
做二维码解码,很多开发者是直接在zxing-Android 项目基础上删删改改,其实不建议这样做,应为那个项目是从Android早期版本开始的,一些东西都为了支持老版本系统而做出了妥协,很多代码都显得老旧而且不优雅,查看源码你会发现它调用摄像头的方法是非常复杂的。这里我们只是用xzing核心库 com.google.zxing:core
class QRcodeAnalyzer : ImageAnalysis.Analyzer { private val reader: MultiFormatReader = MultiFormatReader() init { val map = mapOf<DecodeHintType, Collection<BarcodeFormat>>( Pair(DecodeHintType.POSSIBLE_FORMATS, arrayListOf(BarcodeFormat.QR_CODE)) ) reader.setHints(map) } override fun analyze(image: ImageProxy, rotationDegrees: Int) { if (ImageFormat.YUV_420_888 != image.format) { Log.e("BarcodeAnalyzer", "expect YUV_420_888, now = ${image.format}") return } val buffer = image.planes[0].buffer val data = ByteArray(buffer.remaining()) val height = image.height val width = image.width buffer.get(data) //TODO 调整crop的矩形区域,目前是全屏(全屏有更好的识别体验,但是在部分手机上可能OOM) val source = PlanarYUVLuminanceSource(data, width, height, 0, 0, width, height, false) val bitmap = BinaryBitmap(HybridBinarizer(source)) try { val result = reader.decode(bitmap) Log.e("BarcodeAnalyzer", "resolved!!! = $result") } catch (e: Exception) { Log.d("BarcodeAnalyzer", "Error decoding barcode") } } } 复制代码
大功告成, 核心代码不超过100行。
总结
总结一下,目前cameraX还在有待完善,例如处理摄像头的rotation的时候还是非常迷。
项目地址: github.com/hotstu/QRCo…
本人在掘金上写的内容除特别注明以外均为本人原创,转载需经本人同意,欢迎转载分享,请注明出处。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Android 实现 Ocr手机号扫描
- Python实现FTP弱口令扫描器
- Nmap配合Masscan实现高效率扫描资产
- Nmap配合Masscan实现高效率扫描资产
- 通过.NET实现Gargoyle(一种内存扫描的对抗技术)
- 不会吧,有人用了两年Spring, 居然不知道包扫描是怎么实现的
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Beginning Google Maps API 3
Gabriel Svennerberg / Apress / 2010-07-27 / $39.99
This book is about the next generation of the Google Maps API. It will provide the reader with the skills and knowledge necessary to incorporate Google Maps v3 on web pages in both desktop and mobile ......一起来看看 《Beginning Google Maps API 3》 这本书的介绍吧!