llfbandit / app_links

Android App Links, Deep Links, iOs Universal Links and Custom URL schemes handler for Flutter.
https://pub.dev/packages/app_links
Apache License 2.0
176 stars 68 forks source link

app_links in carplay supported app #81

Closed glettl closed 6 months ago

glettl commented 7 months ago

Hello,

I'm currently facing the following issue with app_links in combination with flutter_carplay.

According to the flutter_carplay documentation I need to change the AppDelegate.swift to


import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
 ) -> Bool {
  //     GeneratedPluginRegistrant.register(with: self)
  //     return super.application(application, didFinishLaunchingWithOptions: launchOptions)
      return true;
  }
}

and create a SceneDelegate.swift with the following content:

@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = scene as? UIWindowScene else { return }

        window = UIWindow(windowScene: windowScene)

        let flutterEngine = FlutterEngine(name: "SceneDelegateEngine")
        flutterEngine.run()
        GeneratedPluginRegistrant.register(with: flutterEngine)
        let controller = FlutterViewController.init(engine: flutterEngine, nibName: nil, bundle: nil)
        window?.rootViewController = controller
        window?.makeKeyAndVisible()
    }
}

and add the new Scene and the Carplay Scene in the Info.plist

<dict>
        <key>UISceneConfigurations</key>
        <dict>
            <key>CPTemplateApplicationSceneSessionRoleApplication</key>
            <array>
                <dict>
                    <key>UISceneClassName</key>
                    <string>CPTemplateApplicationScene</string>
                    <key>UISceneConfigurationName</key>
                    <string>MyApp-Car</string>
                    <key>UISceneDelegateClassName</key>
                    <string>flutter_carplay.FlutterCarPlaySceneDelegate</string>
                </dict>
            </array>
            <key>UIWindowSceneSessionRoleApplication</key>
            <array>
                <dict>
                    <key>UISceneClassName</key>
                    <string>UIWindowScene</string>
                    <key>UISceneConfigurationName</key>
                    <string>Phone</string>
                    <key>UISceneDelegateClassName</key>
                    <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
                </dict>
            </array>
        </dict>
    </dict>

Unfortunately, now the app is opened using a custom url scheme, but getInitialAppLink is null and uriLinkStream is not fired. I assume it's because return super.application(application, didFinishLaunchingWithOptions: launchOptions) isn't called any longer.

I tried removing the carplay related code and everything works fine.

Could you please help me to fix this problem?

llfbandit commented 7 months ago

You're right, since application(didFinishLaunchingWithOptions:) isn't called anymore, the delegate workflow is broken. Can't you both call it and return true?

Here's a similar issue: https://github.com/llfbandit/app_links/issues/70#issuecomment-1732155678

I'll try to improve this in later versions for Apple platforms.

glettl commented 7 months ago

I tried the this solution, but unfortunately I get this error on startup image

llfbandit commented 7 months ago

This should be somehow available in app_links 3.5.0-beta.1. Please have a look to the README file. Feedback appreciated!

glettl commented 7 months ago

It works fine, if the app already runs in background. However, it does not work if the app is closed and opened via a deeplink.

App Delegate:

import UIKit
import Flutter
import app_links

let flutterEngine = FlutterEngine(name: "SharedEngine", project: nil, allowHeadlessExecution: true)

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
 ) -> Bool {
     flutterEngine.run()

     GeneratedPluginRegistrant.register(with: flutterEngine)
     super.application(application, didFinishLaunchingWithOptions: launchOptions)

     if let url = AppLinks.shared.getLink(launchOptions: launchOptions) {
           // We have a link, propagate it to your Flutter app
           AppLinks.shared.handleLink(url: url)
     }

     return false;
  }
}

Scene Delegate

import app_links

@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

            guard let windowScene = scene as? UIWindowScene else { return }

            window = UIWindow(windowScene: windowScene)
            let controller = FlutterViewController.init(engine: flutterEngine, nibName: nil, bundle: nil)
            window?.rootViewController = controller
            window?.makeKeyAndVisible()
        }

    func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
          for context in URLContexts {
            AppLinks.shared.handleLink(url: context.url)
          }
        }

    func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
      if let url = userActivity.webpageURL {
        AppLinks.shared.handleLink(url: url)
      }
    }
}

I had to change to flutter engine to be headless in order to run carplay without opening the app. dont know if thats the problem here.

Really appreciate your support. Thank you.

bverhagen commented 6 months ago

The same issue impacts the macOS platform. Retesting with version 3.5.0-beta.1 as suggested fixes the problem.

glettl commented 6 months ago

Unfortunately, the version 3.5.0-beta.1 does not build.

Failed to build iOS app Error (Xcode): .dart_tool/flutter_build/dart_plugin_registrant.dart:112:9: Error: Undefined name 'AppLinksPluginLinux'.

Also did a flutter pub clean, and pod update.

Thats why I used 3.5.0-beta.2, which builds but it does not work if the app is closed and opened via a deeplink. The app opens but the deeplink is not recognized.

llfbandit commented 6 months ago

Released in v3.5.0. Update your specifics to catch links.