본문 바로가기

Issues/Mobile(Web&App)

[APP & javascript] ios, Android 앱 마켓 이동하기(+ ios 앱스토어 이동 오류)

이슈

flow
(safari) 앱이 있음
> ~앱으로 이동하시겠습니까? confirm 이 뜸
> 2.5초 전 누르면 즉시 앱 실행 (앱으로 이동했기때문에 더이상 js가 타지않아 마켓 실행되지않음)
> 2.5초 후 누르면 > 앱 실행 > 마켓으로 이동
(confirm이 뜬 상태라 js는 이미 실행되었어야하는데 막힌상태. confirm닫자마자 js 차례로 실행됨. 앱이 있는데도 마켓으로 실행이 됨)
아래 소스는 기존 소스로 javascript 앱 마켓이동, 앱 다운로드 유도 등으로 인터넷에 치면 자주 보이는 소스이다.

ios 같은 경우에는 앱이 있는지 없는지에 대한 callback이 없으므로 유저의 앱의 다운로드 유무에 대해 알수가 없다. 따라서 앱을 실행하고 일정시간 이후에 그 페이지에 계속 남아있다면 앱이 없는것으로 간주하고 앱 스토어 주소로 이동하게 되어있다.

그런데 브라우저 별로 앱 주소가 들어오면 실행하는 방식이 다른데, safari에서는 "~~을 여시겠습니까?" 라는 confirm이 뜬다. 여기서 이슈는 앱이 있는 경우에 바로 확인버튼을 누르지 않고 setTimeout을 설정해놓은 일정시간이후에 confirm의 확인버튼을 누르게 되면 앱이 열린 다음 마켓으로 강제로 이동하게 되는 것이 이슈이다.
const openAppStore = () => {
    // 앱 다운로드 유도 배너
    const userAgent = navigator.userAgent;
    const visiteTm = (new Date()).getTime();

    if (userAgent.match(".*Android.*")) {
        if (userAgent.match(/Chrome/)) {
            setTimeout(function() {
                location.href = "intent://#Intent;scheme=;end"; //안드로이드 마켓 주소
            }, 1000);
        }
        else {
            // 크롬 이외의 브라우저들
            setTimeout(function() {
                if ((new Date()).getTime() - visiteTm < 2000) {
                    location.href = "market://details?id=com"; //안드로이드 마켓 주소
                }
            }, 500);

            var iframe = document.createElement('iframe');

            if (iframe) {
                iframe.style.visibility = 'hidden';
                iframe.src = 'intent://#Intent;scheme=;end';
                document.body.appendChild(iframe);
                document.body.removeChild(iframe); // back 호출시 캐싱될 수 있으므로 제거
            }
        }
    }
    else if (userAgent.match(".*iPhone.*") || userAgent.match(".*iPad.*")){
        //아이폰
        setTimeout( function () {
            if (( new Date() ).getTime() - visiteTm < 3000) {
                location.href = "https://apps.apple.com/app/id"; //ios 앱스토어 주소
            }
        }, 2500);
                
        setTimeout( function () {
            // 앱실행
            location.href = "앱주소://";
        }, 0);
    }
}

 

해결방법

아래 소스에서 포인트는 focus 이벤트를 이용한 것이다. confirm을 껐을때 앱으로 이동했느냐 아직 web상에 머물러있냐로 판별하여 web상에 머물러있다면 앱이 없다고 생각하고 앱스토어로 이동하는 이벤트를 실행한다.

flow
> 앱으로 이동함수 실행
> 앱으로 이동하시겠습니까? confirm
앱이 있는경우 > 이동되고 끝
앱이 없는경우 > confirm 이 닫히고 window에 focus 되므로 앱스토어로 이동하는 이벤트 실행
const openAppStore = function() {
    //딥링크 기본 주소 설정 (홈)
    deepLink = deepLink ? deepLink : appScheme + "main?mainTab=0";

    const userAgent = navigator.userAgent;

    /* 안드로이드 */
    if (userAgent.match(".*Android.*")) {
        const parsingDeepLink = deepLink.split(appScheme);

        //안드로이드 마켓주소
        location.href = "intent://딥링크#Intent;scheme=";
    }

    /* IOS */
    else if (userAgent.match(".*iPhone.*") || userAgent.match(".*iPad.*")) {
        var marketLink = "";

        //아이폰 앱스토어 주소
        marketLink = "https://apps.apple.com/kr/app/id";

        // 앱 이동
        function redirectToApp() {
            window.location.href = deepLink;
        }

        // 마켓 이동
        function redirectToMarket(_type) {
            setTimeout(
                function () {
                    window.location.href = marketLink;
                },
                _type === "CATCH" ? 200 : 900
            );
        }

        // 앱 이동 안되고 알럿꺼서 다시 FOCUS 될때 (==> 앱이 없다고 판단 가능하므로 마켓으로 이동시킴)
        window.addEventListener("focus", redirectToMarket, {once: true});

        // 앱 이동으로 실행
        try {
            redirectToApp();
        } 
        catch (e) { 
            // 이건 거의 안타지만 혹시 몰라서 방어코드로 추가
            redirectToMarket("CATCH");
        }
    }
}

 

 

반응형