App does not support leaderboards - iMessage App - ios

I have an iMessage app, and trying to get Leaderboard scores. I am getting error:
Error Domain=GKErrorDomain Code=3 "The requested operation could not
be completed due to an error communicating with the server."
UserInfo={GKServerStatusCode=5043, NSLocalizedDescription=The
requested operation could not be completed due to an error
communicating with the server., NSUnderlyingError=0x600000ed3960
{Error Domain=GKServerErrorDomain Code=5043 "status = 5043, MyApp does
not support leaderboards" UserInfo={GKServerStatusCode=5043,
NSLocalizedFailureReason=status = 5043, MyApp does not support
leaderboards}}}
Please note that my app is live, game center is enabled and it has been days since leaderboards were created on iTunes Connect.
func getScoreLeaderboard(leaderboardIdentifier:String, completion:#escaping ((_ resultScore:GKScore?) -> Void)) {
let leaderBoardRequest = GKLeaderboard()
leaderBoardRequest.identifier = leaderboardIdentifier
leaderBoardRequest.loadScores {
(resultGKScore, error) in
guard error == nil && resultGKScore != nil else {
completion(nil)
return
}
completion(leaderBoardRequest.localPlayerScore)
}
}
I have a doubt, but not sure it can be the problem. Problem might be:
I have an iMessage app with Bundle ID e.g. com.mygame. On iTunes Connect, I made a test app to check in app purchase issue encountered. And its Bundle ID is com.mygame.MessagesExtension.
I think that it is trying to get Leaderboard from app with extension bundle ID. Can it be possible? Since my app com.mygame is live, I am unable to delete extension test app, though it is not being used.
Any help is appreciated.

I confirm that Leaderboard was being retrieved from test app instead of actual one. I end up implementing scores management via Firebase instead of Game Center. Apple customer services are pathetic.

Related

Getting error of "Publisher identifiers not found" when I enable "debugGeography" in AdMob

I am trying to test my GDPR compliance code and trying to display the consent form for AdMob but I get this error:
Consent info update failed. Error: Error Domain=Consent Code=1
"Response error. Publisher identifiers not found: ca-app-pub-0123456789012345"
I have triple checked, my publisherID is correct, it is something like "pub-0123456789012345".
When I check my AdMob account status I see that
"Your account is active and in good standing."
I have followed the directions of Google to receive user consent for personalized ads. I am in the USA, so use this line:
PACConsentInformation.sharedInstance.debugGeography = .EEA
When I disable this line, I don't get the error above anymore, but the error below:
Error loading form: Error: request is not in EEA or unknown.
I have tried to use this line instead but nothing changed:
PACConsentInformation.sharedInstance.debugGeography = PACDebugGeography.EEA
My only guess is that for the reason that my AdMob account is USA based, I get "publisherID not found" error when I enable ".EEA". But how can I do the testing if my guess is true?
I am doing the testing both on simulator and on the phone. I could not manage to display the consent form anywhere.
The code I am using is below:
// advertiseIDOfPhone and publisherID are constants defined elsewhere
PACConsentInformation.sharedInstance.debugIdentifiers = [advertiseIDOfPhone]
PACConsentInformation.sharedInstance.debugGeography = .EEA
PACConsentInformation.sharedInstance.requestConsentInfoUpdate(forPublisherIdentifiers: [publisherID])
{(_ error: Error?) -> Void in
if let error = error {
// Consent info update failed.
print("☢️ Consent info update failed. Error: \(error)")
} else {
print("☢️ Consent info updated.")
// Consent info update succeeded. The shared PACConsentInformation
// instance has been updated.
switch PACConsentInformation.sharedInstance.consentStatus {
case .nonPersonalized:
print("☢️ Personalized ads consent NOT given.")
case .personalized:
print("☢️ Personalized ads consent given.")
case .unknown:
print("☢️ Unknown consent.")
guard let privacyUrl = URL(string: "yourWebsiteURL"),
let form = PACConsentForm(applicationPrivacyPolicyURL: privacyUrl) else {
print("incorrect privacy URL.")
return
}
form.shouldOfferPersonalizedAds = true
form.shouldOfferNonPersonalizedAds = true
form.shouldOfferAdFree = true
form.load {(_ error: Error?) -> Void in
print("⚛️ Load complete.")
if let error = error {
// Handle error.
print("⚛️ Error loading form: \(error.localizedDescription)")
} else {
form.present(from: self) { (error, userPrefersAdFree) in
if error != nil {
// Handle error.
} else if userPrefersAdFree {
// User prefers to use a paid version of the app.
//buy the pro Version
}
}
}
}
default:
break
}
print("☢️ isRequestLocationInEEAOrUnknown: \(PACConsentInformation.sharedInstance.isRequestLocationInEEAOrUnknown)")
}
}
Where can be my mistake here? Is the code I am using good?
--
It seems that this is a known bug:
Kindly note that we are aware of this issue, and our Engineering team
is already working on a resolution. Rest assured that we are keeping
an eye out on this, and that we will update you for any news regarding
this issue.
Regards, Ziv Yves Sanchez Mobile Ads SDK Team
I didn't expect a bug from Google in such a fundamental aspect of a big product and unfortunately I have spent hours on this problem trying to find my mistake somewhere...
While they work on a resolution, you can use the Google Test Publisher ID:
pub-3940256099942544
My account gives me the error but I was able to use the test ID to implement and test the Consent SDK. Just make sure you switch back to your ID before you distribute the app.
I got the Same Issue!
This is not our Code's fault. Admob not serving ads.
Go to Admob Console
In Home There is Dialog Box: "Don't serve Until PaymentDetails Entered"
Click the Learn more and create an AdSense account
after that enter payment details
That's all they will serve ads after 24 hours after the account verified
I have the same issue.
Until I updated my settings on https://fundingchoices.google.com.
Go to the webpage, select APP on the left side, go in and activate the app you are using.

How to check if Apple Music is installed on the user's device?

I am making a music app with swift. The app lets users play music through their Apple Music subscription via their Apple Music app. I am able to check whether the user has an Apple Music subscription via:
SKCloudServiceController().requestCapabilities { (capability:SKCloudServiceCapability, err:Error?) in
guard err == nil else {
print("error in capability check is \(err!)")
return
}
if capability.contains(SKCloudServiceCapability.musicCatalogPlayback) {
print("user has Apple Music subscription")
}
if capability.contains(SKCloudServiceCapability.musicCatalogSubscriptionEligible) {
print("user does not have subscription")
}
}
However: there are scenarios where somebody will, for some reason, have an Apple Music subscription but not have the Apple Music app downloaded on their device. If the user has the subscription but not the device, I want to essentially treat that case as if they do not have a subscription at all, i.e. we cannot play music via Apple Music.
So, I go searching for ways to add a check for if Apple Music is on the user's device. I find this answer: Check whether an app is installed using Swift combined with this resource for finding Apple Music's url scheme and conclude I can check if a user has both an Apple Music subscription and the Apple Music app installed on their device via:
SKCloudServiceController()requestCapabilities { (capability:SKCloudServiceCapability, err:Error?) in
guard err == nil else {
print("error in capability check is \(err!)")
return
}
if capability.contains(SKCloudServiceCapability.musicCatalogPlayback) && UIApplication.shared.canOpenURL(URL(string: "music://")!) {
print("user has Apple Music subscription and has the apple music app installed")
}
if capability.contains(SKCloudServiceCapability.musicCatalogSubscriptionEligible) || !UIApplication.shared.canOpenURL(URL(string: "music://")!) {
print("user does not have subscription or doesn't have apple music installed")
}
}
The issue is, even after deleting Apple Music from my device, the first case, i.e. the one that prints user has Apple Music subscription and has the apple music app installed is still being called. I believe I have the correct url scheme because when changing "music://" to "musi://", the second case, i.e. the one that prints user does not have subscription or doesn't have apple music installed is being called.
When trying to open URL(string: "music://") with Apple Music deleted via UIApplication.shared.open(URL(string: "music://")!), I am hit with the following alert:
So why is the device saying that I can open URL(string: "music://") even after Apple Music is deleted? Is the URL capable of being opened, but the result is simply the presentation of the above alert? Is this the correct way to confirm that the user has Apple Music installed on their device? Is there even a way to confirm the user has Apple Music installed on their device? If Apple gives users the option to delete the Apple Music app, they should also give developers the ability to check if the app is installed.
The best solution I've got, though I expect there is something better out there, is to use MPMusicPlayer.prepareToPlay(completionHandler:) to check if there is an error when trying to play a track:
SKCloudServiceController().requestCapabilities { (capability:SKCloudServiceCapability, err:Error?) in
guard err == nil else {
print("error in capability check is \(err!)")
return
}
if capability.contains(SKCloudServiceCapability.musicCatalogPlayback) {
print("user has Apple Music subscription")
MPMusicPlayerController.systemMusicPlayer.setQueue(with: ["1108845248"])
systemMusicPlayer.prepareToPlay { (error) in
if error != nil && error!.localizedDescription == "The operation couldn’t be completed. (MPCPlayerRequestErrorDomain error 1.)" {
//It would appear that the user does not have the Apple Music App installed
}
}
}
if capability.contains(SKCloudServiceCapability.musicCatalogSubscriptionEligible) {
print("user does not have subscription")
}
}
I am not sure how this could apply to anybody using Apple Music within their app for anything other than playing tracks, but this seems to definitely work as a check when you are about to play a check. Whenever I am hit with that error, I simply create an alert telling the individual they have an Apple Music subscription but doesn't have the app installed.
Still, it would be great to be able to check without some completion handler as that would allow the boolean check to be integrated into conditional statements (via if capability.contains(SKCloudServiceCapability.musicCatalogPlayback) && hasAppleMusicAppInstalled { //do something }).
Luckily Apple provides you a method which returns false if no app installed on the device is registered to handle the URL’s scheme, or if you have not declared the URL’s scheme in your Info.plist file; otherwise, true.
func canOpenURL(_ url: URL) -> Bool
Following i'm posting the url schemes
Open = music://
Open = musics://
Open = audio-player-event://
Add the ones you will further use into your info.plist file.
After this use 'canOpenURL' to check
for more information check Apple docs
https://developer.apple.com/documentation/uikit/uiapplication/1622952-canopenurl
For the lucky souls that need music app installed to display MPMediaPickerController, the easiest way to check is to see if view was presented. If Music app is missing, it will fail silently.
let mediaPickerController = MPMediaPickerController(mediaTypes: MPMediaType.anyAudio)
mediaPickerController.delegate = self
mediaPickerController.prompt = "prompt"
presenter.present(mediaPickerController, animated: true, completion: nil)
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) { [weak self] () -> () in
if self?.presenter.presentedViewController == nil {
self?.callback(.failure(.failedToPresentMusicPickerError))
}
}
A possible solution is doing the following: Setup a developer token through the Apple Music API (Used so you can query Apple Music REST endpoints). Submit a request to the following StoreKit function (Documentation):
requestUserToken(forDeveloperToken:completionHandler:)
If your developer token is valid and the user token value returned is still nil/null then the device user is not a subscriber of the Apple Music service. An error that is generated with the HTTP status code is 401 (Unauthorized). This still requires you checking an error however does not require to try and play a specific track (Especially for some reason if the content track id your checking against becomes invalid or changed).
For the issue of account signed into the device and has a subscription but not the Music app downloaded: Handle the error upon attempting to play specific content and either provide information to the user or use content that does not require an Apple Music subscription as an alternative when an error occurs.
Yes, We can check most of the Applications by following these Steps:
Use the Deep URL or URL Scheme for the particular application you want to open, add that into info.plist
Use the same URL and Call this method
func canOpenURL(_ url: URL) -> Bool
let url = URL(string: "music://")
UIApplication.shared.open(url!) { (result) in
if result {
// The URL was delivered successfully!
}
}
You can use this property to detect if Apple Music is installed.
import MediaPlayer
var isAppleMusicInstalled: Bool {
get async {
await withCheckedContinuation { continuation in
MPMusicPlayerController.systemMusicPlayer.setQueue(with: ["1108845248"])
self.systemMusicPlayer.prepareToPlay { (error) in
if error != nil && error!.localizedDescription.contains("error 6") {
print("Apple Music App not installed")
continuation.resume(returning: false)
} else {
continuation.resume(returning: true)
}
}
}
}
}
Note that it triggers a permission dialog and that you need to add the NSAppleMusicUsageDescription key in your Info.plist with a value like "to check if Apple Music is installed".
Simply do: UIApplication.shared.canOpenUrl(URL(string: “music://”)!)

NEHotspotConfigurationErrorDomain Error on some devices

I've implemented a WiFi auto-join feature in my app -> Click a button and connect to a named SSID. This works on some devices but also fails on others - meaning it won't even show the Apple pop up asking to join the network. The device might be the same device model, same iOS but fails on some and not on others. This is the error that I see being returned when it fails:
Error Domain=NEHotspotConfigurationErrorDomain Code=10 "cannot modify system configuration." UserInfo={NSLocalizedDescription=cannot modify system configuration.
This is the code used to attempt auto-join:
let WiFiConfig = NEHotspotConfiguration(ssid: "MYSSID")
WiFiConfig.joinOnce = true
NEHotspotConfigurationManager.shared.apply(WiFiConfig) { error in
if error == nil {
//success
} else {
//fail
}
}
Any ideas?
Thanks!
Jennie
I figured out this is unique to our devices using an Embedded Event Manager with a SSID prefilled on the register. That SSID cannot be joined to via the Auto-join feature.

In-App Purchase Display Name and Description not properly loading - Swift 4

I am trying to enable In-App Purchases in Swift 4 for iOS and I can not get the Display Name and Description to properly show up (or load) in the app when I test. I do get the error handing message that I put in if (products.count == 0) {. I can't get the Product Title and Product Description that I set up in AppStoreConnect to properly load when I test my app. Instead the code thinks that there are no products because it runs the code in the if (products.count == 0) { closure. I quadruple checked everything else (i.e. Bundle ID, Product ID, StoreKit's imported, the delegates are set up, everything on the AppStoreConnect side is set up, etc.). There are no Xcode Warnings and the In-App Purchase status is "Ready To Submit". Any suggestions?
var product: SKProduct?
var productID = "myProductID"
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
var products = response.products
if (products.count == 0) {
productTitle.text = "Warning" // GETS DISPLAYED
productDescripton.text = "Unable to connect to In-App Purchase." // GETS DISPLAYED
} else {
product = products[0]
productTitle.text = product?.localizedTitle
productDescripton.text = product?.localizedDescription
buyButton.isEnabled = true
buyButton.alpha = 1.0
}
let invalid = response.invalidProductIdentifiers
for product in invalid {
print("\(product)")
}
}
If you are a rookie at integrating In-App Purchases, then you should read this. If you have clean code and you think that you set everything up properly in App Store Connect, but still can't test properly. Specifically, if your products array is showing empty when it shouldn't be. Then, make sure that you have done the following:
1) Set up a Sandbox Tester via Users and Access in App Store Connect. This needs to be set up with an email that is not already used with iTunes, App Store, or Apple.
2) Filled out all of the necessary forms in Agreements, Tax, and Banking via App Store Connect. You'll know that everything is filled out when Paid Applications shows an Active Status.
3) Are testing on a real device that has been signed out of iTunes and App Store.
Common things that will cause this without warning are:
Your products aren't in the 'Ready to Submit' stage. This is most often from a missing screenshot, which is required even for Sandbox (you can upload a blank image for sandbox testing).
You haven't signed the 'Paid Applications' agreement in App Store Connect
Here's a good blog post that covers everything in a little more detail: Configuring In-app Products is Hard

iOS DeviceCheck API - GenerateToken gives error Code 0

I'm trying to implement the new iOS 11 DeviceCheck API (https://developer.apple.com/documentation/devicecheck), but token generation always fails. I've tried on simulator and iPhone SE, with wifi and mobile data. Apple ID in settings is my normal, non-sandbox account.
This is an existing app for an organization - from the docs it sounds like the only configuration requirement is to make sure App ID is set up in the apple developer portal.
Anyone else having this issue?
The exact error message is:
The operation couldn’t be completed. (com.apple.devicecheck.error error 0.)
This is the code I'm using, nothing fancy.
if #available(iOS 11.0, *) {
let device = DCDevice.current
if (device.isSupported) {
device.generateToken(completionHandler: { (data, error) in
if let token = data{
print("token: \(token)")
}else if let error = error{
print("error: \(error.localizedDescription)")
}
})
} else {
print("devicecheck not supported")
}
}
In my case, this error was caused by my iPhone's time being horribly out of sync. I manually changed the device's time to be the actual, current time (Settings → General → Date & Time). After that, the error went away and I was able to generate tokens.
Your code seems fine to me. The problem is simulator. It won't pass device.isSupported. You need to run it on real device.

Resources