Skip to content
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

fix: entitlement requirement issue on iOS devices #900

Open
wants to merge 2 commits into
base: minor
Choose a base branch
from

Conversation

pedromassango
Copy link

There is an iOS Release builds where the audio won't play due to the error below:
[NowPlaying] [MRNowPlaying] Ignoring setPlaybackState because application does not contain entitlement com.apple.mediaremote.set-playback-state for platform

Closed issue that this PR fixes.

Pre-launch Checklist

  • I read the [CONTRIBUTING.md] and followed the process outlined there for submitting PRs.
  • My change is not breaking and lands in minor branch OR my change is breaking and lands in major branch.
  • If I'm the first to contribute to the next version, I incremented the version number in pubspec.yaml according to the [pub versioning philosophy].
  • I updated CHANGELOG.md to add a description of the change (format: * DESCRIPTION OF YOUR CHANGE (@your-git-username)).
  • I updated/added relevant documentation (doc comments with ///).
  • I ran dart analyze.
  • I ran dart format.
  • I ran flutter test and all tests are passing.

@ryanheise
Copy link
Owner

Thanks @pedromassango . I'd like to test this against a minimal reproduction project, but I actually never saw a valid issue submitted for this and was unclear whether it was a build error or a runtime error. How can I test/reproduce this?

@pedromassango
Copy link
Author

I will let you know once I have a reproducible code

@nickolay-kofanov
Copy link

I see the same issue for iOS in my app - it is not a critical error and everything seems to be working well, but I see numerous of such messages in the log:

[NowPlaying] [MRNowPlaying] Ignoring setPlaybackState because application does not contain entitlement com.apple.mediaremote.set-playback-state for platform

@ryanheise
Copy link
Owner

Yes, since the message says "Ignoring setPlaybackState", I would have expected it to be harmless, so it's surprising it turns out this can be critical and prevent audio from playing.

@nickolay-kofanov
Copy link

Yes, but I agree that

center.playbackState = playing ? MPNowPlayingPlaybackStatePlaying : MPNowPlayingPlaybackStatePaused;

should be executed on MacOS only. As the docs say:
https://developer.apple.com/documentation/mediaplayer/mpnowplayinginfocenter/2588243-playbackstate?language=objc

This property only applies to macOS. You must set this property every time the app begins or halts playback, otherwise remote control functionality may not work as expected.

@ryanheise
Copy link
Owner

Yep I definitely agree with that. I think I have a habit of only looking in the sidebar of the documentation which says it is available on these specific versions of iOS and macOS, although the body clearly overrides that information.

I guess I would just like to be able to reproduce this myself before merging, and I'm not sure exactly what the observed behaviour is or how to reproduce it yet.

@csacchetti
Copy link

I have the same problem, but my audio works. I don't know if problems with the remoteControlFunctionality can result.
When can we get this fix in the stable release of the plugin?
Thanks

@ryanheise
Copy link
Owner

Just waiting for @pedromassango to provide instructions on how to reproduce the problem of audio not playing.

@csacchetti can you maybe test this PR and confirm whether it solves your issue?

@ryanheise
Copy link
Owner

ryanheise commented Feb 7, 2022

After testing this PR I'm getting:

/Volumes/Samsung_T5/projects/audio_service/audio_service/darwin/Classes
/AudioServicePlugin.m:291:9: error: implicit declaration of function 'os'
is invalid in C99 [-Werror,-Wimplicit-function-declaration]
    if (os(macOS)) {

Looks like this is a Swift construct, and for Objective-C you need to use one of the TARGET_OS_* tests:

https://epir.at/2019/10/30/api-availability-and-target-conditionals/

@csacchetti
Copy link

@ryanheise
Here is a link to a tutorial using audio_service 0.18 a Just audio that gives this problem.

[NowPlaying] [MRNowPlaying] Ignoring setPlaybackState because application does not contain entitlement com.apple.mediaremote.set-playback-state for platform

Here is the link to the tutorial:
https://suragch.medium.com/background-audio-in-flutter-with-audio-service-and-just-audio-3cce17b4a7d

You can download repository here:
https://github.com/suragch/flutter_audio_service_demo

@ryanheise
Copy link
Owner

Did you test the pr?

@ryanheise
Copy link
Owner

ryanheise commented Feb 7, 2022

I think this PR needs to use #if TARGET_OS_OSX instead of if (os(macOS)) and it should also still keep the @available checks since it is still only available on specific versions.

Before I can merge this, I think we should also ensure that the change works on both macOS and iOS (i.e. the controls appear in the control center in both cases correctly after play/pause).

Edit: from my tests, this seems to make iOS stop working, in that the controls no longer appear on the lock screen while playing. Can anyone confirm?

@daniel-naegele
Copy link

daniel-naegele commented Feb 26, 2022

Some more insight on the original issue:
The problem even exists on the example app in audio_service (I am using an old iPhone SE as a real test device).

I tried to use the version by @pedromassango, but upon compiling I got the following errors:

Failed to build iOS app
Error output from Xcode build:
↳
    2022-02-26 02:00:32.241 xcodebuild[14740:278522]  DVTAssertions: Warning in
    /Library/Caches/com.apple.xbs/Sources/DVTiOSFrameworks/DVTiOSFrameworks-19527/DTDeviceKitBase/DTDKRemoteDeviceData.m:373
    Details:  (null) deviceType from 8ee3fe031ab04f598ab8fc9e5011f2c91ca27d4f was NULL when -platform called.
    Object:   <DTDKMobileDeviceToken: 0x7fb1e8550eb0>
    Method:   -platform
    Thread:   <NSThread: 0x7fb1e8427fe0>{number = 7, name = (null)}
    Please file a bug at https://feedbackassistant.apple.com with this warning message and any useful information you can provide.
    2022-02-26 02:00:33.277 xcodebuild[14740:278555] CFURLRequestSetHTTPCookieStorageAcceptPolicy_block_invoke: no longer implemented and should not be called
    ** BUILD FAILED **


Xcode's output:
↳
    Writing result bundle at path:
    	/var/folders/40/r2px4_ms1k56lqv5lm07c0yc0000gn/T/flutter_tools.b4B02o/flutter_ios_build_temp_dir7s9Fsr/temporary_xcresult_bundle

    Command CompileSwiftSources failed with a nonzero exit code
    /Users/daniel/development/audio_service/audio_service/darwin/Classes/AudioServicePlugin.m:291:9: error: implicit declaration of function 'os' is invalid in C99
    [-Werror,-Wimplicit-function-declaration]
        if (os(macOS)) {
            ^
    /Users/daniel/development/audio_service/audio_service/darwin/Classes/AudioServicePlugin.m:291:12: error: use of undeclared identifier 'macOS'
        if (os(macOS)) {
               ^
    /Users/daniel/development/audio_service/audio_service/darwin/Classes/AudioServicePlugin.m:292:42: warning: 'MPNowPlayingPlaybackStatePlaying' is only available on iOS 11.0 or newer
    [-Wunguarded-availability-new]
            center.playbackState = playing ? MPNowPlayingPlaybackStatePlaying : MPNowPlayingPlaybackStatePaused;
                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    In module 'MediaPlayer' imported from /Users/daniel/development/audio_service/audio_service/darwin/Classes/AudioServicePlugin.m:3:
    /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.2.sdk/System/Library/Frameworks/MediaPlayer.framework/Headers/MPNowPlayingInfoCenter.h:
    44:29: note: 'MPNowPlayingPlaybackState' has been marked as being introduced in iOS 11.0 here, but the deployment target is iOS 9.0.0
    typedef NS_ENUM(NSUInteger, MPNowPlayingPlaybackState) {
                                ^
    /Users/daniel/development/audio_service/audio_service/darwin/Classes/AudioServicePlugin.m:292:42: note: enclose 'MPNowPlayingPlaybackStatePlaying' in an @available check to silence
    this warning
            center.playbackState = playing ? MPNowPlayingPlaybackStatePlaying : MPNowPlayingPlaybackStatePaused;
                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /Users/daniel/development/audio_service/audio_service/darwin/Classes/AudioServicePlugin.m:292:77: warning: 'MPNowPlayingPlaybackStatePaused' is only available on iOS 11.0 or newer
    [-Wunguarded-availability-new]
            center.playbackState = playing ? MPNowPlayingPlaybackStatePlaying : MPNowPlayingPlaybackStatePaused;
                                                                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    In module 'MediaPlayer' imported from /Users/daniel/development/audio_service/audio_service/darwin/Classes/AudioServicePlugin.m:3:
    /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.2.sdk/System/Library/Frameworks/MediaPlayer.framework/Headers/MPNowPlayingInfoCenter.h:
    44:29: note: 'MPNowPlayingPlaybackState' has been marked as being introduced in iOS 11.0 here, but the deployment target is iOS 9.0.0
    typedef NS_ENUM(NSUInteger, MPNowPlayingPlaybackState) {
                                ^
    /Users/daniel/development/audio_service/audio_service/darwin/Classes/AudioServicePlugin.m:292:77: note: enclose 'MPNowPlayingPlaybackStatePaused' in an @available check to silence this
    warning
            center.playbackState = playing ? MPNowPlayingPlaybackStatePlaying : MPNowPlayingPlaybackStatePaused;
                                                                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /Users/daniel/development/audio_service/audio_service/darwin/Classes/AudioServicePlugin.m:292:16: warning: 'setPlaybackState:' is only available on iOS 13.0 or newer
    [-Wunguarded-availability-new]
            center.playbackState = playing ? MPNowPlayingPlaybackStatePlaying : MPNowPlayingPlaybackStatePaused;
                   ^~~~~~~~~~~~~
    In module 'MediaPlayer' imported from /Users/daniel/development/audio_service/audio_service/darwin/Classes/AudioServicePlugin.m:3:
    /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.2.sdk/System/Library/Frameworks/MediaPlayer.framework/Headers/MPNowPlayingInfoCenter.h:
    70:49: note: 'setPlaybackState:' has been marked as being introduced in iOS 13.0 here, but the deployment target is iOS 9.0.0
    @property (nonatomic) MPNowPlayingPlaybackState playbackState MP_API(macos(10.12.2), ios(13.0), macCatalyst(13.0));
                                                    ^
    /Users/daniel/development/audio_service/audio_service/darwin/Classes/AudioServicePlugin.m:292:16: note: enclose 'setPlaybackState:' in an @available check to silence this warning
            center.playbackState = playing ? MPNowPlayingPlaybackStatePlaying : MPNowPlayingPlaybackStatePaused;
                   ^~~~~~~~~~~~~
    3 warnings and 2 errors generated.
    note: Using new build system
    note: Planning
    note: Build preparation complete
    note: Building targets in dependency order
    /Users/daniel/development/audio_service/audio_service/example/ios/Pods/Pods.xcodeproj: warning: The iOS deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of
    supported deployment target versions is 9.0 to 15.2.99. (in target 'FMDB' from project 'Pods')

    Result bundle written to path:
    	/var/folders/40/r2px4_ms1k56lqv5lm07c0yc0000gn/T/flutter_tools.b4B02o/flutter_ios_build_temp_dir7s9Fsr/temporary_xcresult_bundle

Output of flutter doctor:

[✓] Flutter (Channel stable, 2.10.2, on macOS 11.6.4 20G417 darwin-x64, locale en-GB)
    • Flutter version 2.10.2 at /Users/daniel/development/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 097d3313d8 (7 days ago), 2022-02-18 19:33:08 -0600
    • Engine revision a83ed0e5e3
    • Dart version 2.16.1
    • DevTools version 2.9.2

[✗] Android toolchain - develop for Android devices
    ✗ Unable to locate Android SDK.
      Install Android Studio from: https://developer.android.com/studio/index.html
      On first launch it will assist you in installing the Android SDK components.
      (or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions).
      If the Android SDK has been installed to a custom location, please use
      `flutter config --android-sdk` to update to that location.


[✓] Xcode - develop for iOS and macOS (Xcode 13.2.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • CocoaPods version 1.10.0.beta.2

[✗] Chrome - develop for the web (Cannot find Chrome executable at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome)
    ! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.

[!] Android Studio (not installed)
    • Android Studio not found; download from https://developer.android.com/studio/index.html
      (or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions).

[✓] IntelliJ IDEA Community Edition (version 2020.2)
    • IntelliJ at /Applications/IntelliJ IDEA CE.app
    • Flutter plugin installed
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart

[✓] Connected device (2 available)
    • iPhone von Daniel (mobile) • 8ee3fe031ab04f598ab8fc9e5011f2c91ca27d4f • ios        • iOS 14.8 18H17
    • macOS (desktop)            • macos                                    • darwin-x64 • macOS 11.6.4 20G417 darwin-x64
    ! Error: iPhone von Daniel is busy: Fetching debug symbols for iPhone von Daniel. Xcode will continue when iPhone von Daniel is finished. (code -10)

[✓] HTTP Host Availability
    • All required HTTP hosts are available

! Doctor found issues in 3 categories.

@ryanheise
Copy link
Owner

I tried to use the version by @pedromassango, but upon compiling I got the following errors:

Yes, that is a problem with this PR, and I have mentioned in my previous comment what needs to be done to fix this before I can merge this:

I think this PR needs to use #if TARGET_OS_OSX instead of if (os(macOS)) and it should also still keep the @available checks since it is still only available on specific versions.

@pedromassango
Copy link
Author

Just waiting for @pedromassango to provide instructions on how to reproduce the problem of audio not playing.

Hey, so sorry fo the late reply here. After a while I was able to find out that the issue is not related with this change. I will go ahead and close this PR as the problem I was facing as nothing to do with it!

Sorry y’all!

@csacchetti
Copy link

It is true that the audio is still heard and everything works, but I think it is better to remove this message in the console: [NowPlaying] [MRNowPlaying] Ignoring setPlaybackState because application does not contain entitlement com.apple.mediaremote.set-playback-state for platform

@ryanheise
Copy link
Owner

Yes I agree something should be done about that, but has anyone tested the changes @pedromassango proposed but using the #if TARGET_OS_OSX code instead? I am not sure if it has the desired result on all platforms.

@ryanheise ryanheise reopened this Mar 3, 2022
@ryanheise
Copy link
Owner

Reopening.

@pedromassango
Copy link
Author

Yes I agree something should be done about that, but has anyone tested the changes @pedromassango proposed but using the #if TARGET_OS_OSX code instead? I am not sure if it has the desired result on all platforms.

Ok then, honestly I don't have much experience with native iOS 🐒 I will try to test this and give a feedback asap

@ryanheise
Copy link
Owner

Has anyone tried this solution and tested on both iOS and macOS?

@robert-j-webb
Copy link

robert-j-webb commented May 26, 2022

Any updates on this? I ran into this issue (not sure if it's an entitlement or provisioning issue that I'm having) and I can't do background playback, although this plugin is working great for me on android :)

FYI: When I try to build this version of the source code on iOS I do get the same error:

/Volumes/Samsung_T5/projects/audio_service/audio_service/darwin/Classes
/AudioServicePlugin.m:291:9: error: implicit declaration of function 'os'

FYI I got this to work on iOS by adding


  <key>UIBackgroundModes</key>
  <array>
  <string>audio</string>

to my Info.plist. I guess I missewd that part of the documentation! Sorry! I still see the error though but it doesn't seem to matter. The play / pause buttons still work from the UI

@ryanheise
Copy link
Owner

Regarding the os error, see this commment:

#900 (comment)

@csacchetti
Copy link

I tried to read some iOS documentation and it seems to me that the problem might be related to: MPNowPlayingInfoCenter.default().playbackState

In fact, the solution proposed by the forums is this;

https://developer.apple.com/forums/thread/678108
Solution: don't use MPNowPlayingInfoCenter.default().playbackState
Why: I only care about iOS. This doc shows that this is only for macOS https://developer.apple.com/documentation/mediaplayer/mpnowplayinginfocenter/2588243-playbackstate

So if you don't have macOS enabled in xCode you don't have the com.apple.mediaremote.set-playback-state entitlements for the macOS playback state, and so if the Audio Service plugin also supports macOS it is likely to use MPNowPlayingInfoCenter.default().playbackState and thus create the problem.

I have no interest in enabling MacOs for my app (is only for iOS and Android) so I can't verify this but I think @ryanheise could enable this command only if MacOs is enabled and instead disable it if MacOs is not enabled

This explains why in spite of this problem in iOS everything works correctly.

I hope it helps

@ryanheise
Copy link
Owner

That is why I referred readers to #900 (comment) which explains how to correctly "compile out" this code when it is not needed on iOS.

The main reason that this PR hasn't been merged yet is that it does not use the correct preprocessing instructions to do this. The secondary reason is that it needs to be tested and verified to ensure that people no longer get the warning/

@pedromassango
Copy link
Author

@ryanheise I honestly think that this is not the fix for the problem I stated in the original post. I would suggest to close this!

@mhassan772
Copy link

I am getting this same error, everything is working except for custom click() in audio_service. In Android I am able to do custom action based on the headset clicks, but not on iOS at all. For iOS the headset does the default actions instead.
Do you think this error is related to that somehow?

@volgin
Copy link

volgin commented May 11, 2023

I saw this comment on one of Apple's forums:

playbackState is available for MacOS but also for CarPlay implementation. Only by using playbackState I got correct behaviour with CarPlay on simulator.

Can this be the cause of the issue? I don't have CarPlay entitlement for my app, and I do see this warning message. I am applying for CarPlay entitlement. I will test when I get approved.

@anatoliisudor
Copy link

I did a quick test of the proposed changes in this PR and confirmed the way @ryanheise proposes to fix it - works.

NSLog(@"### ENSURE THIS IS UPDATED CODE 0.18.12 Darwin");
#if TARGET_OS_OSX
    if (@available(iOS 13.0, macOS 10.12.2, *)) {
        center.playbackState = playing ? MPNowPlayingPlaybackStatePlaying : MPNowPlayingPlaybackStatePaused;
    }
#endif

And then logs are clear when testing on iOS

2023-09-27 13:17:08.334248+0300 Sudor Staging[1347:69326] flutter: AUDIO MANAGER AUDIOSESSION CALL 8
flutter: AUDIO MANAGER AUDIOSESSION CALL 8
2023-09-27 13:17:08.439089+0300 Sudor Staging[1347:69278] ### ENSURE THIS IS UPDATED CODE 0.18.12 iOS
2023-09-27 13:17:08.444080+0300 Sudor Staging[1347:69278] ### ENSURE THIS IS UPDATED CODE 0.18.12 iOS
2023-09-27 13:17:08.457794+0300 Sudor Staging[1347:69278] ### ENSURE THIS IS UPDATED CODE 0.18.12 iOS
2023-09-27 13:17:08.644577+0300 Sudor Staging[1347:69278] ### ENSURE THIS IS UPDATED CODE 0.18.12 iOS

Important - not only darwin/Classes/AudioServicePlugin.m file needs to be changed, but also:

ios/Classes/AudioServicePlugin.m
macos/Classes/AudioServicePlugin.m

I'm struggling with how to test it with macOS, but I will manage later this week, I hope.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants