5

I created a keyboard extension with a scan button to open a barcode scanner in my containing app. When the scan is completed, it should navigate back to the initial app and the barcode data should be set as text to the textfield that initiated the keyboard and we clicked on scan button.

enter image description here

There is this app Scandit Wedge that does it the same way. But I couldn't find a way to achieve the same. Please refer GIF below.

https://s3.amazonaws.com/id123-dev-ios/scandit.gif

Any help would be much appreciated.

Sameer Bhide
  • 171
  • 7
  • I'm facing at the moment exactly the same problem. Did you find any solution? – mahega Feb 28 '18 at 20:24
  • @mh-itc Using private APIs for doing this for now. – Sameer Bhide Apr 25 '18 at 02:48
  • @SameerBhide Which type of private API did you use for this? Can you provide a reference? – user3524337 Mar 14 '19 at 08:31
  • @SameerBhide can you please answer your question? Which private APIs did you use? The accepted answer is not working for me :/ – ndreisg Aug 22 '19 at 09:13
  • 1
    @ndreisg I implemented the above using Google custom keyboard like implementation. See this link: https://stackoverflow.com/questions/42516357/how-does-googles-custom-ios-keyboard-gboard-programmatically-dismiss-the-fron – Sameer Bhide Aug 23 '19 at 10:39

1 Answers1

1

There is no public API to switch to the previous app, here is the answer: https://stackoverflow.com/a/13447282/1433612

But you could do that if you know the app's bundle id and url scheme. You can find unofficial lists on internet. Assuming that you are able to recognize the source app you can do something like this in your AppDelegate:

public func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
    guard let applicationBundleId = options[UIApplicationOpenURLOptionsKey.sourceApplication] as? String else {
        return true
    }

    // Save your source application
    sourceApplicationBundleId = applicationBundleId
    return true
}

var sourceApplicationBundleId: String?

// Attempt to open application from which your app was opened
func openApplication() {
    guard let applicationBundleId = sourceApplicationBundleId, let url = url(for: applicationBundleId) else {
        return
    }
    UIApplication.shared.open(url, options: [:], completionHandler: nil)
}

func url(for bundleId: String) -> URL? {
    guard let scheme = knownUrlSchemes[bundleId] else {
        return nil
    }

    return URL(string: scheme)!
}

// A list of known url schemes
var knownUrlSchemes: Dictionary<String, String> = {
    return ["com.google.Maps": "comgooglemaps://",
            "com.facebook.Facebook": "fb://"]
}()
Au Ris
  • 4,541
  • 2
  • 26
  • 53
  • Not sure why this answer is accepted. The question was about a keyboard extension calling the containing app. So the `sourceApplicationBundleId` will always be the bundle id of the keyboard extension and it can not be opened via URLScheme. – ndreisg Aug 22 '19 at 09:22