Get reference code with deeplink url through app store - ios

I have some functionality in my app. If user clicks on referral link from outside of the app(from messages,whatsapp etc), it will navigating to app and I am making register url with reference code. After that I am navigating to register screen and loading that register url in web view and it displaying referral code in required field.(this is all happening if our app installed in iPhone device)
But what I need is when app is not installed and we click on referral link-
If app is not installed then it should redirect to appstore and once the app is installed it should redirect to register screen with referral code in it.
-(void)handelReferral:(NSString *)strReferral{
if ([[SuperClass sharedSingletonSuperClass] checkifStringNotNull:strReferral]) {
NSString *strReferralCode;
if ([strReferral rangeOfString:#"ref/"].location != NSNotFound) {
NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:[NSURL URLWithString:strReferral]
resolvingAgainstBaseURL:NO];
NSArray *queryItems = urlComponents.queryItems;
if (queryItems.count > 0) {
NSString *queryValue = [self valueForKey:#"al" fromQueryItems:queryItems];
strReferralCode = [queryValue lastPathComponent];
} else {
strReferralCode = strReferral.lastPathComponent;
}
NSString *strRegisterUrl = [ConfigurationManager shared].data.strRegisterUrl;
NSString *finalRefUrl = [NSString stringWithFormat:#"%#?utm_campaign=app_refferal_ref/ref/%#&utm_medium=app&utm_source=app_refferal",strRegisterUrl,strReferralCode];
if ([self.ReferralDelegate respondsToSelector:#selector(userClickedOnReferralDelegate)]) {
[self.ReferralDelegate userClickedOnReferralDelegate];
} else {
if ([[SuperClass sharedSingletonSuperClass]isPhoneNumberIsAvailable] == false) {
NSLog(#"finalRefUrl=====%#",finalRefUrl);
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"isComingFromRef"];
[[NSUserDefaults standardUserDefaults] setValue:finalRefUrl forKey:#"finalRefUrl"];
[[NSUserDefaults standardUserDefaults] synchronize];
[ServiceGeneralNotifications sharedSingleton].isUserTryingToLogin = YES;
[[SuperClass sharedSingletonSuperClass] pushToLoginScreen];
}
}
}
}
}
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
[self callServiceToPostCampaignDataWithURL:userActivity.webpageURL];
if ([[SuperClass sharedSingletonSuperClass]checkifStringNotNull:[userActivity.webpageURL absoluteString]]) {
[self handelReferral:[userActivity.webpageURL absoluteString]];
}

Use Firebase Dynamic links
With Dynamic Links, your users get the best available experience for the platform they open your link on. If a user opens a Dynamic Link on iOS or Android, they can be taken directly to the linked content in your native app. If a user opens the same Dynamic Link in a desktop browser, they can be taken to the equivalent content on your website.
In addition, Dynamic Links work across app installs: if a user opens a Dynamic Link on iOS or Android and doesn't have your app installed, the user can be prompted to install it; then, after installation, your app starts and can access the link.

Related

Find out the first time opening the app when updated to newer version

The app's current behavior is, the user logged in once will not be logged out unless the user explicitly clicks on the logout.
I keep the user logged in, even if the user closes the app and opens it again.
When newer version of my app is released in appstore, I want to find out whether the user updated my app and opened it for the first time.
At that point I want to make them login again.
Is there a way to find out at the first time launch of the app after its been updated to latest version?
Create some kind of version #'s scheme. Note: You can enable Xcode to create backups and versions whenever you make substantial changes to the code.
There are a number of ways one could create a version constant, save it, and read it back.
When you update an app from the store, there is app data that persists from the previous installed version of the app, which you can read back to determine the version and, then update that persistent data to be ready for the next update cycle.
This answer was a very popular solution in another similar question.
Or, try something like #JitendraGandhi's ObjC answer below, or if you use Swift, try something like my port of #JitendraGandhi's ObjC example to Swift:
func hasAppBeenUpdatedSinceLastRun() -> Bool {
var bundleInfo = Bundle.main.infoDictionary!
if let currentVersion = bundleInfo["CFBundleShortVersionString"] as? String {
let userDefaults = UserDefaults.standard
if userDefaults.string(forKey: "currentVersion") == (currentVersion) {
return false
}
userDefaults.set(currentVersion, forKey: "currentVersion")
userDefaults.synchronize()
return true
}
return false;
}
You can save your currentversion to NSUserDefaults and use this method to check your version every time the app awakes:
#pragma mark - NSBundle Strings
- (NSString *)currentVersion
{
return [[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleShortVersionString"];
}
if the currentversion is different from stored... its time to show the login!
Hope it helps you.
Use NSUserDefaults to store the CFBundleVersion. Then check against it every time the application is launched.
// Check if new version
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *currentAppVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"];
if ([defaults objectForKey:#"savedAppVersionKey"] != nil) {
// Key exists
NSString *savedAppVersion = [defaults objectForKey:#"savedAppVersionKey"];
if ([currentAppVersion isEqualToString:savedAppVersion]) {
// Still running the same app version
// Do nothing
NSLog(#"App version: SAME");
}
else {
// The app version changed from the last launch
// Do something here
NSLog(#"App version: UPDATED");
}
}
// Set the key & synchronize
[defaults setObject:currentAppVersion forKey:#"savedAppVersionKey"];
If you want simple and easy solution, Use this function :
-(BOOL)isAppUpdated
{
NSDictionary *bundleInfo = [[NSBundle mainBundle] infoDictionary];
NSString *currentVersion = [bundleInfo objectForKey:#"CFBundleShortVersionString"];
if ([[[NSUserDefaults standardUserDefaults] objectForKey:#"currentVersion"] isEqualToString:currentVersion])
{
return NO ;
}
else
{
[[NSUserDefaults standardUserDefaults] setObject:currentVersion forKey:#"currentVersion"];
return YES ;
}
}
Following code will return NO / YES. You can call this method multiple times to know whether app was updated before this launch or not.
- (BOOL)launchedFirstTimeAfterUpdate
{
static NSString *lastVersion;
NSString *currentVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleShortVersionString"];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSString *versionKeyName = #"lastLaunchedVersion";
lastVersion = [[NSUserDefaults standardUserDefaults] stringForKey:versionKeyName];
[[NSUserDefaults standardUserDefaults] setObject:currentVersion forKey:versionKeyName];
[[NSUserDefaults standardUserDefaults] synchronize];
});
if (!lastVersion.length)
{
// No last version means, launched first time
return NO;
}
if ([lastVersion compare:currentVersion options:NSNumericSearch] == NSOrderedAscending)
{
// Last version is less than current version
return YES;
}
return NO;
}

Prevent app from using Facebook single sign on?

I have taken over an app that uses Facebook as a login. I want to force the user to be taken to a UIWebView via a URL. Also when a user signs into our app with some other account, say twitter, but then wants to share via Facebook, I want the user to be taken to Facebook login via UIWebView URL not via single sign on.
The apps works as I want it (see above) if the person has not setup single sign on via iPhone > Setting > Facebook. But if the user has setup Single Sign On via iPHone > Settings > Facebook then the app breaks. We are getting an error that the app needs to be officially put in the Facebook app process here https://developers.facebook.com/apps.
We don't want to jump through Facebooks hoops (images, bundle id's etc,...) so we would rather force the user to login via the Facebook webpage via a webview url.
Can I prevent my app from trying to use the Single Sign On on the iphone?
This did it.
[[FBSession activeSession] openWithBehavior:FBSessionLoginBehaviorWithFallbackToWebView completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
switch (status) {
case FBSessionStateOpen:
// call the legacy session delegate
//Now the session is open do corresponding UI changes
self.facebookButton.selected = YES;
self.shareButton.enabled = YES;
self.shareUIButton.enabled = self.shareButton.enabled;
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:kShouldPostToFacebookKey];
break;
case FBSessionStateClosedLoginFailed:
{ // prefer to keep decls near to their use
// unpack the error code and reason in order to compute cancel bool
NSString *errorCode = [[error userInfo] objectForKey:FBErrorLoginFailedOriginalErrorCode];
NSString *errorReason = [[error userInfo] objectForKey:FBErrorLoginFailedReason];
BOOL userDidCancel = !errorCode && (!errorReason ||
[errorReason isEqualToString:FBErrorLoginFailedReasonInlineCancelledValue]);
// call the legacy session delegate if needed
//[[delegate facebook] fbDialogNotLogin:userDidCancel];
}
break;
default:
break; // so we do nothing in response to those state transitions
}
}];

Handle http url with my app (if installed)

I would like to handle a url like: http://www.something.com/product/3/ in this way:
If you have the App installed => handle it with the App.
Else => handle it with safari.
Is it this possible?
The idea is I can send that url via email and if the receiver has the app installed, then the app raises up and do something, and if not installed just open it via safari.
I know about the custom schemes, which work fine in the app but they obviously don't work in safari because they are not http protocol.
1) Create a custom URL scheme in your app. Follow the link if you don't know how to create a custom URL scheme: http://www.idev101.com/code/Objective-C/custom_url_schemes.html
2) Then add following script to the URLs that you want your app to open.
<script language="javascript" type="text/javascript">
var iOS = (navigator.userAgent.match(/(iPad|iPhone|iPod)/g) ? true : false);
var appUrlScheme = "myappscheme://" + document.URL;
if (iOS) {
window.open(appUrlScheme, "_self");
}
</script>
The script is self explanatory, if its an iOS device then it simply tries to open current url with your custom url scheme i.e. myappscheme://whateverurl.com'. If you app is installed on the device then iOS is going to launch your app and pass this URL tohandleOpenURLfunction, otherwise mobile safari will silently ignorewindow.open` call and your webpage will load as normal:
3) Implement handleOpenURL callback method in your AppDelegate to handle the URL:
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
NSLog(#"url: %#", url);
NSLog(#"query string: %#", [url query]);
NSLog(#"host: %#", [url host]);
NSLog(#"url path: %#", [url path]);
//REDIRECT USER TO A VIEW CONTROLLER
return YES;
}
Yes you can do by using URL Scheme,
First create your own custom url scheme in Info.plist file
Add a new row by going to the menu and clicking Editor > Add Item. Set up a URL Types item by adding a new item. Expand the URL Types key, expand Item 0, and add a new item, “URL schemes”. Fill in “readtext” for Item 0 of “URL schemes” and your company identifier for the “URL Identifier”.
Then parse your url for different url for same url scheme to open your app with different screens.. Here i have shown only alert, use to open your specific page as per your link.. And if the app is not installed then it will open in web browser.
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
// Display text
UIAlertView *alertView;
NSString *text = [[url host] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
alertView = [[UIAlertView alloc] initWithTitle:#"Text" message:text delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
[alertView release];
return YES;
}
application:handleOpenURL: (used for earlier iOS 4.1)
application:openURL:sourceApplication:annotation: (used for later iOS 4.1).
No that is not possible.
However you can include in the mail both links:
To open it in safari as normal website: http://www.somewebsite.com
To open the app using custom urls: yourapp://

Dropbox Error Opens Another App on device, not on simulator

I have three apps that upload files to Dropbox. Same code for all three. They all share the same folder so I've used same secret key etc
Heres where it gets weird
1. All was fine for few months
2. Now on apps 2 and 3 when the user tries to log in it opens the first app?
3. Logging out and in, no help, just says Theres a an error connecting to Dropbox and to try later
What ive tried
Creating seprate secret keys etc for all three apps rathe rthan sharing the same, still get the same behaviour?
Some research on this suggested that Dropbox has changed the way it links to users accounts through applications and remins linked even if you delete the app? Has anyone else got any experience with this?
Appdelegate
NSString* appKey = #"00000000000";
NSString* appSecret = #"0000000000";
NSString *root = kDBRootAppFolder;
DBSession* session =
[[DBSession alloc] initWithAppKey:appKey appSecret:appSecret root:root];
session.delegate = self; // DBSessionDelegate methods allow you to handle re-authenticating
[DBSession setSharedSession:session];
[DBRequest setNetworkRequestDelegate:self];
Button Handler in viewController
LogCmd();
self.publishButtonPressed = YES;
if (![[DBSession sharedSession] isLinked]) {
[self loginLogoutButtonPressed:nil];
} else {
DBRestClient *restClient = [[DBRestClient alloc] initWithSession:[DBSession sharedSession]];
restClient.delegate = self;
NSError *error = nil;
NSString *filePath = [ICUtils pathForDocument:self.fileName];
[self.pdfData writeToFile:filePath options:0 error:&error];
if (nil == error) {
[restClient uploadFile:self.fileName
toPath:#"/"
withParentRev:nil
fromPath:filePath];
} else {
[ICUtils raiseAlertWithTitle:#"An error occurred" message:[error localizedDescription]];
}
}
}
Note works ok on the simulator, problem is only present on device
That is because you are using the same key for multiple applications. The Dropbox app is communicating with your app through a custom URL scheme - to launch your app (because there is no other way to launch apps programmatically on iOS).
In other words, the Dropbox app tells the system to open "db-yoursecretkey://somemessage" which opens the registered app for that custom URL scheme. Unfortunately, all of your apps use the same custom scheme as they are all using the same key, so the system just picks one: most likely the first one.
However, you can grant your apps access to all folders in dropbox, thus effectively sharing folders. So it's not really necessary to have all three apps using the same key.

FaceBook API, login in-app

I followed this guide and I've created my app successfully with Facebook integration.
What's the problem?
When the user has to do the login, the app quits in the browser (or in Facebook app, if is installed)
How do I keep authentication entirely in-app?
The point of the oAuth login is that it doesn't happen within your application. It uses fast-app switching to perform the authentication in a trusted environment (either Safari or the Facebook application).
However, you can modify Facebook.m to do the authentication within your application, but you user's credentials will not be remembered. You can see that if your iOS device doesn't support multi-tasking, there is a backup login dialog.
Excerpt from Facebook.m (around line 160):
if ([device respondsToSelector:#selector(isMultitaskingSupported)] && [device isMultitaskingSupported]) {
if (tryFBAppAuth) {
NSString *scheme = kFBAppAuthURLScheme;
if (_localAppId) {
scheme = [scheme stringByAppendingString:#"2"];
}
NSString *urlPrefix = [NSString stringWithFormat:#"%#://%#", scheme, kFBAppAuthURLPath];
NSString *fbAppUrl = [FBRequest serializeURL:urlPrefix params:params];
didOpenOtherApp = [[UIApplication sharedApplication] openURL:[NSURL URLWithString:fbAppUrl]];
}
if (trySafariAuth && !didOpenOtherApp) {
NSString *nextUrl = [self getOwnBaseUrl];
[params setValue:nextUrl forKey:#"redirect_uri"];
NSString *fbAppUrl = [FBRequest serializeURL:loginDialogURL params:params];
didOpenOtherApp = [[UIApplication sharedApplication] openURL:[NSURL URLWithString:fbAppUrl]];
}
}
// If single sign-on failed, open an inline login dialog. This will require the user to
// enter his or her credentials
if (!didOpenOtherApp) {
[_loginDialog release];
_loginDialog = [[FBLoginDialog alloc] initWithURL:loginDialogURL
loginParams:params
delegate:self];
[_loginDialog show];
}
If you remove the first conditional and it's containing code and set didOpenOtherApp to NO, you can get the behavior you are looking for.
To disable this behavior modify Facebook.m line 275 and set both options to NO.
- (void)authorize:(NSArray *)permissions {
self.permissions = permissions;
// with both options NO, authorization always happens in-app
[self authorizeWithFBAppAuth:NO safariAuth:NO];
}

Resources