Swift - trouble integrating Google AdMob with my application - ios

I'm attempting to implement ads for my iOS application using Google's AdMob SDK.
I've been following the official [docs](https://developers.google.com/admob/ios/quick-start), but I'm having trouble getting that to work.
What I've done so far:
Created an AdMob account and registered my app.
Updated my info.plist so it matches the format shown in the tutorial.Needless to say, I replaced the tutorial's app ID with the ID I got from my Google AdMob account.
Building my application as-is with the info.plist changes (without any imports or additional code) already introduced some weird logs:
2020-11-16 03:14:08.242623+0200 [5520:1418287] - <Google>[I-ACS025031] AdMob App ID changed. Original, new: (nil), ca-app-pub-2838133095156647~5679250242
2020-11-16 03:14:08.249700+0200 [5520:1418287] [NetworkInfo] Could not successfully update network info for descriptor <CTServiceDescriptor 0x281b3cec0, domain=1, instance=2> during initialization.
2020-11-16 03:14:08.250665+0200 [5520:1418287] [NetworkInfo] Signal strength query returned error: Error Domain=NSPOSIXErrorDomain Code=13 "Permission denied", descriptor: <CTServiceDescriptor 0x281b3f1a0, domain=1, instance=1>
2020-11-16 03:14:08.251144+0200 [5520:1418287] [NetworkInfo] Signal strength query returned error: Error Domain=NSPOSIXErrorDomain Code=13 "Permission denied", descriptor: <CTServiceDescriptor 0x281b3cec0, domain=1, instance=2>
2020-11-16 03:14:08.258569+0200 [5520:1418287] - <Google>[I-ACS023007] Analytics v.70100000 started
2020-11-16 03:14:08.259511+0200 [5520:1418287] - <Google>[I-ACS023008] To enable debug logging set the following application argument: -APMAnalyticsDebugEnabled (see https://help.apple.com/xcode/mac/8.0/#/dev3ec8a1cb4)
2020-11-16 03:14:08.285264+0200 [5520:1418283] [MC] System group container for systemgroup.com.apple.configurationprofiles path is /private/var/containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles
2020-11-16 03:14:08.286833+0200 [5520:1418283] [MC] Reading from public effective user settings.
2020-11-16 03:14:08.303409+0200 [5520:1418283] - <Google>[I-ACS800023] No pending snapshot to activate. SDK name: app_measurement
2020-11-16 03:14:08.325373+0200 [5520:1418286] - <Google>[I-ACS023012] Analytics collection enabled
Then, I downloaded Google-Mobile-Ads-SDK using cocoapods & attempted to initialize the mobile ads SDK with the following code:
AppDelegate.swift:
// other imports
import GoogleMobileAds
#main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window : UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions: [UIApplication.LaunchOptionsKey : Any]?) -> Bool {
GADMobileAds.sharedInstance().start(completionHandler: nil)
if #available(iOS 13, *) {
return true
}
else {
self.window = UIWindow()
let vc = ViewController()
self.window!.rootViewController = vc
self.window!.makeKeyAndVisible()
}
return true
}
...
This introduces a new error: Main Thread Checker: UI API called on a background thread (in addition to the weird loggings from #3 that remain).
What is my problem? Any help would be appreciated!

I ended up solving my issue by using an older version of the SDK, version 7.43.0 worked for me.
In order to solve the UI API problem, I also had to use DispatchQueue.main.async:
ViewController.swift
override func viewDidLoad() {
DispatchQueue.main.async {
self.interstitial = self.createAndLoadInterstitial()
}
...
I wrote the createAndLoadInterstitial on a separate file:
AdMob.swift
import GoogleMobileAds
extension ViewController: GADInterstitialDelegate {
func createAndLoadInterstitial() -> GADInterstitial {
self.interstitial = GADInterstitial(adUnitID: "ca-app-pub-3940256099942544/4411468910") // Google's test interstitial adUnitID
interstitial.delegate = self
interstitial.load(GADRequest())
return interstitial
}
func interstitialDidDismissScreen(_ ad: GADInterstitial) {
// on interstitial dismiss - load another one
self.interstitial = createAndLoadInterstitial()
}
}
Hopefully future Googlers find this helpful :)

Related

Is Sign in with Apple (SIWA) supported in the tvOS simulator?

I have enabled the entitlements for SIWA in the project target. And the same steps are working fine in the iOS simulator.
I am facing the following issue while trying to Sign in with Apple (SIWA) on the tvOS simulator.
Steps to reproduce the issue:
Upon requesting for SIWA on custom button tap, a full-screen layover displayed for the password of apple id (No option for choosing email relay was given) (screenshot attached in the last for reference)
Upon entering the correct password I get the callback in the error delegate.
Error in the error delegate:
error Error Domain=com.apple.AuthenticationServices.AuthorizationError Code=1000 "(null)"
Below is the code-snippet attached for the whole process.
I have done all the steps required as per the official document of SIWA for iOS.
FYI: The same code is working for iOS for me but not for the tvOS. I have tested SIWA in the iPhone simulator while development and now trying the same with the tvOS but it isn't working.
Below is my code.
Here, function setup( ) is called on viewDidLoad of ViewController
private func setup() {
if #available(tvOS 13.0, *) {
let appleIDProvider = ASAuthorizationAppleIDProvider()
appleIDProvider.getCredentialState(forUserID: "myapp.identifiers.currentUserIdentifier") { (credential, error) in
switch credential {
case .authorized:
print("authorized for sign in")
break
case .notFound, .revoked, .transferred:
print("ready to logout")
break
default:
print("Apple sign in credential state unidentified")
}
}
}
}
Inside the action method of the custom SIWA button, my code looks like
if #available(tvOS 13.0, *) {
let appleIDProvider = ASAuthorizationAppleIDProvider()
let request = appleIDProvider.createRequest()
request.requestedScopes = [.fullName, .email]
let authorizationController = ASAuthorizationController(authorizationRequests: [request])
authorizationController.delegate = self
authorizationController.presentationContextProvider = self
authorizationController.performRequests()
}
The presentation anchor is set in the extension of ViewController
extension ENWelcomeScreenViewController: ASAuthorizationControllerPresentationContextProviding {
#available(tvOS 13.0, *)
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
return self.view.window!
}
}
And finally, the error delegate, in which I am receiving the callback.
/// - Tag: did_complete_error
#available(tvOS 13.0, *)
func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
print("error \(error)")
}
Here is how it looks when the user taps on SIWA button.
Any leads are highly appreciated.
The answer to my question is a big no!!
FINDINGS:
We can not test the sign in with apple in the tvOS simulator.
When I tried running the same on Apple TV it worked.
After entering the apple id credentials to sign-in in my app I get the push notification on the device I am signed-in with the same apple id.
Nothing happens when you tap on the received push notification.
On the Apple forum, I get a similar response from their engineering team.
Here is a screen capture of Apple TV.
Just had the same issue. The simple solution is to take the term "nearby" more than literally. Hold your phone really close to the Apple TV when tapping the notification and everything will do its magic.

Swift 5 App - AdMob returns Timeout (XCode)

I want to show a Reward Ad (Google AdMob) in my swift app. (XCode 11.4, Swift 5, Storyboard), but whenever I load the ad it shows the following error message in the console:
Error Domain=com.google.admob Code=5
"Request Error: The Google Ad request was unable to be fulfilled before a timeout occurred."
UserInfo={NSLocalizedDescription=Request Error: The Google Ad request was unable to be fulfilled before a timeout occurred., gad_response_info=<GADResponseInfo: 0x6000030f8090>}
I basically followed the tutorial from Google AdMob Tutorial.
I added my GADApplicationIdentifier to the info.plist
In the AppDelegate:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
GADMobileAds.sharedInstance().start(completionHandler: nil)
}
In the ViewController I followed the steps from the new RewardAd Tutorial and basically copied and pasted it, except for replacing the AdId with my own (I'm running it in a Simulator, so using own AdID's should not be a problem if I understood correctly...)
This is where it fails:
override func viewDidLoad() {
super.viewDidLoad()
rewardedAd = GADRewardedAd(adUnitID: adId)
rewardedAd?.load(GADRequest()) { error in
if let error = error {
print("Error while loading ad: \(error.description)")
// Timeout occurs here!!!
} else {
if self.rewardedAd?.isReady == true {
self.rewardedAd?.present(fromRootViewController: self, delegate:self)
}
}
}
}
Any idea why I get the timeout?
Note:
I also created a sample SwiftUI app with the same rewarded app structure, which also gets the timeout
and yes my internet connection works just fine
I tried the example AdIds from AdMob too, then I get the following error:
Error while loading ad: Error Domain=com.google.admob Code=1
"Request Error: No ad to show."
UserInfo={NSLocalizedDescription=Request Error: No ad to show., gad_response_info=<GADResponseInfo: 0x6000018f4d80>}
I used in the 'info.plist' : ca-app-pub-3940256099942544~1458002511
and for the AdID : ca-app-pub-3940256099942544/1712485313 both from the above mentioned tutorial pages from Google.
I think you should use your own appID with test Ad ID.

How to fix `The user canceled the sign-in flow.` with Sign In with Google on iOS?

I am integrating Sign in with Google with iOS Firebase SDK. When a user taps on the GIDSignIn button, the app shows an alert showing "MyAPP" want to use Google.com for Sign in, but the alert dismisses quickly. The error I get in the didSignInFor user: GIDGoogleUser method as follows:
2019-02-21 16:54:13.104279+0530 MyApp[18743:185089] [Warning] Attempting to load the view of a view controller while it is deallocating is not allowed and may result in undefined behavior (<SFAuthenticationViewController: 0x7fa327945800>)
[DEBUG] Google sign-in error: Error Domain=com.google.GIDSignIn Code=-5 "The user canceled the sign-in flow." UserInfo={NSLocalizedDescription=The user canceled the sign-in flow.}
I have followed the Authenticate Using Google Sign-In on iOS documentation.
I also tried the answer at Google Sign-In crashes on iOS 9 attempting to call canOpenURL, but it is not working.
The AppDelegate implements GIDSignInUIDelegate as well.
If I change the button from GIDSignInButton to UIButton, it works, but the style is lost.
I also faced the issue before. The GIDSignInButton object don't need addTarget in code or linking #IBAction. The GIDSignInButton class already handle that action for us.
If you are trying to to run GIDSignIn.sharedInstance()?.signIn() in #IBAction. You can run GIDSignIn.sharedInstance()?.presentingViewController = self just before signIn instead of insideviewDidLoad().
#IBAction func googleLogin(_ sender: UIButton) {
GIDSignIn.sharedInstance()?.presentingViewController = self
GIDSignIn.sharedInstance()?.signIn()
}
In Appdelegate try using the below code
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
let result = GIDSignIn.sharedInstance().handle(url,
sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String,
annotation: options[UIApplication.OpenURLOptionsKey.annotation])
return result
}

iOS swift You must specify clientID Exception in google integration

Code:
let signIn = GPPSignIn.sharedInstance()
signIn.shouldFetchGooglePlusUser = true
signIn.clientID = "912597493260-qg351fl8olmnmjl8qobos8n6u909jp0o.apps.googleusercontent.com"
signIn.scopes = [kGTLAuthScopePlusLogin];
signIn.trySilentAuthentication();
GIDSignIn.sharedInstance().signInSilently()
signIn.delegate = self
due to uncaught exception 'NSInvalidArgumentException', reason: 'You must specify |clientID| for |GIDSignIn|
I double checked my code.Even i set client-id getting this exception.Where i went wrong?any help will be appreciated.thanks in advance
I was following Google's own guide for adding Sign-In here. I followed it step by step - integrated the google configuration file too. As per the guide, if the configuration file was included, setting the client id manually was not required. Unfortunately, I encountered exactly the same error when I run the app and hit the Sign-In button:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'You must specify |clientID| for |GIDSignIn|'
Solution:
For some reason, clientID was not automatically picked from the configuration file. We should instead configure the GIDSignIn object directly, (using the client ID found in the GoogleService-Info.plist file) in the app delegate's application:didFinishLaunchingWithOptions: method:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Initialize sign-in
var configureError: NSError?
GGLContext.sharedInstance().configureWithError(&configureError)
assert(configureError == nil, "Error configuring Google services: \(configureError)")
GIDSignIn.sharedInstance().clientID = "Cliend id From GoogleService-Info.plist file"
GIDSignIn.sharedInstance().delegate = self
return true
}
Also, if you are using Firebase, you can do it this way too:
GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
It looks like the auto-generated config file, GoogleService-Info.plist, will include the wrong credentials by default; it includes the Web Client credentials instead of the iOS app credentials.
You need to correct the Client ID and the Reverse Client ID in the GoogleService-Info.plist.
Since these credentials are also used in your app's URLSchemes, you need to correct this there too.
I was also facing the same issue. I followed every step as per the documentation by https://firebase.google.com/docs/auth/ios/google-signin#swift_9 .
At last, I tried adding Client ID manually on my Controller's viewDidLoad and it worked after a long struggle.
Refer the code below. Replace your project specific Client-ID from GoogleService-info.plist in place of ClientID :
class IntroController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
GIDSignIn.sharedInstance().clientID = "*ClientID*"
GIDSignIn.sharedInstance()?.presentingViewController = self
GIDSignIn.sharedInstance().signIn()
}
}
The clientId definitely does get picked up from the .plist file. If it appears not to be, it is likely that your code is attempting to use the sign-in object before it has been properly configured. Set a breakpoint on your configureWithError line, and make sure that it gets hit before any attempt to set a delegate, perform silent sign-in, etc.
Looks like the sign in method has now been updated by google, I was implementing the Google Calendar for iOS app and I found the following code for Sign In:
func applicationDidFinishLaunching(_ application: UIApplication) {
// Initialize sign-in
var configureError: NSError?
GGLContext.sharedInstance().configureWithError(&configureError)
assert(configureError == nil, "Error configuring Google services: \(configureError!)")
}
in their document which gave the same error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'You must specify |clientID| for |GIDSignIn|'
I took the lines which were inside:
func applicationDidFinishLaunching(_ application: UIApplication)
and put them in this method and sign in worked:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
Code for refernce:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// Initialize sign-in
var configureError: NSError?
GGLContext.sharedInstance().configureWithError(&configureError)
assert(configureError == nil, "Error configuring Google services: \(configureError!)")
return true
}
You may need to obtain GoogleService-Info.plist from https://console.firebase.google.com rather than https://console.developers.google.com/.
Using Firebase remember also that you have to call Firebase.configure() function before you set the clientId. Otherwise, it won't work.

Integrating google analytics into iOS app

I'm following the instructions on here to integrate google analytics into my app: https://developers.google.com/analytics/devguides/collection/ios/v3/?ver=swift#get-config
I'm at the point where I need to initialize analytics for my app. I've added this code in my AppDelegate.swift file:
import UIKit
import <Google/Analytics.h>
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions:[NSObject: AnyObject]?) -> Bool {
**// Configure tracker from GoogleService-Info.plist.
NSError *configureError;
[[GGLContext sharedInstance] configureWithError:&configureError];
NSAssert(!configureError, #"Error configuring Google services: %#", configureError);
// Optional: configure GAI options.
GAI *gai = [GAI sharedInstance];
gai.trackUncaughtExceptions = YES; // report uncaught exceptions
gai.logger.logLevel = kGAILogLevelVerbose; // remove before app release**
}
I'm getting the following error messages.
For my import <Google/Analytics.h> line, I'm getting this message:'Consecutive statements on a line must be separated by ';'.
For the rest of the code I'm getting several errors, although I simply copied the code in the tutorial into my file. See my screenshot.
enter image description here
You're getting this issue since you're in a Swift project. You'll need to create an Objective-C bridging header, and add the import statement there. Afterwards, everything should work properly. Check out this SO answer for more details:
https://stackoverflow.com/a/24005242/1784384

Resources