카카오 공유하기 - iOS 하이브리드 앱(웹뷰) 카카오톡이 없는 경우 마켓으로 이동하지 않는 현상에 대해 문의사항이 있습니다

카카오 공유하기 - iOS 하이브리드 앱(웹뷰) 카카오톡이 없는 경우 마켓으로 이동하지 않는 현상에 대해 문의사항이 있습니다.

1. 개발환경

2. 상황

iOS 하이브리드 앱(웹뷰)에서 카카오톡이 설치되어 있지 않은 경우 다운로드 버튼을 눌러도 App Store로 이동하지 않습니다.

kakao3

  • 참고 사항

    • 아이폰 - 카카오톡 설치 O

      • iOS 하이브리드 앱 - 카카오 공유하기 기능 동작 O
      • iOS 모바일 브라우저(safari, chrome) - 카카오 공유하기 기능 동작 O
    • 아이폰 - 카카오톡 설치 X

      • iOS 하이브리드 앱 - App Store 이동 X
      • iOS 모바일 브라우저(safari, chrome) - App Store 이동 O
  • 다음 설정을 추가했습니다.

  • URL 스킴
    https://talk-apps.kakao.com/scheme/kakaolink 에서 다운로드 버튼을 클릭했을때 다음과 같은 URL 스킴이 내려오는 것 같은데요 어떻게 핸들링 해야하는지 잘 모르겠습니다.

itms-appss://apps.apple.com/kr/app/kakaotog-kakaotalk/id362057947

3. 로그

다운로드 버튼을 눌렀을때 xcode에서는 다음과 같은 로그가 발생합니다.

2022-09-25 13:39:00.625336+0900 KakaoShare[1325:102023] [ProcessSwapping] 0x1050025e0 - [pageProxyID=6, webPageID=22, PID=1331, navigationID=3] ProvisionalPageProxy::didFailProvisionalLoadForFrame: frameID=3
2022-09-25 13:39:00.625532+0900 KakaoShare[1325:102023] [Process] 0x109030018 - [pageProxyID=6, webPageID=16, PID=1330] WebPageProxy::didFailProvisionalLoadForFrame: frameID=3, isMainFrame=1, domain=WebKitErrorDomain, code=102, isMainFrame=1
2022-09-25 13:39:00.630855+0900 KakaoShare[1325:102046] [assertion] Error acquiring assertion: <Error Domain=RBSServiceErrorDomain Code=1 "target is not running or doesn't have entitlement com.apple.runningboard.assertions.webkit" UserInfo={NSLocalizedFailureReason=target is not running or doesn't have entitlement com.apple.runningboard.assertions.webkit}>
2022-09-25 13:39:00.630961+0900 KakaoShare[1325:102046] [ProcessSuspension] 0x10401c8a0 - ProcessAssertion::acquireSync Failed to acquire RBS assertion 'ConnectionTerminationWatchdog' for process with PID=1331, error: Error Domain=RBSServiceErrorDomain Code=1 "target is not running or doesn't have entitlement com.apple.runningboard.assertions.webkit" UserInfo={NSLocalizedFailureReason=target is not running or doesn't have entitlement com.apple.runningboard.assertions.webkit}
2022-09-25 13:39:00.632425+0900 KakaoShare[1325:102172] [assertion] Error acquiring assertion: <Error Domain=RBSAssertionErrorDomain Code=2 "Specified target process does not exist" UserInfo={NSLocalizedFailureReason=Specified target process does not exist}>
2022-09-25 13:39:00.632532+0900 KakaoShare[1325:102172] [ProcessSuspension] 0x10401c900 - ProcessAssertion::acquireSync Failed to acquire RBS assertion 'WebProcess Background Assertion' for process with PID=1331, error: Error Domain=RBSAssertionErrorDomain Code=2 "Specified target process does not exist" UserInfo={NSLocalizedFailureReason=Specified target process does not exist}

4. 질문 정리

swfit, iOS 개발환경에 미숙해서, 제가 설정을 잘못한것 같은데요 혹시, 코드 보시고

iOS 하이브리드 앱(웹뷰)에서 카카오톡이 설치되어 있지 않은 경우 다운로드를 눌렀을때 카카오톡 App Store로 이동하려면 어떻게 해야하는지 알려주실 수 있으신가요?

제가 swift 개발자가 아니고, 마음이 급하다 보니 코드를 잘못 작성한것 같습니다.

ios swift(story board) 코드 저장소: GitHub - skyepodium/kakaoshare-storyboard

카카오톡이 없는 경우에 App Store로 이동함을 확인했습니다.

다음 코드에서 tms-appss 을 추가했고, URL 스킴으로 호출했을때 App Store로 이동함을 확인했습니다.

// 카카오 SDK가 호출하는 커스텀 URL 스킴인 경우 open(_ url:) 메서드를 호출합니다.
if let url = navigationAction.request.url , ["kakaolink", "itms-appss"].contains(url.scheme) {

전체코드

import UIKit
import WebKit
@objcMembers class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {

    // 웹뷰 목록 관리
    var webViews = [WKWebView]()
    var webView: WKWebView!
    override func viewDidLoad() {
        super.viewDidLoad()
        
        NotificationCenter.default.addObserver(self, selector: #selector(didRecieveTestNotification(_:)), name: NSNotification.Name("TestNotification"), object: nil)

        let screenSize: CGRect = UIScreen.main.bounds
        webView = createWebView(frame: screenSize, configuration: WKWebViewConfiguration())
        // Do any additional setup after loading the view.
        let myRequest = URLRequest(url: Var.myURL!)
        webView.load(myRequest)
    }
    
    override func loadView() {
        let webConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.uiDelegate = self
        view = webView
        
    }
    
    @objc func didRecieveTestNotification(_ notification: Notification) {
            print("Test Notification")
        let myRequest = URLRequest(url: Var.myURL!)
        webView.load(myRequest)
    }
    
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void ) {
        print("!!! webView method - string", navigationAction.request.url?.absoluteString ?? "")

        // 카카오 SDK가 호출하는 커스텀 URL 스킴인 경우 open(_ url:) 메서드를 호출합니다.
        if let url = navigationAction.request.url , ["kakaolink", "itms-appss"].contains(url.scheme) {

            // 카카오톡 실행 가능 여부 확인 후 실행
            if UIApplication.shared.canOpenURL(url) {
                UIApplication.shared.open(url, options: [:], completionHandler: nil)
            }

            decisionHandler(.cancel); return
        }

        // 서비스에 필요한 나머지 로직을 구현합니다.
        decisionHandler(.allow)
    }
    
    /// ---------- 팝업 열기 ----------
    /// - 카카오 JavaScript SDK의 로그인 기능은 popup을 이용합니다.
    /// - window.open() 호출 시 별도 팝업 webview가 생성되어야 합니다.
    ///
    func webView(_ webView: WKWebView,
                 createWebViewWith configuration: WKWebViewConfiguration,
                 for navigationAction: WKNavigationAction,
                 windowFeatures: WKWindowFeatures
    ) -> WKWebView? {
        guard let frame = self.webViews.last?.frame else {
            return nil
        }
        return createWebView(frame: frame, configuration: configuration) // 웹뷰를 생성하여 리턴하면 현재 웹뷰와 parent 관계가 형성됩니다.
    }

    /// ---------- 팝업 닫기 ----------
    /// - window.close()가 호출되면 앞에서 생성한 팝업 webview를 닫아야 합니다.
    ///
    func webViewDidClose(_ webView: WKWebView) {
        destroyCurrentWebView()
    }

    // 웹뷰 생성 메소드 예제
    func createWebView(frame: CGRect, configuration: WKWebViewConfiguration) -> WKWebView {
        let webView = WKWebView(frame: frame, configuration: configuration)
        webView.uiDelegate = self // set delegate
        webView.navigationDelegate = self
        self.view.addSubview(webView) // 화면에 추가
        self.webViews.append(webView) // 웹뷰 목록에 추가
        return webView // 그 외 서비스 환경에 최적화된 뷰 설정하기
    }

    // 웹뷰 삭제 메소드 예제
    func destroyCurrentWebView() {
        self.webViews.popLast()?.removeFromSuperview() // 웹뷰 목록과 화면에서 제거하기
    }
}

//Var.swift
import Foundation
class Var{
    public static var myURL = URL(string:"http://kakao-share.s3-website.ap-northeast-2.amazonaws.com/")

//    public static var myURL = URL(string:"https://developers.kakao.com/tool/demo/message/kakaolink?method=button")
}