[Info]Tags categorized posts and contents patterns..

[AJAX] Ajax Code E xamples.. [Book] About the book.. [CSS] CSS Code E xamples.. [DB] Sql Code E xamples.. [DEV] All development stor...

2016년 4월 11일 월요일

[jQuery]모바일 웹에서 앱 설치 여부 확인 및 앱 이동 관련..

갑자기 모바일을 만질 기회가 생겼다.. 지금 생각해보면, 모바일 앱을 한것이 아니라 모바일 웹을 하게 되서 그나마 다행이라고 생각한다.. 앱은 진짜 아닌것 같다.. -_-;;

이유는 웹만 하던 나이기에 모바일 웹이란 것을 처음 접했는데 이건 머 테스트하기도 겁니 드럽고, 웹도 브라우저 버전에 따른 특성을 꽤나 타고 있다고 생각을 했는데 모바일 웹 쪽은 말도 안되게 더 많았다.. 진짜 말 그대로 욕나오는 헬이었다.. 좀 간단한 개념에서 바꾸는 것은 몰라도 스크립트 만지고 어쩌고 하면서 조금 깊게 들어가는건 절대!!! 하고 싶지 않다..

못하더라도 그냥 웹이 더 좋았다.. ㅠㅜ

구현해야 될 상황은 모바일 웹에서 버튼을 클릭하면, 특정 앱이 설치가 되어있는지를 판단 후 설치 페이지로 이동하거나 설치되어 있는 앱을 실행하는 것이었다.. 처음 상황을 파악한 후에 겁니 간단하군.. 이라고 생각을 했다.. 근데 완전 오산이었다.. 나만의 착각이었다..

검색을 하다보니 좋은 글이 있었다.. tageon 님 블로그 소스가 바로 그것이었다.. 역시 구글링이라고 생각을 하면서 해당 소스를 코딩했다.. 컨셉은 간단했다.. click(function) 이벤트가 발생하면, 꼼수의 개념으로 frame 을 만들고, setTimeout fucntion 을 통해서 딜레이 될 시간동안 현재날짜와 시간을 비교하고, 모바일 OS 버전에 따라서 분기를 해주고, 스토어 url 로 링크가 되거나 혹은 기 설치된 url 로 이동하는 패턴이었다.. 물론 첨에는 한참 쳐다보고 이해했다.. 한눈에 알아볼정도로 두뇌가 좋지는 않은 관계로..

근데 이걸 해보니 이런 된장 마즐.. OS 버전 등의 문제로 내 폰이 갤럭시 노트2 인데 그 외 노트 4이상 내지는 iPhone 9.X 버전에서는 죄다 실행이 안되는 것이다..

그래서 꿍시렁대면서 또 검색결과 정영탁 님의 블로그에 또 다른 소스가 있었다.. 해당 컨셉도 거의 비슷하긴 하지만, 약간의 차이가 있어서 또 열심히 코딩을 했는데 역시나 결과는 같았다.. 내 폰에서만 되고, 나머지 상위 버전 폰에서는 다 안되는 것이다..

찾아보면, 대부분 소스 패턴은 비슷한데 안된다.. 이상해서 검색을 해봤다.. 대체 왜.. 무엇 때문에.. 안되는 것일까..

1차적으로 Android 는 버전이 4.X 대에서 5.X 대로 넘어가면서 frame 적용 등에 대한 부분이 문제가 있었다.. 무엇보다 Chrome 의 버전 문제가 태반이었다.. 대신 소스에도 적겠지만, Intent 라는 개념을 통한 활용방법이 있었다.. 하지만, 개념 자체를 이해하고 있는것은 아니다..

2차적으로 iOS 는 버전이 9.X 대로 넘어가면서 웹에서 앱을 호출하면, safari 브라우저에서 주소가 올바르지 않아 찾을수 없다면서 자체적으로 오류를 한 번 뱉어낸다.. 그리고 9.X 대에서도 9.1, 9.2, 9.3 버전별로 틀린것인지 아이폰 내부적으로 사용하는 alert 창이 발생하는 것도 있고, 아닌 것도 있었으며, 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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<script type="text/javascript">
$(document).ready(function() {

 var androidAppLink = 'redpigScheme://'; //각자 정의된 scheme 를 적는다..
 var androidIntentUrl = 'intent://scan/#Intent;scheme=redpigScheme;package=com.android.chrome;end';
 var iosAppLink = 'redpigScheme://';
 var playStorePrefix = 'market://details?id=com.soribada.android&hl=ko'; //각자 정의된 store url 을 적는다..
 var appStorePrefix = 'https://itunes.apple.com/kr/app/id346528006?mt=8'; //각자 정의된 store url 을 적는다..

 var ua = navigator.userAgent;
 var supportDevicesRegEx = /Android|iPhone|iPad/i;
 var supportDevice = ua.match(supportDevicesRegEx);

 if(!!supportDevice) {
  var deviceName = supportDevice.pop();
  launchApp(deviceName);
  
 } else {
  location.href = playStorePrefix;
 }

 function launchApp(deviceName) {
  var isIOS = 'Android' != deviceName ? true : false;
  
  if(isIOS && isChromeAndBigThanChromeVersion18()) {
   location.href = androidIntentUrl;
      
  } else if(isIOS && isBigThanIOS9()) {
   location.href = universalLink;
   failApp(isIOS);
   
  } else {
   var src = deviceName == 'Android' ? androidAppLink : iosAppLink;
   $('<iframe>').attr('src', src);
   failApp(isIOS);
  }
 }
 
 function isChromeAndBigThanChromeVersion18() {
  var ua = navigator.userAgent;
  if(ua.indexOf('Chrome') == -1 ){
   return false;
  }
  
  var versionRegEx = /Chrome\/[0-9]+\.[0-9]+\.[0-9]+/;
  var majorVersion = ua.match(versionRegEx).pop().split('\/')[2];
  return parseInt(majorVersion) > 18 ? true: false;
 }
    
 function isBigThanIOS9(){
  var ua = navigator.userAgent;
  var versionRegEx = /iPhone OS [0-9]+/;
  var version = ua.match(versionRegEx).pop().split(' ')[2];
  var majorVersion = parseInt(version.split('_')[0]);
  return majorVersion >=9 ? true: false;
 }
 
 function failApp(isIOS) {
  var storeURL = isIOS ? appStorePrefix : playStorePrefix;
  var deLay = 1000;
  setTimeout(function() {
   location.href = storeURL;
  }, deLay);
 }
});
</script>

소스가 아주 어렵지는 않을 것이다.. 이 소스는 나 스스로 짠것이 아니라 칭구가 도와줬는데 이것저것 관심이 많은 녀석이고 해서 도움을 요청했다.. B 씨 이 자리를 빌어서 진정 고맙다.. 주말에 본인 시간 빼가면서 도와줬으니.. 쌩유..!!!

우선 기본적으로 var 선언을 해주는데 5번 라인 androidIntentUrl 변수가 초반에 언급했던 Intent 다.. 모바일 웹에서 설정 파일을 통해서 본인이 링크하고자 하는 앱의 url 정보를 간단한 명칭으로 정의해주고, package 등의 정보도 같이 하면, 보다 손쉽게 링크되고 하는 듯하다.. java xml 의 매핑정보 정도가 아닐까 생각하고 넘어갔다.. 개념 자체를 파해친건 아니라서 잘은 모르겠다..

14번 라인은 12번 라인 supportDevice 에서 가져온 정보를 통해서 분기를 시킨다.. 정상이라면, 모바일 OS 명을 넘겨주고, 그것이 아니라면 PC 혹은 기타 기기에서 접근이기에 무조건 스토어 설치 페이지로 보내버린다..

위에서 정상처리가 되었다면, 22번 라인 launchApp 을 통해서 분기를 시도한다.. 신형 안드로이드 기반, iOS 기반, 기타 OS 로 구분해서 분기를 한다..

단, 분기하기 위한 조건 판별 과정에서 39번 라인 isChromeAndBigThanChromeVersion18 과 50번 라인 isBigThanIOS9 에서 정규식을 통해서 navigator.userAgent 에서 뽑아온 정보를 확인하고 버전을 리턴하게 되는 것이다..

58번 라인은 setTimeout 개념을 집어넣어서 1초의 시간을 주어진 후에 스토어 url 로 가거나 혹은 앱 url 로 이동하게 된다..

완성 소스도 아니고, 그나마 오래한 분야가 아니다보니 누군가에게 누가 될까봐 아주 디테일하게 설명하기가 좀 부끄럽다.. ㅎㅎ..

실제 소스에는 삽질한 흔적이 겁나 많은데 그것들을 다 보여줄 수는 없는 노릇이고, 최대한 깔끔하게 갖고 왔다..

현 시점에서의 최종 소스는 Android 쪽 코딩은 그대로 가고, iOS 는 30번 라인에 존재하는 failApp(isIOS); 부분을 없애서 설치, 미설치 할 것 없이 무조건 스토어로 가게 변경하였다..

항상 개발을 하다보면, 싫다고는 하지만 그래도 기왕 나한테 넘어온것이라면, 어느정도의 해결 이상을 해내고 싶었는데 아쉽다.. 항상 그렇게 해온것은 아니긴 하지만, 주말에도 나와서 찾아보고 코딩하고 했는데 결과가 이렇게 되니 좀 아쉽게 남는 듯하다..

무튼.. 어느쪽 모바일 OS 건 간에 좀 어느정도 패턴에 있어서 확일화를 했으면 좋겠다.. 웹 개발 때도 그랬는데 이건 머 버전이 0.1 이 올라갔음에도 안되는거 투성이고, 모바일 개발자분들 진짜 존경스럽다.. 특히나 웹하고 틀리게 단말기 기준으로 돌아가니 나에게 기기가 없으면, 테스트가 안되는 것 아닌가.. 에씨 ㅡㅡ..


나중에 언제가 될지는 모르겠으나 해당 개발 관련해서 무엇인가 추가가 되거나 수정이 되서 기능적인 보완이 된다면, 추가적으로 포스팅을 해야겠다.. 그렇지만 개인적으로 모바일쪽은 좀 멀리하고 싶어진 계기였다.. ㅋㅋㅋㅋ..

글구 고생을하고 찾아보고 하면서, schme, intent, Universal Link, 모바일 OS 버전 등등에 대해서 알게 되서 좀 좋았다..

댓글 없음:

댓글 쓰기