我已经开始探索camerax库以及示例应用程序,并且我注意到管理生命周期时有些不一致。
在此线程中,我将仅谈论预览用例,因为它主要与生命周期有关。
在示例应用程序中,在CameraFragment
中,用例与onViewCreated
中的CameraX
绑定,并且在onDestroyView
中取消绑定。第一个问题是,如果我们将LifecycleOwner
传递给bind
方法,我们是否必须使用unbind
用例?我们可以将它们绑在onCreate
中,然后将生命周期管理放到CameraX
上吗?
我还尝试关注"入门"教程,其中TextureView
的CC_11刚刚替换。在示例应用程序中,首先将TextureView
从父中删除,然后添加,然后更换SurfaceTexture
。我们必须这样做吗?原因是什么?
另一件事是,在示例应用程序中,用例是由view.post { }
方法绑定的。我遇到了这种方法的许多问题,因为将片段放在背面上,替换为另一个片段,而不是重新创建的camerax记录了许多消息:
E/CamX: [ERROR][STATS_AEC] aec_led_calibration.cpp:560: aec_led_cal_apply_calibration Invalid pointer 0x7921174000 0x0
E/CamX: [ERROR][STATS_AEC] aec_set.cpp:1346: aec_set_fps_range Aec_Error invalid input 414 E/CamX: [ERROR][STATS_AEC] camxcaecstatsprocessor.cpp:1671 SetAlgoBayerHistValue() Unsupported bayer hist channel!
E/CamX: [ERROR][STATS ] camxcaecstatsprocessor.cpp:3194 ProcessRequestFastAE() [FastAE] Failed to apply gain to the stats! E/CamX: [ERROR][STATS_AEC] aec_process.cpp:1229: aec_process_stats_parsing aec is null or invalid
E/CamX: [ERROR][STATS_AEC] aec_process.cpp:7983: aec_process_preview_and_video Error: invalid stats
只能设置OnPreviewOutputUpdateListener
而不是绑定所有用例吗?
编辑
为了显示确切的问题,我创建了简单的项目相机游乐场。
这是CameraFragment
,具有整个逻辑。
class CameraFragment : Fragment() {
private val preview by lazy {
val configuration = PreviewConfig.Builder().build()
Preview(configuration)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
CameraX.bindToLifecycle(this, preview)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_camera, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
button_gallery.setOnClickListener {
requireActivity().supportFragmentManager
.beginTransaction()
.replace(R.id.container, GalleryFragment())
.addToBackStack("GalleryFragment")
.commit()
}
preview.setOnPreviewOutputUpdateListener { texture_view.surfaceTexture = it.surfaceTexture }
}
}
现在单击图库按钮后,CameraFragment
被GalleryFragment
替换。按下返回按钮并返回CameraFragment
后,Camerax记录了此类消息:
2019-05-09 14:12:20.969 778-1363/? E/CamX: [ERROR][STATS ] gcamfastaeutil.cpp:1170 SetTuningData() [FastAE] ERROR! Failed to get the tuning data
2019-05-09 14:12:20.969 778-1363/? E/CamX: [ERROR][HAL ] camxmetadatapool.cpp:1447 GetMetadataByTag() Invalid Slot to get a metadata from
2019-05-09 14:12:20.969 778-1363/? E/CamX: [ERROR][HAL ] camxmetadatapool.cpp:1447 GetMetadataByTag() Invalid Slot to get a metadata from
2019-05-09 14:12:20.969 778-1363/? E/CamX: [ERROR][STATS_AEC] aec_led_calibration.cpp:560: aec_led_cal_apply_calibration Invalid pointer 0x7920f1d000 0x0
2019-05-09 14:12:20.969 778-1363/? E/CamX: [ERROR][STATS_AEC] aec_set.cpp:1346: aec_set_fps_range Aec_Error invalid input 0
2019-05-09 14:12:20.969 778-1363/? E/CamX: [ERROR][STATS ] camxae.cpp:2203 AECSetSensorInfo() Wrong initial sequence from HAL!
2019-05-09 14:12:20.969 778-1363/? E/CamX: [ERROR][STATS_AEC] aec_get.cpp:777: aec_get_param GET_EXP_PARAMS ERROR, Uninitialized exposure settings requested
2019-05-09 14:12:20.969 778-1363/? E/CamX: [ERROR][HAL ] camxmetadatapool.cpp:1447 GetMetadataByTag() Invalid Slot to get a metadata from
camerax库, camera start&停止使用Java
要打开相机,我们没有特定的代码。只有您可以使用 bindtolifecycle((。另外,do 不是忘记,实现 LifeCycleObServer 。这是在相机中启动相机的镜头代码示例。
private void mStartCamera(){
Camera camera = mCameraProvider.bindToLifecycle(this, cameraSelector, preview, imageAnalysis);
}
要关闭相机,您应该在 cameraprovider 上工作。您做不是需要使用相机对象。简短的代码示例。
private void mStopCamera(){
mCameraProvider.unbindAll();
}
- 奖金
如果您要问&quot&quot&quot cameraprovider?您需要在 cameraproviderfuture 上添加侦听器。shor代码示例。
private void mDefineCameraProvider() {
final ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);
cameraProviderFuture.addListener(() -> {
try {
ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
mCameraProvider = cameraProvider;
}
catch (ExecutionException | InterruptedException e) {
// No errors need to be handled for this Future.
// This should never be reached.
Log.e("CANER", "Camera provider error: " +e);
}
}, ContextCompat.getMainExecutor(this));
}
第一个问题是,如果我们通过生命周围的clode虫来绑定方法,我们是否必须解开用例?我们可以将它们束缚在on greate中,然后将生命周期管理留在camerax上?
你是正确的。我认为示例应用程序可以安全删除CameraX.unbindAll()
调用。
首先将纹理视图从父级删除,然后添加,然后更换surfaceTexture。我们必须这样做吗?原因是什么?
需要将纹理视图删除并从父视图中重新添加,以使其附加的surfaceTexture。这是因为一旦将其连接到视图层次结构,内部就可以在内部创建自己的surfaceTexture,并且一旦从视图层次结构中删除了父textureView,则内部surfaceTexture才能正确分离。入门Codelab已更新以包括重新连接。
另一件事是,在示例应用中,用例是从view.post {}方法绑定的。我遇到了这种方法的许多问题,因为将片段放在背面上,替换为另一个碎片,而不是重新创建的,camerax记录了许多消息
viewFinder.post { ... }
内部的绑定用例,以确保在正确布置纹理浏览后用例绑定。您从E/CamX
开始看到的错误实际上与Camerax库无关,并且似乎来自设备的本机相机堆栈(即相机驱动程序(。如果您在应用程序本身中没有看到任何问题,则可能会忽略错误消息。
可以仅设置OnPreviewOutputupDateListener而不是绑定所有用例吗?
我不确定我明白这一点。您必须绑定Camerax的所有用例,以实际启动它们作为相机会话的一部分。查看文档以获取更多详细信息。