apache / cordova-ios

Apache Cordova iOS
https://cordova.apache.org/
Apache License 2.0
2.16k stars 987 forks source link

With Cordova and the cordova-plugin-wkwebview-engine I can no longer play sounds without direct user action when the App is installed over the official Apple App-Store! #937

Closed RonnySchleicher closed 4 years ago

RonnySchleicher commented 4 years ago

Bug Report

If I use the cordova-plugin-wkwebview-engine and play a soundfile, i become follow assertion.

2020-07-10 13:40:04.054571+0200 TEST[1927:49192] [assertion] Error acquiring assertion: <NSError: 0x600002e7ba80; domain: RBSAssertionErrorDomain; code: 2; reason: "Client is missing required entitlement"> {
    userInfo = {
        RBSAssertionAttribute = <RBSLegacyAttribute: 0x7fce0fd216e0; requestedReason: MediaPlayback; reason: MediaPlayback; flags: PreventTaskSuspend | PreventTaskThrottleDown | WantsForegroundResourcePriority>;
    }
}

This is not nice but not the real problem.

If I install this app via the app store and the audio object of this sound file plays automatically without user action, for example after receiving an SIO message, the assertion causes the app to crash.

The really deadly problem is that with Cordova and the cordova-plugin-wkwebview-engine I can no longer play sounds without direct user action when the App is installed over the official Apple App-Store! The App will be closed after crash!

Note: The problem only occours if I use the cordova-plugin-wkwebview-engine, without everything is fine.

Steps to reproduce the Assertion in X-Code

Important NOTE: The assertion also occurs in the iPhone simulator.

The complete changed index.js look like this:

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
var app = {
    // Application Constructor
    initialize: function() {
        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
    },

    // deviceready Event Handler
    //
    // Bind any cordova events here. Common events are:
    // 'pause', 'resume', etc.
    onDeviceReady: function() {
        this.receivedEvent('deviceready');

        document.getElementById('buttontest').addEventListener('click', function() {
            console.log('Received Event click: start #############################');
            try {
              var audio = new Audio('sounds/s1.wav');
              audio.play();
            }
            catch(err) {
              console.log(err.message);
            }

            console.log('Received Event click: end -----------------------------');
        });
    },

    // Update DOM on a Received Event
    receivedEvent: function(id) {
        var parentElement = document.getElementById(id);
        var listeningElement = parentElement.querySelector('.listening');
        var receivedElement = parentElement.querySelector('.received');

        listeningElement.setAttribute('style', 'display:none;');
        receivedElement.setAttribute('style', 'display:block;');

        console.log('Received Event: ' + id);
    }
};

app.initialize();

When I start the app on the iPhone (in this sample it is an iPhone X), the new button is showing.

Bildschirmfoto 2020-07-10 um 14 12 49

After click the button follow message is showing in the X-Code

2020-07-10 14:16:40.964661+0200 TEST[2123:63730] Received Event click: start #############################
2020-07-10 14:16:40.983068+0200 TEST[2123:63730] Received Event click: end -----------------------------
2020-07-10 14:16:41.101598+0200 TEST[2123:63842] [assertion] Error acquiring assertion: <NSError: 0x6000029ec4b0; domain: RBSAssertionErrorDomain; code: 2; reason: "Client is missing required entitlement"> {
    userInfo = {
        RBSAssertionAttribute = <RBSLegacyAttribute: 0x7fce0fd202c0; requestedReason: MediaPlayback; reason: MediaPlayback; flags: PreventTaskSuspend | PreventTaskThrottleDown | WantsForegroundResourcePriority>;
    }
}
2020-07-10 14:16:41.101697+0200 TEST[2123:63842] [ProcessSuspension]  0x116baab68 - ProcessAssertion() PID 2123 Unable to acquire assertion for process with PID 2123
2020-07-10 14:16:41.101786+0200 TEST[2123:63730] [ProcessSuspension] 0x116baab68 - ProcessAssertion::processAssertionWasInvalidated()
2020-07-10 14:16:41.103452+0200 TEST[2123:63842] [assertion] Error acquiring assertion: <NSError: 0x6000029dd0b0; domain: RBSAssertionErrorDomain; code: 2; reason: "Client is missing required entitlement"> {
    userInfo = {
        RBSAssertionAttribute = <RBSLegacyAttribute: 0x7fce11229040; requestedReason: MediaPlayback; reason: MediaPlayback; flags: PreventTaskSuspend | PreventTaskThrottleDown | WantsForegroundResourcePriority>;
    }
}
2020-07-10 14:16:41.103541+0200 TEST[2123:63842] [ProcessSuspension]  0x116baabb8 - ProcessAssertion() PID 2123 Unable to acquire assertion for process with PID 2129
2020-07-10 14:16:41.103617+0200 TEST[2123:63730] [ProcessSuspension] 0x116baabb8 - ProcessAssertion::processAssertionWasInvalidated()

What is expected to happen?

No error message appeares.

What does actually happen?

The error message appeares.

Command or Code

see above

Environment, Platform, Device

Version information

see above

Checklist

breautek commented 4 years ago

Sounds like you need an entitlement now based on:

reason: "Client is missing required entitlement">

But... there doesn't seem to be any entitlements for media playback. And according to one user on this thread:

Unfortunately, from iOS 13 this ability is under sytem entitlements, com.apple.multitasking.systemappassertions and com.apple.multitasking.unlimitedassertions, you can try it in simulator, no error in log. There is no way to launch it on device thought, as you need an Apple issued provision profile. So, all we can do is to hope that some future release will fix this.

I don't have a test device, so I can't really play around with this, just posting some relevant information I found while searching for potential solutions and/or workarounds.

RonnySchleicher commented 4 years ago

Important NOTE:

This assertion also occurs in the iPhone simulator.

RonnySchleicher commented 4 years ago

Hello. The problem is really very first. Are there any suggestions to solve it?

bkervaski commented 4 years ago

This worked for me, try playing a 1s silent audio file in "onDeviceReady":

let silence = new Audio('silence.mp3') silence.play()

RonnySchleicher commented 4 years ago

@bkervaski I will try this out asap.

vikram1234 commented 4 years ago

Is there any fix for this issue? i have same problem, not able to play audio in background and stops after 30 seconds -

domain: RBSAssertionErrorDomain; code: 2; reason: "Client is missing required entitlement"> { userInfo = { RBSAssertionAttribute = <RBSLegacyAttribute: 0x15b115da0; requestedReason: MediaPlayback; reason: MediaPlayback; flags: PreventTaskSuspend | PreventTaskThrottleDown | WantsForegroundResourcePriority>; } }

breautek commented 4 years ago

There was a known bug that affected iOS 13.1-13.5 with fix landing in iOS 13.6 that caused problems from audio playback from webviews.

https://bugs.webkit.org/show_bug.cgi?id=211394

No one in this thread has mentioned what iOS version they were experiencing this issue on, so it would be great if someone could help us identify that this bug is related to the WKWebView bug.

RonnySchleicher commented 4 years ago

In my opinion it is not possible to play sounds in the old way. It is necessary to request a promise to allow a url to an audio file to be played.

See the follow link

https://webkit.org/blog/7734/auto-play-policy-changes-for-macos/

I solved the problem for myself by using the cordova-plugin-media https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-media/