内容简介:在今年的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, 居然不知道包扫描是怎么实现的
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
疯狂又脆弱 坚定又柔软
朱墨 / 湖南文艺出版社 / 2018-3 / 39.80元
《疯狂又脆弱 坚定又柔软》是朱墨的一部作品集,介绍了作者考研到北京,工作在华谊,以及留学去英国的经历,在这短短几年中她一路升职加薪,25岁升任华谊宣传总监,27岁赚到人生的第一笔100万,30岁却毅然离职去英国留学,在表面的光鲜亮丽之下,她也曾付出过外人所不知道的心血和努力。她的人生告诉我们,每一个身居高位或者肆意潇洒的人,都曾为梦想疯狂地倾尽全力,而那些心怀梦想的人也总是怀揣一颗坚定又柔软的内心......一起来看看 《疯狂又脆弱 坚定又柔软》 这本书的介绍吧!