NSURLSessionDataTask in appdelegate - objective-c

I would call a NSURLSessionDataTask in appDelegate when the app is open from mail, so in this function
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
I tried but doesn't work, why??
I need to get a query from this function
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
NSURLComponents *components = [[NSURLComponents alloc] init];
components.query = [url query];
BOOL confirmRegistration = NO;
NSString *userToken;
for (NSURLQueryItem *queryItem in components.queryItems) {
if ([queryItem.name isEqualToString:#"userToken"])
{
userToken = queryItem.value;
}
else if ([queryItem.name isEqualToString:#"registrationType"])
{
if ([queryItem.value isEqualToString:#"confirmRegistration"])
{
confirmRegistration = YES;
}
}
}
//la app รจ stata aperta con la mail di conferma registrazione
if (confirmRegistration)
{
NSDictionary* userInfo = #{#"userToken": userToken};
[[NSNotificationCenter defaultCenter] postNotificationName:#"confirmRegistration" object:nil userInfo:userInfo];
}
return YES;
}
Thank you

When Application is opened from anywhere, the application:didFinishLaunchingWithOptions: is called.
There you check the launchingOptions to see what triggered the opening for application.
For instance, if application is opened using push notifications. You do something like below.
if let userInfo = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as? [NSObject : AnyObject] {
self.application(application, didReceiveRemoteNotification: userInfo)
}
You can check the keys which you get when you open the application from Mail.
UPDATE
There are keys like UIApplicationLaunchOptionsSourceApplicationKey and UIApplicationLaunchOptionsURLKey which you can print or compare to what triggered the application launch and then start your work.
When you open your application from Mail then print the following and use it to compare and start your work.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
print(launchOptions?[UIApplicationLaunchOptionsSourceApplicationKey])
print(launchOptions?[UIApplicationLaunchOptionsURLKey])
return true
}

Related

iOS13 application openUrl? (Obj-C)

How do you import files to your app on ios13?
Previously I could download a txt file in Safari and chose Copy to (app) and I would catch this in the app delegate open Url delegate. Doesn't work anymore.
The Copy To is still there in Safari, but it just dismissed Safari and nothing happens.
-- Edit:
Sorry, I was a bit unclear.
Previously, when downloading a file through another app (like Safari), the user could select to open this file in my app by tapping "Copy To (app)".
I would then catch this copy request through the appdelegate:
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
[...]
}
This delegate is not called in iOS13, only iOS12 and below.
I have tried finding a way to catch the "Copy to" request from other apps to no avail. There seems to be a new way of handling these things through a SceneDelegate?
In projects having SceneDelegate.swift file, should implement scene:openURLContext method.
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
print(#function)
print(URLContexts)
}
Output:
scene(_:openURLContexts:)
[
<UIOpenURLContext: 0x282fbca20;
URL: file:///private/var/mobile/Containers/Data/Application/A644621B-BD6C-443B-A9D1-A212EA59EE2E/Documents/Inbox/file.pdf;
options: <UISceneOpenURLOptions: 0x2823112c0;
sourceApp: (null);
annotation: (null);
openInPlace: NO>>
]
Reference: Migration from AppDelegate to SceneDelegate
Version for Objective C.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSURL *url = [launchOptions objectForKey:UIApplicationLaunchOptionsURLKey];
[[CommonController sharedInstance] handleExternalUrl: url];
return YES;
}
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
{
NSLog(#"application openURL: %#", url);
return [[CommonController sharedInstance] handleExternalUrl: url];
}
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions API_AVAILABLE(ios(13.0)){
NSSet *c = connectionOptions.URLContexts;
if(c && [c count] > 0)
{
NSURL *url = ((UIOpenURLContext*)[[c allObjects] firstObject]).URL;
[[CommonController sharedInstance] handleExternalUrl: url];
}
}
- (void)scene:(UIScene *)scene openURLContexts:(nonnull NSSet<UIOpenURLContext *> *)URLContexts
API_AVAILABLE(ios(13.0)){
NSURL *url = [[URLContexts allObjects] firstObject].URL;
[[CommonController sharedInstance] handleExternalUrl: url];
}

App State: undefined and endless waiting tests

Somehow when running our e2e detox tests we always wait for some synchronization to finish (If we disable it and wait manually it works).
I tried removing all animation but somehow there is still something running.
The log shows the following:
detox info Sync App State: undefined
detox info Sync Dispatch Queue: com.apple.main-thread
detox verb ws send: {"type":"currentStatus","params":{},"messageId":21}
detox verb ws onMessage: {"type":"currentStatusResult","messageId":21,"params":{"state":"busy","resources":[{"name":"App State","info":{"elements":["<UIViewController: 0x7fdc1351bf50>"],"appState":"Waiting for window's root view controller's view to appear."}},{"name":"Dispatch Queue","info":{"queue":"<OS_dispatch_queue_main: com.apple.main-thread[0x112beadc0] = { xref = -2147483648, ref = -2147483648, sref = 1, target = com.apple.root.default-qos.overcommit[0x112bec300], width = 0x1, state = 0x001ffe9e00000400, dirty, max qos 6, in-flight = 0, thread = 0x403 }>","prettyPrint":"com.apple.main-thread"}}],"messageId":21}}
detox verb ws
detox info Sync App State: undefined
detox info Sync Dispatch Queue: com.apple.main-thread
detox verb ws send: {"type":"currentStatus","params":{},"messageId":22}
detox verb ws onMessage: {"type":"currentStatusResult","messageId":22,"params":{"state":"busy","resources":[{"name":"App State","info":{"elements":["<UIViewController: 0x7fdc1351bf50>"],"appState":"Waiting for window's root view controller's view to appear."}},{"name":"Dispatch Queue","info":{"queue":"<OS_dispatch_queue_main: com.apple.main-thread[0x112beadc0] = { xref = -2147483648, ref = -2147483648, sref = 1, target = com.apple.root.default-qos.overcommit[0x112bec300], width = 0x1, state = 0x001ffe9e00000400, dirty, max qos 6, in-flight = 0, thread = 0x403 }>","prettyPrint":"com.apple.main-thread"}}],"messageId":22}}
Any help where this issue is coming from highly appreciated
[Update 2018/04/18]:
Just to clarify:
The render function of my app component is like that:
render() {
const {
isOnboardingVisible,
} = this.props;
if (isOnboardingVisible) {
return (
<View>
<Onboarding onPressButton={this.props.onOnboardingViewed} />
</View>
);
}
return <LoginScreen statusBarHidden {!!this.props.notification} />;
};
The test navigates from the onboarding to the login screen by changing the isOnboardingVisible prop and gets stuck in the login screen waiting for an element to be visible (it's clearly visible on the screen).
If I remove the onboarding screen and directly start the test on the login screen the test works.
Here is our AppDelegate.m like requested in the comments:
#import "AppDelegate.h"
#import <CodePush/CodePush.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <BugsnagReactNative/BugsnagReactNative.h>
#import <Fabric/Fabric.h>
#import <Crashlytics/Crashlytics.h>
#import <react-native-branch/RNBranch.h>
#import "OneSignalConfig.h"
#import <React/RCTPushNotificationManager.h>
#import <FBSDKCoreKit/FBSDKCoreKit.h>
#implementation AppDelegate
#synthesize oneSignal = _oneSignal;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"GoogleService-Info" ofType:#"plist"];
NSDictionary *plistDict = [NSDictionary dictionaryWithContentsOfFile:filePath];
[GIDSignIn sharedInstance].clientID = [plistDict objectForKey:#"CLIENT_ID"];
#ifdef FREEWORK_DEBUG
[RNBranch useTestInstance];
#endif
#ifdef FREEWORK_EDGE
[RNBranch useTestInstance];
#endif
#ifdef FREEWORK_STAGING
[RNBranch useTestInstance];
#endif
[RNBranch initSessionWithLaunchOptions:launchOptions isReferrable:YES];
NSURL *jsCodeLocation;
#ifdef DEBUG
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:#"index" fallbackResource:nil];
#else
jsCodeLocation = [CodePush bundleURL];
#endif
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:#"Freework"
initialProperties:nil
launchOptions:launchOptions];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
OneSignalConfig* config = [[OneSignalConfig alloc] init];
self.oneSignal = [[RCTOneSignal alloc] initWithLaunchOptions:launchOptions
appId: [config getOneSignalAppId]
settings:#{kOSSettingsKeyAutoPrompt: #false}];
[[FBSDKApplicationDelegate sharedInstance] application:application
didFinishLaunchingWithOptions:launchOptions];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
[BugsnagReactNative start];
[Fabric with:#[[Crashlytics class]]];
return YES;
}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
BOOL handled = [[GIDSignIn sharedInstance] handleURL:url
sourceApplication:options[UIApplicationOpenURLOptionsSourceApplicationKey]
annotation:options[UIApplicationOpenURLOptionsAnnotationKey]];
return handled;
}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
if (![RNBranch.branch application:application openURL:url sourceApplication:sourceApplication annotation:annotation]) {
if ([LinkedinSwiftHelper shouldHandleUrl:url]) {
return [LinkedinSwiftHelper application:application openURL:url sourceApplication:sourceApplication annotation:annotation];
} else if ([[GIDSignIn sharedInstance] handleURL:url
sourceApplication:sourceApplication
annotation:annotation]) {
return YES;
} else if( [url.absoluteString rangeOfString: #"fb" ].location != NSNotFound ) {
return [[FBSDKApplicationDelegate sharedInstance] application:application openURL:url sourceApplication:sourceApplication annotation:annotation];
} else {
}
}
return YES;
}
// Respond to Universal Links
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler {
return [RNBranch continueUserActivity:userActivity];
} // Required to register for notifications
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
[RCTPushNotificationManager didRegisterUserNotificationSettings:notificationSettings];
}
// Required for the register event.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
[RCTPushNotificationManager didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
// Required for the notification event. You must call the completion handler after handling the remote notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
[RCTPushNotificationManager didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
// Required for the registrationError event.
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
[RCTPushNotificationManager didFailToRegisterForRemoteNotificationsWithError:error];
}
// Required for the localNotification event.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
[RCTPushNotificationManager didReceiveLocalNotification:notification];
}
#end

How to detect Remote notification in didFinishLaunchingWithOption application method in objective c?

when app in not in background mode ,inactive mode and app is completely closed. than how to detect is their any notification using application's delegate "didFinishLaunchingWithOption" method. i have searched a lot about it but not get anything. please help .
Thanks
Below methods is used for notifiaction
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (notification)
{
}
}
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
NSString *token = [[[[deviceToken description]
stringByReplacingOccurrencesOfString:#"<"withString:#""]
stringByReplacingOccurrencesOfString:#">" withString:#""]
stringByReplacingOccurrencesOfString: #" " withString: #""];
NSLog(#"Token:%#",token);
}
//app is forground this method will access
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
}
//need to on teh background fetch option in info plist
//app is background state this below mthod will call while notification receives
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
NSLog(#"Background mode working%#",userInfo);
if([userInfo[#"aps"][#"content-available"] intValue]== 1) //it's the silent notification when recive preferences and text messages
{
}
}
//handling interactive notification
- (void)application:(UIApplication *)application handleActionWithIdentifier:(nullable NSString *)identifier forLocalNotification:(nonnull UILocalNotification *)notification completionHandler:(nonnull void (^)())completionHandler {
}
You can do this in the didFinishLaunchingWithOption method
let launchedFromRemoteNotification = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] != nil
You can get Notification in the didFinishLaunchingWithOption in this way :
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSDictionary *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (notification) {
NSLog(#"app recieved notification from remote%#",notification);
}else{
NSLog(#"app did not recieve notification");
}
}
Try this it may help you.
If the App was terminated and is starting again, you can detect the Remote Notification only if the App is being launched because the user tapped on the remote notification in the notifications tray.
You can detect it in the didFinishLaunchingWithOptions method
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSDictionary *notificationDict = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (notificationDict) {
//Your App received a remote notification
}else{
//Your App did not receive a remote notification
}
}

application:openURL not triggered

I have a problem implementing - (BOOL)application:openURL and using UIDocumentInteractionController for exporting PDF file from an application to another.
(1) Target application does nothing but just display URL of the imported PDF file (in a label).
here is the code in AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[ViewController alloc] initWithText:#"No file is imported."];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication: (NSString *)sourceApplication annotation:(id)annotation
{
if (url != nil)
{
[self.viewController handleOpenURL:url];
return YES;
}
else
{
[self.viewController handleOpenURL:[NSURL fileURLWithPath:#"AppDelegate.h"]];
return NO;
}
}
Method "handleOpenURL" just take the url and put in a label in the view controller and show an alert:
- (void)handleOpenURL:(NSURL *)fileURL
{
_text = [fileURL absoluteString];
self.lblText.text = _text;
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:#"Alert" message:_text delegate:self cancelButtonTitle:nil otherButtonTitles:nil, nil];
[alert show];
}
(2) In source application, I simply use UIDocumentInteractionController to list "Open In" options (my target application appears well in the list)
Here is the code:
_docInteractionController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:attachmentFile]];
_docInteractionController.delegate = self;
_docInteractionController.UTI = [_extensionUTIs objectForKey:[[attachmentFile pathExtension] lowercaseString]];
BOOL opened = [_docInteractionController presentOpenInMenuFromRect:CGRectZero inView:self.view animated:NO];
(3) Problem:
- When I select the target application (from "Open In" list), simulator switches from source application to target application okay, but looks like application:openURL method is not invoked because the label keeps as initial (No file is imported.) and no alert view shows up.
Please advise me what could be wrong here ?
Thanks in advance.
I used these two methods for facebook integration to handle openURL...its working fine.
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [ [[HIFacebookConnect sharedGameObject] facebook] handleOpenURL:url];
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [[[HIFacebookConnect sharedGameObject] facebook] handleOpenURL:url];
}
Just want to mark my question as answered because I have already found the glitch.
Update: It was my fault when not including full file path when initiating UIDocumentInteractionController object.

Facebook iOS SDK 3.0 - session not open

I am using the latest Facebook iOS SDK 3.0
I need a help in in the login process:
First I declare this property in AppDelegate.h:
#property (nonatomic, strong) FBSession *session;
and in ViewController class I get this to use it in the code as this:
AppDelegate *delegate = [[UIApplication sharedApplication]delegate];
[delegate.session someproperty];
I also have this method in ViewController that get called from viewDidLoad:
-(void)login
{
AppDelegate *delegate = [[UIApplication sharedApplication]delegate];
[delegate.session accessToken];
NSLog(#"%d",delegate.session.isOpen);
if (!delegate.session.isOpen)
{
delegate.session = [[FBSession alloc] init];
if (delegate.session.state == FBSessionStateCreatedTokenLoaded)
{
[delegate.session openWithCompletionHandler:^(FBSession *session,
FBSessionState status,
NSError *error)
{
NSLog(#"%d", delegate.session.isOpen); // First Line //////////////////
}];
}
NSLog(#"%#", delegate.session.description); // Second Line //////////////////
}
}
After the facebook app get authorized the firs NSLog print zero, and the second NSLog indicate that the session state is FBSessionStateCreated not FBSessionStateOpen?
this is the output for the second NSLog:
2012-08-16 18:37:24.327 Facebook3[2418:f803] <FBSession: 0x6890ff0, state: FBSessionStateCreated, loginHandler: 0x0, appID: 193716877424306, urlSchemeSuffix: , tokenCachingStrategy:<FBSessionTokenCachingStrategy: 0x6890f20>, expirationDate: (null), refreshDate: (null), attemptedRefreshDate: 0001-12-30 00:00:00 +0000, permissions:()>
What I am missing here.
Note : in the app setting at https://developers.facebook.com I configure the app as this:
1- Configured for iOS SSO: Enabled
2- iOS Native Deep Linking: Enabled
3- iOS Bundle ID : com.mycompany.appname
i used this framework for my project. it works properly.
this is my related code
-(IBAction)logIn:(id)sender;
{
AppDelegate *appdelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
if (!FBSession.activeSession.isOpen) {
[appdelegate sessionOpener];
}
else {
[self loginHelp];
}
and my sessionOpener function is;
-(void) sessionOpener
{
[FBSession sessionOpenWithPermissions:nil
completionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
// session might now be open.
if (!error) {
[self.viewController loginHelp];
}
}];
NSLog(#"%d", FBSession.activeSession.isOpen);
NSLog(#"%#", FBSession.activeSession.description );
}
it works for me. may be helpful to you.
and my console print is:
1
2012-08-16 22:24:55.899 TaraftarlikOyunu[838:c07] <FBSession: 0xd2512c0, state: FBSessionStateOpen, loginHandler: 0xd250240, appID: 433294056715040, urlSchemeSuffix: , tokenCachingStrategy:<FBSessionTokenCachingStrategy: 0xd24fda0>, expirationDate: 2012-10-15 19:02:34 +0000, refreshDate: 2012-08-16 19:05:03 +0000, attemptedRefreshDate: 0001-12-30 00:00:00 +0000, permissions:(
)>
I had the same problem as you and I had mixed between using FBSession and instance of FBSession when calling handleOpenURL. I changed from
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
[FBSession.activeSession facebookSession handleOpenURL:url];
}
to this
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
[session facebookSession handleOpenURL:url];
}