Google Analytics not tracking in Swift - ios

I'm trying to get Google Analytics to run in my Swift project. I'm following this tutorial: https://developers.google.com/analytics/devguides/collection/ios/v3/?ver=swift
It says i'm suppose to include it with #import <Google/Analytics.h> that seems to be objective-c though.. however i'm able to do: import Google
I download the GoogleService-info.plist and the it's target membership to my app.
Then i pasted this code:
// Configure tracker from GoogleService-Info.plist.
var configureError:NSError?
GGLContext.sharedInstance().configureWithError(&configureError)
assert(configureError == nil, "Error configuring Google services: \(configureError)")
// Optional: configure GAI options.
var gai = GAI.sharedInstance()
gai.trackUncaughtExceptions = true // report uncaught exceptions
gai.logger.logLevel = GAILogLevel.Verbose // remove before app releaseAppDelegate.swift
However i don't see any statistics for my app, is there anything i have done wrong or is additional work needed?

You also need to track an event. I think the above code is only for setting up GA in your app. For example, you can add the following code to one of your view controllers whose screen view you want to track :
let tracker = GAI.sharedInstance().defaultTracker
tracker.set("TEST", value: "TEST")
let builder = GAIDictionaryBuilder.createScreenView()
tracker.send(builder.build() as [NSObject : AnyObject])
And also keep in mind, that GA events sometimes take very long to show up on the live tracker in the dashboard.
Hope it helps!

var configureError: NSError?
GGLContext.sharedInstance().configureWithError(&configureError)
assert(configureError == nil, "Error configuring Google services: \(configureError)")
guard let gai = GAI.sharedInstance() else {
assert(false, "Google Analytics not configured correctly")
}
gai.trackUncaughtExceptions = true // report uncaught exceptions
gai.logger.logLevel = GAILogLevel.verbose // remove before app release
gai.dispatchInterval = 20
gai.tracker(withTrackingId: "UA-XXXXXXXX-X")
//Track an event
let tracker = GAI.sharedInstance().defaultTracker
let eventTracker: NSObject = GAIDictionaryBuilder.createEvent(
withCategory: YOUR_CATEGORY_NAME,
action: YOUR_ACTION_NAME",
label: YOUR_LABEL_NAME,
value: nil).build()
tracker?.send(eventTracker as! [AnyHashable: Any])

Related

Make sure GIDClientID is set in Info.plist new GoogleSignIn IOS version

I'm just trying to configure the new GoogleSignIn IOS and keep getting the error.
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'No active configuration. Make sure GIDClientID is set in Info.plist.'
I've scoured the web and the one or two questions on here for solutions however I can't seem to get this error to clear no matter what. This is in my URL Schemes:
and this is my Info.plist
Does anyone have any examples of exactly how my info.plist should look?
Cheers.
I've just faced a similar issue when implementing Firebase Authentication w/ GoogleSignIn.
If you think that you will add new property "GIDClientID" into Info.plist of target project, DON'T DO THAT.
Below are the guidelines of Firebase for Authentication w/ Google, this code fixes the issue above but the way it shows how to use signIn method is invalid at this moment:
guard let clientID = FirebaseApp.app()?.options.clientID else { return }
// Create Google Sign In configuration object.
let config = GIDConfiguration(clientID: clientID)
// Start the sign in flow!
GIDSignIn.sharedInstance.signIn(with: config, presenting: self) { [unowned self] user, error in
// ...
}
There's a solution is to set the configuration to GIDSignIn.sharedInstance before calling signIn method, as below:
guard let clientID = FirebaseApp.app()?.options.clientID else { return }
// Create Google Sign In configuration object.
let config = GIDConfiguration(clientID: clientID)
GIDSignIn.sharedInstance.configuration = config
let scenes = UIApplication.shared.connectedScenes
let windowScenes = scenes.first as? UIWindowScene
let window = windowScenes?.windows.first
guard let rootViewController = window?.rootViewController else { return }
GIDSignIn.sharedInstance.signIn(withPresenting: rootViewController) { signInResult, error in
// ...
}

Getting "Error Domain=NSCocoaErrorDomain Code=257" in a document based app while attempting state restoration

Full error message is:
[main] *** Error from FPBookmarkableStringFromDocumentURL, file:///private/var/mobile/Library/Mobile%20Documents/com~apple~CloudDocs/MY_APP/hello.txt -> Error Domain=NSCocoaErrorDomain Code=257 "The file couldn’t be opened because you don’t have permission to view it."
This error is thrown from a SceneDelegate (introduced in iOS 13) when I relaunch my app & attempt to reopen previously opened file (for example when the app was "backgrounded" & the memory freed, so I want to reload the state of the scene).
I followed the steps from this WWDC session https://developer.apple.com/videos/play/wwdc2019/212 & the downloaded example source code from https://developer.apple.com/documentation/uikit/app_and_environment/scenes/supporting_multiple_windows_on_ipad
I basically copied their configure(window: UIWindow?, with activity: NSUserActivity) -> Bool function and transformed it to fit my needs. It seems to work, flawlessly, but I'm getting the error.
I'm using the default NSUserActivity technique described in "Adopting Handoff in Document-Based Apps" section of https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/Handoff/AdoptingHandoff/AdoptingHandoff.html#//apple_ref/doc/uid/TP40014338-CH2-SW17
Here's the body of the configure function:
if activity.activityType == "com.myName.MyApp.openedDocumentUserActivity" {
if let documentURL = activity.userInfo?[UIDocument.userActivityURLKey] as? URL {
if let docBrowserVC = window?.rootViewController as? DocumentBrowserViewController {
documentURL.startAccessingSecurityScopedResource() // tried this, it returns false
docBrowserVC.presentDocument(at: documentURL)
return true
}
}
}
return false
If anyone knows about a workaround, thank you.
I had to create bookmark data from the URL and persist that in the NSUserActivity. Using UIDocument.documentURL is not sufficient because it is security-scoped.
For creating the bookmark (no error checking in this snippet):
let userActivity = NSUserActivity(activityType: "com.foobar")
let bookmarkData = try? documentURL.bookmarkData()
userActivity.addUserInfoEntries(from: ["URLBookmarkData": bookmarkData])
scene.userActivity = userActivity
Then for reading:
let bookmarkData = userActivity.userInfo?["URLBookmarkData"] as? Data {
let resolvedURL = try? URL(resolvingBookmarkData: bookmarkData, options: NSURL.BookmarkResolutionOptions(), relativeTo: nil, bookmarkDataIsStale: &bookmarkDataIsStale)

How to use AWS Rekognition to detect Image Labels and Faces in Swift 3

So I've been trying to use the AWSRekognition SDK in order to detect faces and labels in images. However, Amazon has no Documentation on how to integrate their SDK with iOS. They have links that show how to work with Rekognition (Developer Guide) with examples only in Java and very limited.
Amazon Rekognition Developer Guide
If you click on their "iOS Documentation", it takes you to the general iOS documentation page, with no signs of Rekognition in any section.
AWS iOS Developer Guide
I wanted to know if anyone knows how to integrate AWS Rekognition in Swift 3. How to Initialize it and make a request with an image, receiving a response with the labels.
I already downloaded the AWSRekognition.framework and the AWSCore.framework and added them into my project. Also I have imported both of them in my AppDelegate.swift and initialized my AWS Credentials.
let credentialsProvider = AWSCognitoCredentialsProvider(
regionType: AWSRegionType.usEast1,
identityPoolId: "us-east-1_myPoolID")
let configuration = AWSServiceConfiguration(
region: AWSRegionType.usEast1,
credentialsProvider: credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
Also I've tried to initialize Rekognition and build a Request:
do {
let rekognitionClient:AWSRekognition = AWSRekognition(forKey: "Maybe a Key from AWS?")
let request: AWSRekognitionDetectLabelsRequest = try AWSRekognitionDetectLabelsRequest(dictionary: ["image": UIImage(named:"TestImage")!, "maxLabels":3, "minConfidence":90], error: (print("error")))
rekognitionClient.detectLabels(request) { (response:AWSRekognitionDetectLabelsResponse?, error:Error?) in
if error == nil {
print(response!)
}
}
} catch {
print("Error")
}
Thanks a lot!
The documentation on the web for the Rekognition iOS SDK is lacking but the comments in the SDK code were pretty helpful for me. If you hold Cmd while clicking on a keyword in Xcode you should be able to find all the info you need in the comments.
From this you can see that the Key is referring to a previously registered client which you can do with registerRekognitionWithConfiguration, but you can skip all that by using the default as Karthik mentioned:
let rekognitionClient = AWSRekognition.defaultRekognition()
I have been working with face detection so I haven't used AWSRekognitionDetectLabelsRequest in my own code, but I think where you might be going wrong is that the image property of AWSRekognitionDetectLabelsRequest should be an AWSRekognitionImage and not a UIImage like you are passing in. You can call UIImageJPEGRepresentation to get the raw bytes from a UIImage.
let sourceImage = UIImage(named: "TestImage")
let image = AWSRekognitionImage()
image!.bytes = UIImageJPEGRepresentation(sourceImage!, 0.7)
guard let request = AWSRekognitionDetectLabelsRequest() else {
puts("Unable to initialize AWSRekognitionDetectLabelsRequest.")
return
}
request.image = image
request.maxLabels = 3
request.minConfidence = 90
It should also be a lot easier to debug if you set the request properties individually like this too.
let credentialsProvider = AWSCognitoCredentialsProvider(regionType:.EUWest1,
identityPoolId:"please enter pool id")
let configuration = AWSServiceConfiguration(region:.EUWest1, credentialsProvider:credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
let rekognitionClient = AWSRekognition.default()
let image = AWSRekognitionImage()
image!.bytes = UIImageJPEGRepresentation(sourceImages, 0.7)
guard let request = AWSRekognitionDetectLabelsRequest()
else {
puts("Unable to initialize AWSRekognitionDetectLabelsRequest.")
return
}
request.image = image
request.maxLabels = 5
request.minConfidence = 90
rekognitionClient.detectLabels(request) { (response:AWSRekognitionDetectLabelsResponse?, error:Error?) in
if error == nil {
print("response ",response)
}
}
}

Google Analytics crash with Swift 2.0

I've just installed GoogleAnalytics from CocoaPods and tried to use it, suddenly it crashes with an error:
fatal error: unexpectedly found nil while unwrapping an Optional value
The crash occurs in this part:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
let tracker = GAI.sharedInstance().defaultTracker
tracker.set(kGAIScreenName, value: "Main")
let builder = GAIDictionaryBuilder.createScreenView()
tracker.send(builder.build() as [NSObject : AnyObject])
}
And when reaching this line:
tracker.set(kGAIScreenName, value: "Main")
Maybe it has something to do with the framework is bridged from Objective-C?
Update
So I fixed the crash by wrapping it with an if statment and still nothing sent to Google Analytics:
let name = "Main"
if let gai = GAI.sharedInstance() {
if let tracker: GAITracker = gai.trackerWithTrackingId("TRACKING_ID") {
tracker.set(kGAIScreenName, value: name)
let builder = GAIDictionaryBuilder.createScreenView()
tracker.send(builder.build() as [NSObject : AnyObject])
print("tracker initialized")
}
}
The docs for the GAI class have this to say about defaultTracker
>
For convenience, this class exposes a default tracker instance.
This is initialized to nil and will be set to the first tracker that is instantiated in trackerWithTrackingId:. It may be overridden as desired.
So I'm guessing you need to call trackerWithTrackingId: somewhere, or if you are already doing it, make sure it happens before this method is called.
So I figured out the problem, I used Google Analytics with CocoaPods as explained in the Google Analytics iOS tutorial and added this line to the Bridging Header file:
#import <Google/Analytics.h>
but I guess that's not enough, after adding these lines:
#import <GoogleAnalytics/GAI.h>
#import <GoogleAnalytics/GAIDictionaryBuilder.h>
#import <GoogleAnalytics/GAILogger.h>
#import <GoogleAnalytics/GAITrackedViewController.h>
#import <GoogleAnalytics/GAITracker.h>
It worked perfect. (Thanks Rich Tolley for the help)
For me I had to add those lines in the AppDelegate:
var configureError:NSError?
GGLContext.sharedInstance().configureWithError(&configureError)
assert(configureError == nil, "Error configuring Google services: \(configureError)")

iOS Swift : error with google login

I was following this tutorial to add google sign in in my iOS app using swift. I followed all the steps as mentioned but when I try to build app then it is giving me an issue in my appdelegate.swift file.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
var configureError: NSError?
GGLContext.sharedInstance().configureWithError(&configureError)
assert(configureError == nil, "Error configuring Google services: \(configureError)")
GIDSignIn.sharedInstance().clientID = "client id"
return true
}
so below line of code
GGLContext.sharedInstance().configureWithError(&configureError)
Error text is "Use of unresolved identifier GGLContext". What could be the issue here ?
in Bridging-Header.h
import <GoogleSignIn/GoogleSignIn.h>
import <Google/Core.h>
in AppDelegate.swift
import Google
Preliminary:
I have been annoyed for a few days now that when I integrated the Cocoapod Google/SignIn that I was getting Thread warnings. After digging into everything, I may have found a solution. This probably would only be something worth looking at if the only aspect of google you want in your project in sign in. If you have Firebase or any other part of google integrated, you probably will never hit an issue that leads you to this thread though.
OK, after delving into this problem for a bit, I found my solution to be:
In Bridging Header import only #import <GoogleSignIn/GoogleSignIn.h>
In AppDelegate import only import GoogleSignIn
In Podfile import only pod 'GoogleSignIn'
In AppDelegate didFinishLaunchingWithOptions do domething like this:
if let path = Bundle.main.path(forResource: "GoogleService-Info", ofType: "plist"),
let googleInfo = NSDictionary(contentsOfFile: path),
let clientId = googleInfo["CLIENT_ID"] as? String {
GIDSignIn.sharedInstance().clientID = clientId
}
GIDSignIn.sharedInstance().delegate = self
and remove:
var configureError: NSError?
GGLContext.sharedInstance().configureWithError(&configureError)
assert(configureError == nil, "Error configuring Google services: \(configureError!)")
With this setup, everything seems to be working great. I got the idea by looking at the link below. Let me know if this works for you.
https://github.com/googlesamples/google-services/blob/master/ios/signin/SignInExampleSwift/AppDelegate.swift
I found the solution, You can use the Bridge-Header.h file and import like that
#ifndef Bridge_header_h
#define Bridge_header_h
#import "Google/Core.h"
#import "GoogleSignIn.h"
#endif /* Bridge_header_h */
it's work perfectly at my end.
in swift, the below worked for me.
import GoogleSignIn

Resources