kakao_flutter_sdk, app_links 카카오톡 로그인과 딥링크 충돌?

flunge·2022년 1월 7일
0

Flutter

목록 보기
8/13

개요

카카오톡 로그인을 사용하던 중 딥링크 기능을 추가하면서 겪은 문제이다.
안드로이드는 문제없이 작동하는데 iOS에서 카카오톡 간편로그인이 되지 않는 문제이다.

문제

await AccessTokenStore.instance.toStore(await AuthApi.instance
  .issueAccessToken(await isKakaoTalkInstalled()
    ? await AuthCodeClient.instance.requestWithTalk()
    : await AuthCodeClient.instance.request()));

문제의 코드이다.
kakao_flutter_sdk의 카톡 로그인 예제 그자체이다. 3번째 줄이 카톡이 깔려있을 때 호출되는 메소드인데 아무런 값을 반환하지 않고 에러를 던지지도 않는다.

AuthCodeClient.instance.requestWithTalk().then((value) => print(value));

이런식으로 로그를 찍어도 봤는데 찍히지도 않는다. 그런데 app_links패키지를 빼고 캐시까지 전부 지우고 다시 실행하면 로그인이 잘된다.

해결

import Flutter
import UIKit

public class SwiftAppLinksPlugin: NSObject, FlutterPlugin {
  fileprivate var methodChannel: FlutterMethodChannel
  fileprivate var initialLink: String?
  fileprivate var latestLink: String?

  public static func register(with registrar: FlutterPluginRegistrar) {
    let methodChannel = FlutterMethodChannel(name: "com.llfbandit.app_links/messages", binaryMessenger: registrar.messenger())

    let instance = SwiftAppLinksPlugin(methodChannel: methodChannel)

    registrar.addMethodCallDelegate(instance, channel: methodChannel)
    registrar.addApplicationDelegate(instance)
  }

  init(methodChannel: FlutterMethodChannel) {
    self.methodChannel = methodChannel
  }

  public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
    switch call.method {
      case "getInitialAppLink":
        result(initialLink)
        break
      case "getLatestAppLink":
        result(latestLink)
        break      
      default:
        result(FlutterMethodNotImplemented)
        break
    }
  }

  // Universal Links
  public func application(
    _ application: UIApplication,
    continue userActivity: NSUserActivity,
    restorationHandler: @escaping ([Any]) -> Void) -> Bool {

    switch userActivity.activityType {
      case NSUserActivityTypeBrowsingWeb:
        guard let url = userActivity.webpageURL else {
          return false
        }
        handleLink(url: url)
        return true
      default: return false
    }
  }

  // Custom URL schemes
  public func application(
    _ application: UIApplication,
    open url: URL,
    options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    
    handleLink(url: url)
    return true
  }

  fileprivate func handleLink(url: URL) -> Void {
    debugPrint("iOS handleLink: \(url.absoluteString)")

    if (initialLink == nil) {
      initialLink = url.absoluteString
    }

    latestLink = url.absoluteString

    methodChannel.invokeMethod("onAppLink", arguments: latestLink)
  }
}

app_links 패키지의 ios 구현 부분이다. 중간의 주석을 보면 universal link와 custom url scheme을 구현한 메소드 이름이 application이다.
앱을 실행할 때 호출되는 메소드가 application이다. 앱이 universal link이나 custom url scheme을 통해 실행될 때 맞는 메소드를 찾아 호출하고 handleLink를 호출하고 메소드 채널을 통해 값을 flutter단으로 전달한다.

Future<void> initDeepLinkSet() async{
  final applink = AppLinks(
    onAppLink: (uri){
      print('🥶🥶🥶🥶🥶🥶🥶🥶🥶🥶🥶 $uri');
    }
  );

  final lastAppLink = await applink.getLatestAppLink();
  if(lastAppLink != null)
    print('🦧🦧🦧🦧🦧🦧🦧🦧🦧🦧🦧🦧🦧🦧🦧 $lastAppLink');
    print('🦞🦞🦞🦞🦞 ${lastAppLink.queryParameters['code']}');
}

딥링크 처리를 위한 메소드이다. 이 메소드를 로그인 페이지가 아닌 그 후에 보여지는 메인 페이지에서 호출해서 왜 안된건지 몰랐던 것이다.
로그인 페이지에서 로그인 버튼을 눌러서 문제의 requestWithTalk()가 호출되면 카톡이 실행되고 카톡에서 로그인을 위한 값을 받아서 우리의 프로젝트를 실행 하는데 이 때 Custom URL schemes방식으로 실행하게 된다. 이 때 우리의 app_links가 카톡에서 받아온 링크를 채갔던 것이다.
그래서 requestWithTalk()메소드는 호출되었으나 코드를 반환하지 않고 에러를 던지지도 않았던것이다.

kakaoa66c327dd11217556028ced9d45cfbe5://oauth?code=카카오톡인증코드
카카오톡 간편로그인을 하면 이렇게 생긴 값을 반환하는데 마지막에 카카오톡 인증코드를 따로 어떻게 처리하면 된다.

마치며

카톡 로그인 뿐만 아닌 다른 소셜 로그인도 이러한 문제가 발생할 수 있을 것이다.
굿굿굿

0개의 댓글