Camera from SafariViewController is black but interface still shows

We use the SafariViewController to display a website, within this website it allows us to upload images from the camera through the normal html systems (this is not controlled by the app).

Now the problem is that in iOS (android works fine) when I go to use the camera it just displays a black screen with the normal camera interface over the top. Almost like the lens hasn’t opened or someone is covering it with their finger.
No matter how many times I push the button to take a photo nothing happens, this would suggest the camera hasn’t initialized properly.

If I close the app (double tap home button and swipe up to close) and then reopen the app the camera works fine. After a while it goes back to the black screen and you have to close and reopen the app again.

On startup of the Ionic app i have a timeout for 200ms and then ask for permissions to use the camera, once this is granted another 200ms later I open the SafariViewController to my website.

What would be the reason for it being a black screen with interface in this case?

Ionic Info
cli packages:

@ionic/cli-plugin-cordova       : 1.6.2
@ionic/cli-plugin-ionic-angular : 1.4.1
@ionic/cli-utils                : 1.7.0
ionic (Ionic CLI)               : 3.7.0

global packages:

Cordova CLI : 7.0.1 

local packages:

@ionic/app-scripts : 1.3.7
Cordova Platforms  : ios 4.3.1
Ionic Framework    : ionic-angular 3.3.0

System:

Node       : v8.1.2
OS         : macOS Sierra
Xcode      : Xcode 8.3.3 Build version 8E3004b 
ios-deploy : 1.9.1 
npm        : 5.3.0

Does the website work as expected when used in a normal mobile browser?

Yes, when opened directly from Safari on the phone it works as expected.

If I go back to the app it still does not load the camera until the app is closed and reopened.

That is strange.

Just to understand better:
Is a Ionic Native plugin involved here? Doesn’t really sound like it, right?
Does the website code do any “strange” things?

The only native plugins we’re using is Diagnostics to request permissions, splashscreen, and safari-view-controller.

Since it’s loading a website through the safari view controller we have no need for the camera package as we don’t directly access the camera through the code. We have tried installing the camera plugin just to see if having it helped with some sort of permissions; but it doesn’t.

Website code does not do anything strange. It does have a directive on it that just catches the “change” event on the input. But essentially it’s just a input type of file.
<input type="file" ngfiles item="register" ngupload="$ctrl.FileUpload" multiple="multiple" />

Like I’ve said, it definitely works fine, except for the first time the app is installed and permissions requested (this is the big problem), and randomly through the week it’ll stop working again.

I’ve tried reloading the js after permissions are requested; didn’t work.

var initial = window.location.href;
this.splash.show();
window.location.href = initial;
this.splash.hide();

My next solution is to use cordova-plugin-screen-orientation to lock the orientation to the side it’s not on and then set it back. Because changing orientation reloads the app (for some reason). But this seems more like a hack than an actual solution.

Workaround I would call it…

Could you explain the structure again a bit more, please?
You have an Ionic app that has a Safarai View Controller that loads a website, correct?

That’s the structure.

Ionic App that uses Safari View Controller to load a website.
On the website, it has a file upload button which you can take a photo from your phone’s camera.

If you go to this page in safari on the phone, it works.
If you go to this page in the safari view controller, it doesn’t work (until the app has been restarted - then it works).

The flow of the app currently is

    Open the app
    Splashscreen loads and hides
    platform ready
    timeout 200ms -> Check permissions
        Request permission if required
    Once we have permissions
        timeout 200ms -> Open safari view controller to website

Hmm, really interesting problem. No idea how to solve and debug it further.

Can you make it work by closing and reopening the Safari View Controller?

I have that functionality too. You can click “Done” in the safari view controller which closes it (I get the closed event from the plugin) and then reopen it with a button press in the app. Camera still doesn’t work.

I’ve also tried a different website that allows uploads (not one hosted by us) and it has the same issue.
So, it’s not the website.

I have noticed this in the logs of xcode though:
Warning: Attempt to present <SFSafariViewController: 0x13dd3f4a0> on <MainViewController: 0x13dd0cc40> whose view is not in the window hierarchy!

Can you maybe try in other apps that have an in app browser as well? Maybe this is a general problem and not with your app… just have to find such apps. Facebook? Twitter?

I’ve got a feeling it’s related to the safari view controller.

Not sure what’s happened, but after all this playing around and then attempting to remove unneeded code it’s working on first startup correctly. And future startups.

However, now the issue is if the user changes orientation with safari view open, safari will reload (log them out, etc) and then the camera won’t work.
If I hook into the screenOrientation.onChange() event and then use safariViewController.show(…) in that event the camera will work correctly (but the user is still logged out of the website and everything reloaded).

I will still test another app like facebook or twitter to see if it has the same issue.