달력

42025  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

'모바일 개발/공통'에 해당되는 글 1건

  1. 2017.12.14 javascript로 웹에서 App 열기

 ios 도 그렇고 android도 그렇고  url 형식으로 앱에 접근이 가능하다. 앱이 설치 되어 있다면 앱을 실행 시키고, 앱이 설치되어 있지 않다면 앱 설치 페이지로 전환 시켜주는게 가능하다. 그리고 앱에 특정 데이터를 전달 해서 원하는 기능을 제공 할 수 있다.


일단 기본 적인 android 와 ios 둘 다 메커니즘은 동일하다. user-action을 통한 이벤트여야지 동작을 한다는 것과, setTimeout을 이용해서 마켓으로 이동을 시켜야 한다는 것. 

소스로 확인 해보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
var androidPackage = "my.app.package";
var appleAppId = ""; // id1401934913 형식으로 itunes url에 나오는 앱아이디.
var androidMarketUrl = "market//detail?id="+androidPackage;
var iosMarketUrl = "http://itunes.apple.com/kr/app/" + appleAppID;
function goStore(){
    var startTime = +new Date();
    setTimeout(
        function() {
            var now = +new Date();
            if ( now - startTime < 1000){
                var marketUrl = "";
                if( isAndroid ){
                    marketUrl = androidMarketUrl;
                }else if( isiOS ){
                    marketUrl = iosMarketUrl;
                }
                location.href = marketUrl;
        }
    , 500)
    if ( isAndroid ){
        openAndroid();
    }else if ( isiOS ){
        openiOS();
    }
}
 
function openAndroid(){
    var userAgent = navigator.userAgent.toLowerCase();
    if ( userAgent.match(/chrome/) ){
        location.href = "intent://hostName?param1=someValue1¶m2=someValue2/"
                                    +"#Intent;scheme=schemeName;action=android.intent.action.VIEW;"
                                    +"category=android.Intent.category.BROWSABLE;package="+androidPackage;
    }else{
        var iframe = document.createElement( 'iframe' );
        iframe.style.visivility = 'hidden';
        iframe.src = 'schemeName://hostName?param1=someValue1¶m2=someValue2';
        document.body.appendChild(iframe);
        document.body.removeChild(iframe);
    }
}
 
function openiOS(){
    location.href = "schemeName://hostName?param1=someValue1¶m2=someValue2";
}

안드로이드는 버전에 따리 분기 처리해줘야 하는데 요즘은 schemeName 을 intent로 고정해서 사용한다고 한다. 이전 버전에서는 iframe을 이용하는게 제일 깔끔하다고 어디서 봐서 iframe으로 사용 했다. 

중요한 부분은 3 함수 모두 사용자 액션 기반으로 발동이 되어야 한다는 것이다. onload나 그런 것이 아닌 dom을 클릭해서 실행 하던지 comfirm() (confirm만으로는 안된다. dom을 클릭해야만 발동되더라..) 을 통해 처리 해야 한다는 것이다.

안드로이드에서는 schemeName 과 hostName은 Manifest파일에 실행 될 activity 안에 아래 내용을 붙여 주면 된다.


1
2
3
4
5
6
7
8
<activity android:name="name" android:label="label" android:theme="theme">
    <intent-filter>
        <action android:name="android.intent.action.VIEW"> </action>
        <category android:name="android.intent.category.BROWSABLE"></category>
        <category ........=""> </category>
        <data android:host="hostName" android:scheme="schemeName"></data>
    </intent-filter>
</activity>

이렇게 넣어주면된다. 보면 action과 category도 맞춰줘야하는 건 쉽게 알 실듯 여러분들은 똑똑하니까

iOS 의 경우는 캡쳐로 때움.ㅋ

identifier랑 schemeName이랑 동일하게 하면 된다. 다르게 해도 되는 지는 모르겠다.ㅋ  iOS에서는 hostName은 따로 설정하지 않아도 된다.


자 이제 실행시킨 앱에서 파라미터를 받아서 어떻게 처리 하는지를 보자.

안드로이드 먼저

아까 실행될 acitivity의 onCreate에서 작업하면 된다.

1
2
3
4
5
if( getIntent().getScheme() != null && getIntent.getScheme().equals( "schemeName" ) ){
    String someValue1 = getIntent().getData().getQueryParameter( "param1" );
    String someValue2 = getIntent().getData().getQUeryParameter( "param2" );
    //do....
}

아래는 iOS 11 기준으로. iOS 는 버전별로 어디어디서 실행되는지는 모르겠다. iOS8 까지는 아래대로 하면 문제없을듯 하다. AppDelegate에 아래 함수를 수정해주자. 없으면 추가해주고.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
    guard let query = url.query else {return false}
    let querys = query.components(separatedBy: "&")
    var keyValue = Dictionary<string,string>()     
    for q in querys {
        guard let point = q.index(of: "=") else {continue}
        let keyEnd = q.index(before: point)
        let valueStart = q.index(after: point)
         
        let key = String(q[q.startIndex...keyEnd])
        var value = String(q[valueStart..< q.endIndex]) 
        keyValue[key] = value
    }
    //dosomethings..
    return true
}

나의 경우는 http url 을 파라미터로 넘겨서 앱에 있는 webview를 해당 url 로 넘겨주는 것을 구현했는데, iOS에서 병신같은 일이 일어났다.

파라미터로 넘긴 url 이  http://www.someDomain.co.kr/folder1/page.php/ 였다고 가정을 하면 끝에 /를 붙였다고 페이지 로딩 직후 바로 이전 url로 넘겨버리는 엄청난....병신같은...................ㅡㅡ 첨엔 내가 소스를 잘못 짠줄 알았는데 알고보니 / 때문이였다. 안드로이드는 상관없이 잘된다... WKWebView 버그인지는 잘 모르겠다. 근데, ㅋ 웃긴게 openurl로 넘겨온게 아니면 슬러쉬 있든 없든 잘된다는 거다.ㅋ


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
    guard let query = url.query else {return false}
    let querys = query.components(separatedBy: "&")
    var keyValue = Dictionary<string,string>()
     
    for q in querys {
        guard let point = q.index(of: "=") else {continue}
        let keyEnd = q.index(before: point)
        let valueStart = q.index(after: point)
         
        let key = String(q[q.startIndex...keyEnd])
        var value = String(q[valueStart..< q.endIndex]) 
         
        //url 끝에 슬러쉬 붙었다고 페이지 이동안됌. 이뭐병.... 끝에 슬러쉬를 없애주자...
        while value.hasSuffix("/"){
            let suffixIndex = value.index(value.endIndex, offsetBy: -1)
            value = String(value[value.startIndex..< suffixIndex])
        }
        keyValue[key] = value
    }
    //dosomethings..
    return true
}

이러니 잘되네............. 결국 저 슬러쉬 문제를 정리하기 위해서 겸사겸사 쓴 포스트.

Posted by
|