Download

Custom URL redirect from SFSafariViewController to UE4 app? ...FOnOpenURL delegate?

Hi folks,

I am trying to do a redirect from an HTML/JS page that is loaded inside a SFSafariViewController back to my UE4 app using a custom uri scheme. I am using this How to use SafariViewcontroller as Callback on some URL in Objective C - Mobikul more or less. The redirect is supposed to close the SFSafariViewController w/ additional information passed back in query params.

I can not get the redirect to work and/or SFSafariViewController does not close. I have validated that the uri scheme is defined correctly (in project settings additional plist data) by using Safari dev tools on my computer to invoke Javascript in the SFSafariViewController in my deployed app on the iOS device. Trying to redirect to a url w/ *window.location.href = ‘testing://?success=1’ *, which is different than defined uri scheme, gives a “Safari cannot open the page because the address is invalid”, which is expected, and when redirecting to the url w/ window.location.href = ‘freedomofkeima://?success=1’, I do not see this error, but I also do not see the SFSafariViewController close.

Does anyone know how to handle custom uri schemes? I am unsure if the delegate FOnOpenURL in UnrealEngine/IOSAppDelegate.h at master · raysjoshua/UnrealEngine · GitHub would be available to me or can be used (new to c++), and I am also not sure if the code from the example link in my app is modified correctly.

My additional plist data (my bundle id is com.mypackage.mygame):



<key>LSApplicationQueriesSchemes</key><array><string>freedomofkeima</string></array><key>CFBundleURLTypes</key><array><dict><key>CFBundleURLSchemes</key><array><string>freedomofkeima</string></array><key>CFBundleURLName</key><string>com.mypackage.mygame</string></dict></array><key>UIRequiresPersistentWiFi</key><true/>

My blueprint, which is run on game start:

BrowserBlueprint.cpp:



#include "BrowserBlueprint.h"
#include "Runtime/Engine/Classes/Kismet/KismetSystemLibrary.h"
#include "Engine/GameEngine.h"
#include "BrowserSettings.h"
#include "EngineUtils.h"
#include "Engine/World.h"

#if PLATFORM_IOS
#include "MyBrowserController.h"
#endif

UBrowserBlueprint::UBrowserBlueprint(const FObjectInitializer &ObjectInitializer) : Super(ObjectInitializer) {}

void UBrowserBlueprint::loadBrowserWithUrl() {
#if PLATFORM_IOS
  [MyBrowserController loadBrowserWithUrl];
#endif
}


MyBrowserController.h:


#pragmaonce

#if PLATFORM_IOS
#import <Foundation/Foundation.h>
#import <SafariServices/SafariServices.h>

@interface MyBrowserController : UIViewController <SFSafariViewControllerDelegate>
+ (void)loadBrowserWithUrl;

@end
#endif

MyBrowserController.cpp



#include "MyBrowserController.h"
#include "BrowserSettings.h"

#if PLATFORM_IOS
#include "IOSAppDelegate.h"
#import <Foundation/Foundation.h>
#import <SafariServices/SafariServices.h>
#endif

#if PLATFORM_IOS
@interface MyBrowserController()
@end

@implementation MyBrowserController

+ (MyBrowserController*)GetDelegate {
  static MyBrowserController *Singleton = [MyBrowserController alloc] init];

  return Singleton;
}

+ (void)loadBrowserWithUrl {
  [MyBrowserController GetDelegate] performSelectorOnMainThread:@selector(loadBrowserURLInIOSThread) withObject:nil waitUntilDone:NO];
}

- (void)loadBrowserURLInIOSThread {
  const UBrowserSettings *browserSettings = GetDefault<UBrowserSettings>();

  NSString *oUrlString = browserSettings->url.GetNSString();
  NSString *urlString = [NSString alloc] initWithString:UrlString];
  NSURL *url = [NSURL URLWithString:urlString];

  SFSafariViewController *safariVC = [SFSafariViewController alloc] initWithURL:url entersReaderIfAvailable:NO];
  safariVC.delegate = self;

  UINavigationController *navigationController = [UINavigationController alloc]initWithRootViewController:safariVC];
  [navigationController setNavigationBarHidden:YES animated:NO];

  [IOSAppDelegate GetDelegate].IOSController presentViewController:navigationController animated:YES completion:nil];
}

#pragma mark - SFSafariViewController delegate methods

-(void)safariViewController:SFSafariViewController *)controller didCompleteInitialLoad:BOOL)didLoadSuccessfully {
  //Load finished
}

-(void)safariViewControllerDidFinish:SFSafariViewController *)controller {
  //Done button pressed
}

- (BOOL)application:UIApplication *)app openURL:NSURL *)url options:NSDictionary<NSString *, id> *)options {
  NSString *sourceApplication = [options objectForKey:@"UIApplicationOpenURLOptionsSourceApplicationKey"];
  NSString *urlScheme = [url scheme];
  NSString *urlQuery = [url query];

  if ([urlScheme isEqualToString:@"freedomofkeima"] && [sourceApplication isEqualToString:@"com.apple.SafariViewService"]) {

    //TODO check for success query param

    NSLog(@"Value: %@", urlQuery);
    NSDictionary *data = [NSDictionary dictionaryWithObject:urlQuery forKey:@"key"];

    [NSNotificationCenter defaultCenter] postNotificationName:@"SafariCallback" object:self userInfo:data];

    return YES;
  }

  return NO;
}

- (void)safariCallback:NSNotification *)notification {
  [IOSAppDelegate GetDelegate].IOSController dismissViewControllerAnimated:NO completion:nil];
}

@end
#endif