How to get unique user ID for HockeyApp? - ios

In the HockeyApp SDK v. 3.5, they have shifted to a new method of user identification. In previous versions of the SDK, there was a callback method - (NSString*)userNameForCrashManager:(BITCrashManager *)crashManager which would set a string which would identify all crash reports sent from the client.
However, in version 3.5 of the SDK, it seems that this is deprecated, and it is preferred that you simply call:
[[BITHockeyManager sharedHockeyManager].authenticator authenticateInstallation];
This sets a unique ID for the user. But how can I access this identifier? I want to attach it to support emails so that I can search for crash reports the user has submitted.

You can use the following delegate to set the userName:
- (NSString *)userNameForHockeyManager:(BITHockeyManager *)hockeyManager componentManager:(BITHockeyBaseManager *)componentManager
This is documented in the header and help ofBITHockeyManagerDelegate and the replacement is also mentioned in the header and help of BITCrashManagerDelegate documentation.
BITAuthenticator is only used for beta distribution due to the fact that Apple removed the UDID calls from iOS 7. See the documentation and help. It is automatically disabled in App Store builds and without further setup creates anonymous IDs! Please read the mentioned documentation.

I think you are looking for publicInstallationIdentifier. That should return an NSString, unique for each user.
Look at this header file - BITAuthenticator.h .
Also, in the BITHockeyManager, there is a method called configureWithIdentifier: in which you can pass the identifier.

Related

Is there a way to recognize, that the app was installed thru firebase dynamic link in didFinishLaunchingWithOptions?

I am implementing firebase dynamic links in my iOS app and I can already parse the link, redirect to AppStore etc. Now I want to distinguish the first run of the app, when user installs it from the dynamic link - I want to skip the intro and show him the content that is expected to be shown.
Is there some parameter, that I could catch in application(_:didFinishLaunchingWithOptions:) so I could say that it was launched thru the dynamic link?
The method application(_:continueUserActivity:userActivity:restorationHandler:) is called later, so the intro is already launched.
This case is difficult to test, because you have to have your app published on the AppStore.
You actually don't need to have the app published in the App Store for this to work — clicking a link, closing the App Store, and then installing an app build through Xcode (or any other beta distribution platform like TestFlight or Fabric) has exactly the same effect.
According to the Firebase docs, the method that is called for the first install is openURL (no, this makes no sense to me either). The continueUserActivity method is for Universal Links, and is only used if the app is already installed when a link is opened.
I am not aware of any way to detect when the app is opening for the first time after install from a 'deferred' link, but you could simply route directly to the shared content (skipping the intro) whenever a deep link is present. If a deep link is NOT present, show the regular intro.
Alternative Option
You could check out Branch.io (full disclosure: I'm on the Branch team). Amongst other things, Branch is a great, free drop-in replacement for Firebase Dynamic Links with a ton of additional functionality. Here is an example of all the parameters Branch returns immediately in didFinishLaunchingWithOptions:
{
"branch_view_enabled" = 0;
"browser_fingerprint_id" = "<null>";
data = "{
\"+is_first_session\":false,
\"+clicked_branch_link\":true,
\"+match_guaranteed\":true,
\"$canonical_identifier\":\"room/OrangeOak\",
\"$exp_date\":0,
\"$identity_id\":\"308073965526600507\",
\"$og_title\":\"Orange Oak\",
\"$one_time_use\":false,
\"$publicly_indexable\":1,
\"room_name\":\"Orange Oak\", // this is a custom param, of which you may have an unlimited number
\"~channel\":\"pasteboard\",
\"~creation_source\":3,
\"~feature\":\"sharing\",
\"~id\":\"319180030632948530\",
\"+click_timestamp\":1477336707,
\"~referring_link\":\"https://branchmaps.app.link/qTLPNAJ0Jx\"
}";
"device_fingerprint_id" = 308073965409112574;
"identity_id" = 308073965526600507;
link = "https://branchmaps.app.link/?%24identity_id=308073965526600507";
"session_id" = 319180164046538734;
}
You can read more about these parameters on the Branch documentation here.
Hmm... as far as I'm aware, there's not really anything you can catch in the application:(_:didFinishLaunchingWithOptions) phase that would let you know the app was being opened by a dynamic link. You're going to have to wait until the continueUserActivity call, as you mentioned.
That said, FIRDynamicLinks.dynamicLinks()?.handleUniversalLink returns a boolean value nearly instantly, so you should be able to take advantage of that to short-circuit your into animation without it being a bad user experience. The callback itself might not happen until several milliseconds later, depending on if it's a shortened dynamic link (which requires a network call) or an expanded one (which doesn't).

iOS: Detect whether my SDK is installed on another apps on the device

I am developing a location based Q&A SDK for mobile devices.
When a question is asked about a specific location, the server side targets the most relevant user and sends the question to that user. If the user fails to answer, the question is sent to the second best user, and so on.
The problem is that my SDK might be installed on more than one application on the device, meaning that the user can get a question more than once.
Is there a way to detect whether my SDK is installed on more than one app? I thought that sending the UDID to the server might work, but iOS UDIDs differ between applications.
You can use UIPasteboard to share data between applications on the device.
The UIPasteboard class enables an app to share data within the app and with another app. To share data with any other app, you can use system-wide pasteboards; to share data with another app that has the same team ID as your app, you can use app-specific pasteboards.
In your SDK, do something like this:
#interface SDKDetector : NSObject
#end
#implementation SDKDetector
+ (void)load
{
int numberOfApps = (int)[self numberOfAppsInDeviceUsingSDK];
NSLog(#"Number of apps using sdk:%d", numberOfApps);
}
+ (NSInteger)numberOfAppsInDeviceUsingSDK
{
static NSString *pasteboardType = #"mySDKPasteboardUniqueKey";
NSData *value = [[UIPasteboard generalPasteboard] valueForPasteboardType:pasteboardType];
NSMutableArray *storedData = [[NSKeyedUnarchiver unarchiveObjectWithData:value] mutableCopy];
if (!storedData) {
storedData = [NSMutableArray new];
}
NSString *bundleId = [[NSBundle mainBundle] bundleIdentifier];
if (![storedData containsObject:bundleId]) {
[storedData addObject:[[NSBundle mainBundle] bundleIdentifier]];
}
value = [NSKeyedArchiver archivedDataWithRootObject:storedData];
[[UIPasteboard generalPasteboard] setData:value forPasteboardType:pasteboardType];
return [storedData count];
}
#end
If you only want to provide an SDK, it is not possible. Apple has added security steps to prevent that for user privacy. Keychain sharing will not work, because apps must share the same bundle seed ID (see here for more info).
If you want to provide an app along with your SDK, then you could do something like Facebook does, where app sends a "helo" message, Facebook asks user and finally Facebook sends "ehlo" message.
Your App -> "I would like to use the SDK; please give me token" -> SDK Controller App -> (Remember which apps have requested use) -> "OK, you can use the SDK; here is a token: #123" -> Your App
The SDK controller app can now send the server the list of apps.
I think you can group the apps on the same device by IP address as they will use the same address to connect to your server.
So the IP address will represent the device and the API key will represent the app that uses the SDK.
Can you try using
advertisingIdentifier
Not sure whether it serves your purpose. It is explained in here ASIdentifierManager class reference : Apple doc
I think its possible using keychain, you can have an unique keychain key in which you can save anything you want, and can be accessed by other apps if available. So for your SDK, lets say if there is one app, it will register some value in keychain with a unique key which is private to your SDK only if the key doesn't exist, and if it exist you get to know, since you can save any value in keychain, you can try multiple options and combinations which suits you.
You can use KeychainItemWrapper for the implementations.
Elaboration
Lets say we have an method.
[MySDK register];
Which can be used anywhere, say in AppDelegate. The register method will generate a token for the app, for the device, which we will save in the keychain using an unique key we have defined in the SDK, say in com.mysdk.key. And while saving in keychain the SDK can actually do a registration.
We consider the above method is implemented in multiple apps.
Now we have scenario.
User installs an App-A which uses the SDK, the register method will call and create a token and will save in keychain for the first time.
Now user installs another App-B which also uses the SDK, the same register method will call, but now it will check for the key com.mysdk.key in keychain, if exist it will just update the count for the token, which meant for the device.
Note
Keychain not meant to save only unique identifier, you can save other informations too.
Update
Check demo projects https://db.tt/7xpKrgMp
The wrapper I have used in the projects is same as SDK in your case which is same in both the projects.
Cheers.

xcode apigee logInUserWithFacebook extra parameter?

I'm using Apigee for my iphone/ipad app.
Like many apps today, mine requires a login via Facebook and Apigee has a function specifically for this in the iOs framework, here's how it's called:
[ApigeeDataClient logInUserWithFacebook:[FBSession activeSession].accessTokenData.accessToken];
As far as my code goes, everything works well up until the above line. I'm receiving the following error.
Response: {"error":"invalid_request","error_description":"missing access token"}
However check out how the function is making the call (from the logs):
Synch outgoing call: 'https://api.usergrid.com/sgfishing/deepseafishing/auth/facebook?ql=fb_access_token=CAADrhKxrQp4BANfZCMuZBdOwUL9nc0H4VzZC1EXVLjABRbcrucTlUgwlKczFinl51GIWyBM5nlZBX1RF84azFAEOfChqN7vgSmvqgwybV8iPU2xjncZB9T5YTdY0pesJkHsSlvOafMhQ6MfIa6qdZCbTYBZCFB2oIPgEnro4runJKcqCy68wZCFQwyIzACVThAC3IEjZADs36hToQxhYZBzAWVhbKlcqJQsroZD'
I would like to bring your attention to this ...facebook?<b>ql=</b>fb_access_token=CAADrh....
I'm not sure why ql= is there, I've checked the definition of logInUserWithFacebook and ql= is nowhere to be found.
Any help would be greatly appreciated.
This is a bug in our iOS SDK. It has been fixed in version 2.0.9 of our SDK (released yesterday).
?ql= is typically used for query language statements see if there is any such code around in your program
This just a tip...may help

Where exactly should I put the call to [FBSettings publishInstall:appId]

I'm looking at integrating support for tracking Facebook's new mobile app ads.
I've read the tutorial here:
https://developers.facebook.com/docs/tutorials/mobile-app-ads/
It says:
Include the following code to be executed when your app opens for the first time by user
[FBSettings publishInstall:appId];
So the first question is - where do I put this so that it only invokes the call if the install was driven from Facebook? I don't want FB to get credit for someone who found my app themselves on the app store.
Do I need to manually track whether or not I've called the publishInstall before for this specific user? (The preamble sentence implies this - but the SDK documentation for publishInstall implies otherwise).
And even more confusing is that the SDK FBSettings reference includes shouldAutoPublishInstall which defaults to YES. This would suggest that I don't need to do anything other than have the SDK integrated. So why does the tutorial not mention this as an option?
I assume that the appId is the associated Facebook appId (as opposed to the App Store App ID). This is also not clear from the documentation.
I browsed the sources of facebook iOS SDK, and it seems that guide is wrong.
You are right, that autoPublishInstall is set to YES by default, which means we don't need to invoke [FBSettings publishInstall:appId]; manually. AppId is indeed the facebook app id.
When you invoke openActiveSessionWith.... method, it initializes FBSession with
initWithAppID:permissions:defaultAudience:urlSchemeSuffix:tokenCacheStrategy: which contains in the end [FBSettings autoPublishInstall:self.appID];
+ (void)autoPublishInstall:(NSString *)appID {
if ([FBSettings shouldAutoPublishInstall]) {
dispatch_once(&g_publishInstallOnceToken, ^{
// dispatch_once is great, but not re-entrant. Inside publishInstall we use FBRequest, which will
// cause this function to get invoked a second time. By scheduling the work, we can sidestep the problem.
[[FBSettings class] performSelector:#selector(publishInstall:) withObject:appID afterDelay:FBPublishDelay];
});
}
}
So technically it should report the install out of the box (if I'm not missing something). I'm going to play with it a little more today to see if it works as expected and update answer with results.
Just put it at -[application:didFinishLaunchingWithOptions].
Not all of the apps want to integrate the Facebook login. They only want the feature "mobile app install ads". For these kind of app, they should invoke +[FBSettings publishInstall:appId] manually. On the other hand, if your app has already integrated facebook login, you can assume that the FB sdk has published the installation.
If we just have to put
[FBSettings publishInstall:appId];
manually in
-[application:didFinishLaunchingWithOptions]
how will I identify which install happened from facebook? I don't want FB to get credit for someone who found my app themselves on the app store.
put the code in Appdelegate DidbecomeActive method
- (void)applicationDidBecomeActive:(UIApplication *)application
hope this help :)

Using AddThis SDK for iOS, Need to change "via #AddThis" for default Twitter text

First ever SO question, woohoo.
I've integrated the AddThis SDK into an iOS app. I've set it up to share the App Store link to the App via various channels. All works well except the default text in the Twitter message appends "via #AddThis" to the end of the tweet. Although this text is editable by the user, I'd like to change it to "via #MyTwitterHandle".
AddThis' documentation says you can use:
[AddThisSDK setTwitterViaText:#"MyTwitterHandle"];
Except this doesn't work. It raises a warning that AddThisSDK may not respond to the method call and the app crashes when it reaches this line.
Examining the AddThisSDK header file, there's no such method outlined. I've searched their forums and FAQ etc to no avail. And I did run into other instances where the method names in their documentation were different from those in the SDK. If that's the case here I haven't found the correct name. Does anyone know how to do this?
Thanks in advance.
Do you have the latest version of the addthis iOS sdk? http://www.addthis.com/help/ios-quickstart
Please set setTwitterViaText before the sharing code.
This will work:
[AddThisSDK setTwitterViaText:#"My App"];
[AddThisSDK shareURL:myUrl withService:#"twitter" title:#"myTitle" description:myDescription];
This will not work:
[AddThisSDK shareURL:myUrl withService:#"twitter" title:#"myTitle" description:myDescription];
[AddThisSDK setTwitterViaText:#"My App"];

Resources