-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
fix(android): no camera devices on app start #3575
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
|
ah dope! |
| // Init cameraProvider + manager as early as possible | ||
| init { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uhm - does that not effectively just revert our changes? @hannojg can you review/confirm?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mrousavy Not a full revert, early init of native part (cameraProvider/extensionsManager) is still kept in init.
The only change is moving sendAvailableDevicesChangedEvent() back into initialize(), because that's where it's safe to call getJSModule.
The problem with previous approach is that getJSModule was being called from init (by sendAvailableDevicesChangedEvent) before JS bridge was ready. You can see that here:
private ReactApplicationContext createReactContext(...) {
...
// CameraDevicesManager.init triggers here
NativeModuleRegistry nativeModuleRegistry = processPackages(reactContext, mPackages);
// JS bridge initialization starts here
CatalystInstanceImpl.Builder catalystInstanceBuilder = new CatalystInstanceImpl.Builder()
...
// Key point: calling getJSModule before this will throw IllegalStateException,
// which is what currently happens in CameraDevicesManager.init.sendAvailableDevicesChangedEvent.getJSModule
reactContext.initializeWithInstance(catalystInstance);So why it works on cold start?
Short answer: timing/race condition.
Long answer: cameraProvider and extensionsManger initialize asynchronously by coroutine. On cold start coroutine usually schedules slightly later, so JS bridge is ready by the time sendAvailableDevicesChangedEvent() runs. Hot restart exposes this timing issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it thanks!
What
I was looking at a bug where no camera devices were returned, however, getting them later I was getting values:
This resulted in the camera never displaying
Changes
Problem:
cameraProviderinonInitialize()getConstants()will be called beforeonInitialize()so we just return an empty camera listSolution:
cameraProvider+managerto the init which will be called earlier, react context should be present at this point as its a constructor arggetConstantsgets called we can get the devices, which fixes the. problemcameraManager.registerAvailabilityCallbackinonInitialize()as this needs to the looper, which we don't have available ininit(at least on new arch as its init from a bg thread)Note: I am wondering if this is a performance improvement as well, as before I assume something as:
So first frame time might be faster? 🤷
Tested on
Related issues
Not sure, haven't checked