iOS13 application openUrl? (Obj-C) - objective-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];
}

Related

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
}
}

NSURLSessionDataTask in appdelegate

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
}

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];
}

popup facebook feed dialog (for wall posting) in ios xcode 4.3 (storyboard)

I am making an app in which I need to integrate a facebook share (feed) dialog. I read all stuff on https://developers.facebook.com/docs/mobile/ios/build/ , and I was able to load facebook share (feed) dialog when the app finished launching. But my problem is that I am using xcode 4.3 i.e storyboard and I want to load facebook feed dialog on button action.
I made another view controller and paste all the stuff of AppDelegate's function
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
in its -(void) viewDidload and was able to load "login page" and then my "facebook app" page.
After that when I allow permission to my facebook app it does not show "feed dialog"
Here is my viewController.h file
#import "FBConnect.h"
#interface ViewController : UIViewController<FBSessionDelegate,FBDialogDelegate>
{
Facebook *facebook;
}
#property (nonatomic, retain) Facebook *facebook;
#end
-Here is my ViewController.m file
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize facebook=_facebook;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
facebook = [[Facebook alloc] initWithAppId:#"284727404938450" andDelegate:self];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
if (![facebook isSessionValid]) {
[facebook authorize:nil];
}
}
- (void)fbDidLogin {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
[facebook dialog:#"feed" andDelegate:self];
}
but here are two methods which are used in AppDelegate file
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [ facebook] handleOpenURL:url];
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [ facebook] handleOpenURL:url];
}
I know that in xib these methods should be:
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [[_ViewController facebook] handleOpenURL:url];
}
// For iOS 4.2+ support
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [[_ViewController facebook] handleOpenURL:url];
}
These method are responsible for popping up a feed dialog for the current "facebook" instance (Facebook *facebook).
My problem is that in the storyboard we dont have a "window" and view controller intances so my guess is that these two methods are not being called for my current viewController's "facebook" instance. How can I call these two functions for my "facebook" instance, where my viewController is not an instance of AppDelegate file?
Please help me out.
You can pass a reference of your viewcontroller in the app delegate's _viewcontroller before using Facebook (or calling these delegate functions).
Your view controller's viewdidload() will look like as below:
-(void)viewDidLoad{
[[UIApplication sharedApplication] delegate]._viewComtroller = self; // pass reference to the appdalegate
// Other code (or call the facebook function here)
}
It will be working
Be careful because you are defining an ivar named "facebook" and a property named "facebook" that creates another ivar named "_facebook". Then on your code your are working with the ivar "facebook", so when you call [_ViewController facebook] you are accessing the property (ivar _facebook) and not the ivar "facebook" that you initialized.
I don't think this is the answer you were looking for but it seemed important to point out.
Good luck!
Looks like you're missing a few Facebook related delegates and that you're not putting them all in your main app delegate as the online tutorial instructs:
See https://developers.facebook.com/docs/mobile/ios/build/
Well one solution could implement the Facebook delegate methods in the AppDelegate, then in your viewController in the viewDidLoad method, or the method you prefer, use
AppDelegate *appDelegate= (AppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate.facebook authorize:permissions];
where permissions is an array with the permissions you need. That should work and the methods
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [ facebook] handleOpenURL:url];
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [ facebook] handleOpenURL:url];
}
are performed.