cordova-plugin-iosrtc: iOS 14.3 getUserMedia fails

Please read first!

Please use Public Google Group (mailing list) for general technical discussions and questions.

  • I have used Google with the error message or bug in association with the library and Cordova words to make sure the issue I’m reporting is only related to iOSRTC.
  • I have provided steps to reproduce (e.g. sample code or updated extra/renderer-and-libwebrtc-tests.js file).
  • I have provided third party library name and version, ios, Xcode and plugin version and adapter.js version if used.

Note: If the checkboxes above are not checked (which you do after the issue is posted), the issue will be closed, removing this checkbox will result in automatic closed issue.

Versions affected

  • Cordova version 10.0.0
  • Cordova iOS version 6.1.1
  • Plugin version 6.0.16
  • iOS 14.3
  • twilio-video plugin 2.7.3

Description

On iOS 14.3, when I try to call any method on twilio-video.js that would call getUserMedia (like createLocalTracks, createLocalVideoTrack, or createLocalAudioTrack), I receive an error. This reads like a permissions error, but permissions are accepted when they pop up, and the error occurs after the last permission prompt is accepted.

WARN in [createLocalTracks #2]: Call to getUserMedia failed: NotAllowedError: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.

This does not occur on older versions of iOS.

Steps to reproduce

Try and create a localTrack on iOS 14.3

Expected results

I would expect it to call getUserMedia in the plugin

Actual results

It does not appear to even be reaching iosrtc’s getUserMediaPlugin file, it just fails immediately.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 51 (33 by maintainers)

Most upvoted comments

Ok, I think I found a solution

and it’s basically related to my above comment with Cordova secure access to ‘getUserMedia’ and to @SzymG comment https://github.com/cordova-rtc/cordova-plugin-iosrtc/issues/618#issuecomment-748620749

While debuggin, I realized that the plugin’s getUserMedia implementaton is not used https://github.com/cordova-rtc/cordova-plugin-iosrtc/blob/master/src/iosrtcPlugin.swift#L1023 Instead, seems a WKWebView implementation was used which produced the above error.

And I have a ‘registerGlobals’ call which brought more questions…

What I tried then is to call ‘registerGlobals’ right when a user press a ‘call’ button and it helped (!).

This leaded me to some explanation of the issue - it maybe related to ‘adaper.js’ mangling with ‘getUserMedia’ or so, e.g. a ‘registerGlobals’ was called first, and then it was overrided with standard WKWebView implementation of ‘getUserMedia’ by ‘adaper.js’. So some kind of a race condition.

Mooving ‘registerGlobals’ call to a later stage resolved the issue.

I’ve successfully managed it by following @IgorVNC advice: What I tried then is to call ‘registerGlobals’ right when a user press a ‘call’ button and it helped (!).

To be more precise, I’ve added registerGlobals() right before getUserMedia is required.

alright, after much debugging, i conclude that webrtc-adapter override navigator.mediaDevices even if the webrtc-adapter is injected before or after calling registerGlobals, the initial workaround is to call every time cordova.plugins.iosrtc.registerGlobals every time before you call navigator.mediadevices.getUserMedia.

Here is the fix i tested for iosRTC

// Prevent WebRTC-adapter to overide navigator.mediaDevices after shim is applied since ios 14.3
Object.defineProperty(
  navigator,
  'mediaDevices',
  {
    value: new cordova.plugins.iosrtc.MediaDevices(),
    writable: false
  },
  {
    enumerable: false,
    configurable: false,
    writable: false,
    value: 'static'
  }
);

see: https://github.com/cordova-rtc/cordova-plugin-iosrtc/commit/a2d3d0e63ad0fa92e6b57d8e4b539fc96bc229e6

To test that fix, you can try master:

cordova plugin remove cordova-plugin-iosrtc --verbose
cordova plugin add https://github.com/cordova-rtc/cordova-plugin-iosrtc#master --verbose
cordova platform remove ios --no-save
cordova platform add ios --no-save

or simply call following methods right after cordova.plugins.iosrtc.registerGlobals:

// Prevent WebRTC-adapter to overide navigator.mediaDevices after shim is applied since ios 14.3
Object.defineProperty(
  navigator,
  'mediaDevices',
  {
    value: new cordova.plugins.iosrtc.MediaDevices(),
    writable: false
  },
  {
    enumerable: false,
    configurable: false,
    writable: false,
    value: 'static'
  }
);

iOS 14.3 does bring getUserMedia support to WKWebview see https://bugs.webkit.org/show_bug.cgi?id=208667

We may need to perform better feature detection but over time you should not need this plugin to call registerGlobals, plugin can be useful for audio output and some other reasons such as support for iOS 10 to 14.2.

You need to request the permission properly, must likely using dedicated iosRTC api may work see request permission api see https://github.com/cordova-rtc/cordova-plugin-iosrtc/blob/master/docs/iosrtc.md#iosrtcrequestpermission

Oh and make sure it is not called nowhere before, for example, I use RTCMultiConnection.js, the thing it that they added their own registerGlobals inside their lib, and therefore I had to remove the whole thing where they want to declare cordova.iosrtc for us.

@Gregadeaux it has been confirmed that you need to make sure to call registerGlobals to expose SHIM at the right time.

Note on people that think this plug-in is now useless: you need to be on an https page, not the case with localhost unless debug. Meaning this plug-in is still useful.

I’m facing the same issue on iOS 14.3. My Ionic App uses 6.0.16 version of plugin. When I call navigator.mediaDevices.getUserMedia({video: false, audio: true}); I get an error:

NotAllowedError: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission

What’s interesting - when before getUserMedia I call requestPermisson function, I get info, that permission is approved.

What’s also interesting - when I run my app on --debug, there is no problem. Problem occurs, on the --prod build.

Same problem in our app on iOS 14.3. Solved it by calling registerGlobals() right before requesting the getUserMedia. @hthetiot should we also update the iosRTC stack to the latest release as you mention previously? (just asking because it’s working now with the above fix…)

Just tested build 6.1.17 without calling registerGlobals() before getUserMedia and the problem persists… When calling registerGlobals() before getUserMedia problem is solved.

Thank you @neeact

I will get this bitch, i will keep you posted here.

Finally found the issue, it look like webrtc-adater is overiding navigator.mediaDevices object even after registerGlobals, causing to use native getUserMedia instead of SHIM. Solution is to freeze navigator.mediaDevices to prevent webrtc-adater to overide.

	// Prevent WebRTC-adapter to overide navigator.mediaDevices after shim is applied
	Object.freeze(navigator.mediaDevices)

I solved problem in my case. I’ve done everything as @hthetiot said, including requestPermission etc, but it wasn’t still working. My problem was, that I called registerGlobals() in app.component.ts, when app started. When I added registerGlobals() also to the service, where i called getUserMedia everything worked as I expected. App asked me for additional permission, but problem was solved. Hope I helped.

I will try and run the sample, but as stated in a comment, I have removed twilio from the test and am seeing the same error. I do not receive that error on lower versions of iOS with the same app. So it is unrelated to twilio.

This is what is in my app.component.ts constructor

this.platform.ready().then(() => {
      this.statusBar.styleDefault();
      this.splashScreen.hide();
      this.screenOrientation.lock('landscape').catch(e => e);


      
      if (this.platform.is('ios')) {
        if (window["cordova"] && window["cordova"]["plugins"] && window["cordova"]["plugins"]["iosrtc"]) {
          cordova.plugins.iosrtc.registerGlobals();
          cordova.plugins.iosrtc.debug.enable('*', true);


          // // load adapter.js
          // const adapterVersion = 'latest';
          // const script = document.createElement('script');
          // script.type = 'text/javascript';
          // script.src = 'https://webrtc.github.io/adapter/adapter-' + adapterVersion + '.js';
          // script.async = false;
          // document.getElementsByTagName('head')[0].appendChild(script);
        }
      }```