Search code examples
codenameone

Codenameone: AppArg is null on ios when app open via applink


When opening my ios app via an applink, as specified by associated domains feature, the AppArg is null.

The consecutive call of start() method, as described in this issue, does not occur. In my case, start() is called only once, with a null AppArg, and that's it.

The first thing a do, in the start() method, is call

Display.getInstance().getProperty("AppArg",null);

This works fine when opening the app via a custom scheme, but not when opening via an applink.

Note: I use the ios.glAppDelegateBody and ios.afterFinishLaunching build hints to handle app open via push notification. I figured this might interfere with AppArg reading so I removed those temporarily and tried again, but to no avail.

Currently, the only solution I see is to write some native code and try to get the opening url this way, but I'd very much like for the AppArg to work as it states.

I've tested on iphone 6s with ios 15.1.

Update 3:

This problem occurs due to the call of the facebook sdk in the didFinishLaunchingWithOptions which causes the method to return NO, and that prevents continueUserActivity to execute and retrieve the launch url. The offending code is this:

return [[FBSDKApplicationDelegate sharedInstance] application:application
                                didFinishLaunchingWithOptions:launchOptions];

This code gets executed if the facebook.appIdbuild hint is present in the codenameone settings.

After I removed it, things started working.

However, you won't be able to do this if you actually use facebook connect.

Update 2

I added the following snippet to the apple-app-site-association file hosted on my domain, as per the documentation here.

"activitycontinuation": {

"apps": [ <id of my app> ]

}

It didn't work still.

The same documentation also states the an associated domain entitlement like this: activitycontinuation:example.com should be added. So I added it to the ios.associatedDomains build hint, along with the applinks, looking like this:

ios.associatedDomains=applinks:mydomain.com,activitycontinuation:mydomain.com

It still didn't work. The build suceeded, but I'm not sure that codename one is actually doing something with activitycontinuation service.

So, the problem is still not solved!

Update:

So, the flow start,stop,start only happens when the app is in background and gets opened via an applink click, and both times start is called with the AppArg populated with the applink. All well in this case.

However, if the app is closed, and opepend via applink click, start is called only once and the AppArg is null. Problem!

The method shouldApplicationHandleURL is never called. I implemented it on the main app class, returning true.

I have also tried adding native code to try to get the applink, for the case when the app was previously closed. I tried to add the code below to the glAppDelegateBody build hint, but the build failed complaining that the continueUserActivity is duplicate. The code used was something like this:

- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
  restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler {

    NSURL *url = userActivity.webpageURL;
    // Handle url
  
  return YES;
}

Currently, I'm running out of ideas. So, please, help. Thank you.


Solution

  • By adding the following code to the ios.afterFinishLaunching build hint, the AppArg will be populated at start with the app launchUrl (if any), regardless of the fact that facebook sdk is used or not:

    NSDictionary *activityDictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey];
    if (activityDictionary) {
        NSUserActivity *userActivity = [activityDictionary valueForKey:@"UIApplicationLaunchOptionsUserActivityKey"];
        if (userActivity != nil) {
               if ([NSUserActivityTypeBrowsingWeb isEqualToString:userActivity.activityType] && userActivity.webpageURL != nil) {
            JAVA_OBJECT launchUrlStr = fromNSString(CN1_THREAD_GET_STATE_PASS_ARG [userActivity.webpageURL absoluteString]);
            JAVA_OBJECT appArgKey = fromNSString(CN1_THREAD_GET_STATE_PASS_ARG @"AppArg");
            JAVA_OBJECT displayInstObj = com_codename1_ui_Display_getInstance__(CN1_THREAD_GET_STATE_PASS_SINGLE_ARG);
            
            com_codename1_ui_Display_setProperty___java_lang_String_java_lang_String(CN1_THREAD_GET_STATE_PASS_ARG displayInstObj, appArgKey, launchUrlStr);
            }
        }
    }