Translate

2014년 6월 28일 토요일

[Android][Webview] Bridge 연결된 메소드가 실행되지 않는문제 (Uncaught TypeError: Object [object Object] has no method)




잘 구동되던 Android App 이 어느날부터 정상적으로 작동하지 않는 문제가 발생을 했다.
App 에서는 따로 수정하여 배포하지 않았으니 서버쪽에서 문제가 있는 것으로 생각을 했는데
예상외로 App의 문제였다.



Webview 의 bridge 로 연결을 시켜놓은 메소드가 없어서 실행이 안된다는 로그가 보였다.

로그내용
Uncaught TypeError: Object [object Object] has no method 메소드명(브릿지 시켜놓은)

문제를 찾아보니 Android 4.x 버전에서 API 변화가 있었나 싶다.
(그렇다고 잘 돌아가는 앱이 비정상적으로 작동하다니.. 버럭!!)



해결방법

class JsObject {
    @JavascriptInterface   <= Bridge 연결한 메소드위에 해당 애노테이션 추가
    public String toString() { return "injectedObject"; }
 }
 webView.addJavascriptInterface(new JsObject(), "injectedObject");
 webView.loadData("", "text/html", null);
 webView.loadUrl("javascript:alert(injectedObject.toString())");



개발자페이지 참고자료: 링크
문제해결 원본자료: 링크



2014년 6월 24일 화요일

[Android][Volley] Volley를 사용해야 하는 이유




회사에서 Volley 기술을 사용해야 할 수 있으니 공부를 해서 세미나를 해보라고 한다.
이번기회에 Volley 에 대해서 공부하고 정리한 것을 공유해본다.


Keynote 파일을 공유해봤자 일반 Windows 에서는 보지 못할테니..
동영상으로 만든것 하나와 iCloud 에 올린 문서를 공유한다. (둘다 내용은 같다)


1. 동영상


2. Keynote 문서 공유: 링크
    (iCloud 계정이 있어야 볼수 있는것 같습니다.)





내용은 다음과 같다.
1. 왜 Volley 를 사용해야 하는가?
2. Thread Pool을 이용한 동시 요청 지원
3. 이미지 로딩 툴: NetworkImageView
4. 요청 취소
5. 다양한 Response 형식을 처리하도록 확장 가능
[JSON, XML, Image, protobuffer(구글의 직렬화 기술) etc..]



2014년 6월 23일 월요일

[Shell][Bash] 파일명의 특정 문자열을 일괄적 변경방법



파일명을 일괄 변경할 일이 있는데 이게 파일 개수가 꽤 많아서
찾는 시간이 조금 걸리더라도 찾아서 작업을 하는게 나을 것 같다는 판단!!



sed를 이용해 사용한 Script는 다음과 같다.

#!/bin/bash
for i in `find .`
do
mv $i `echo $i | sed -e 's/\/e/\/h/'`
done


출처: http://kjahyeon.no-ip.info/blog/?p=127



출처에서 변경된 부분 설명

1. ls 로 사용 시 현재의 디렉토리만 변경이 가능하지만 find로 검색 시 하위의 디렉토리까지 변경이 가능하다.

2. sed 관련
  - 사용방법: sed 's/원본문자열/치환할문자열/'   (문자열은 정규식 사용이 가능하다)
  - 위에서 내가 사용한 방법은 '/e' 문자열을 '/h'로 변경하는 작업이다.






다음과 같은 파일이 있다면
./1/e111.jpg
./1/e222.jpg
./2/e111.jpg
./2/e222.jpg

...


다음과 같이 변경이 된다.
./1/h111.jpg
./1/h222.jpg
./2/h111.jpg
./2/h222.jpg

...



2014년 6월 18일 수요일

[Android] LG G3 - "USB 디버깅을 허용하시겠습니까?" 팝업이 뜨지 않는문제



최근 LG G3 를 구매를 했는데 해당 단말기에 어플을 넣으려 연결하니
ADB에 Device 가 정상적으로 붙지 않았다.


Window, Mac(OSX) 에서 모두 연결이 되지 않는 문제가 발생..

1004lucifer
다음과 같이 "USB 디버깅을 허용하시겠습니까?" 라는 문구가 나와서 허용을 해줘야 하는데
해당 팝업이 뜨지 않았다.






왜그런가 한참을 이것저것 해봤는데 결국 다음과 같이 허무하게 해결..ㅠㅠ
1004lucifer




PS. 추가내용
집에와서 Ubuntu 13.10 에 연결 시 에는 PTP모드로 변경해야만 정상적으로 인식이 되었다.




2014년 6월 13일 금요일

[Android] Android 2.x 에서 iframe 엘리먼트의 Scroll, Height 속성이 적용되지 않는 문제





iframe 으로 다른 컨텐츠를 로딩 후 Android 에서 확인해보니
레이아웃이 잘못나오거나 동작을 하지 않는 문제가 발생했다.


이슈 사항은 다음과 같다.


* iframe Element

Android 2.x
  - height 속성이 적용되지 않는다.
  - 위의 문제로 인해 scroll 을 적용할 수 없다.




해결 방법은??

iframe 내에 들어가는 컨텐츠의 height를 iframe 에 적용하고 싶은 height 로 잡아준 후
내부에서 스크롤을 잡아준다.


outer.html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <div id="divWrapper" style="width:100%; height:500px;">
        <div id="divHeader" style="width:100%; height:100px;"></div>
        <div id="divContent" style="width:100%; height:300px;">
            <iframe id="iframeContent" style="width:100%; height:100%;" src="inner.html"></iframe>
        </div>
        <div id="divFooter" style="width:100%; height:100px;"></div>
    </div>
</body>
</html>





inner.html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
    <script src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
    <script type="text/javascript">
        $(document).ready(function() {
            var iframeWrapper = parent.document.getElementById('divContent');
            iframeWrapper = $(iframeWrapper);

            $('html').css({
                'height' : iframeWrapper.css('height')
            });
            $('body').css({
                'height' : iframeWrapper.css('height')
            });
        });
    </script>
</head>
<body>
    <div id="innerContent">
        Content
    </div>
</body>
</html>




PS.
inner.html 에 들어가는 div 또한 scroll 이 되지 않으므로 해당 페이지에서 scroll 처리가 필요하다.
http://1004lucifer.blogspot.kr/2014/06/android-android-2x-div-element-scroll.html




PS.
ID 값을 가지지 않고도 inner.html 페이지에서 자신의 iframe 의 height 값을 가져올 수 있다.
방법은 아래의 링크
http://1004lucifer.blogspot.kr/2014/07/html-iframe-iframe-width-height-id.html




2014년 6월 5일 목요일

[Android] Android 2.x 에서 Div Element 의 Scroll 이 적용되지 않는문제




모바일 페이지 제작을 하다가 Android 2.x 버전에서는 Div 의 스크롤이 적용되지 않는 문제를 발견했다.

찾아보니 다음과 같다고 한다.

OS ver: Android 2.x
Element: Div
Attribute: overflow:auto/scroll is ignored


참고: 하단의 소스에서 <br/> 부분이 보여지지 않음.

위와 같은 상황이라면 아래의 소스는 Android 2.x 에서 동작하지 않는다.

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        #wrapperDiv {
            height:100px;
            overflow: scroll;
            background-color:#edffbc;
        }
        #content {
            background-color: #adffe9;
        }
    </style>
</head>
<body>
    <div id="wrapperDiv">
        <div id="content">
            1111111111<br/>
            2222222222<br/>
            3333333333<br/>
            4444444444<br/>
            5555555555<br/>
            6666666666<br/>
            7777777777<br/>
            8888888888<br/>
            9999999999<br/>
            0000000000<br/>
            1111111111<br/>
            2222222222<br/>
            3333333333<br/>
            4444444444<br/>
            5555555555<br/>
            6666666666<br/>
            7777777777<br/>
            8888888888<br/>
            9999999999<br/>
            0000000000<br/>
            1111111111<br/>
            2222222222<br/>
            3333333333<br/>
            4444444444<br/>
            5555555555<br/>
            6666666666<br/>
            7777777777<br/>
            8888888888<br/>
            9999999999<br/>
            0000000000<br/>
            1111111111<br/>
            2222222222<br/>
            3333333333<br/>
            4444444444<br/>
            5555555555<br/>
            6666666666<br/>
            7777777777<br/>
            8888888888<br/>
            9999999999<br/>
            0000000000<br/>
        </div>
    </div>
</body>
</html>




그래서 이것저것 알아보니 iScroll 을 많이 사용하는 것 같다. 링크

그냥 컨텐츠의 내용을 보여주는 목적만 있다면 위의 것을 사용해도 상관은 없지만
우리는 컨텐츠의 내용중 touch, click 이벤트 발생 시 특정 액션을 수행해야 했다.


iScroll 을 사용 할 수 없는 상황이 되어버렸다.
(iScroll 에서는 touch, click 이벤트 버블을 막아버린다.)


결국 스크립트로 스크롤 기능(플리킹 포함)을 직접 구현을 했다.  -_-

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
    <script src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
    <script src="http://code.jquery.com/ui/1.10.4/jquery-ui.min.js"></script>
    <style type="text/css">
        #wrapperDiv {
            position: relative;
            height:100px;
            overflow: auto;
            background-color:#edffbc;
        }
        #content {
            width: 100%;
            background-color: #adffe9;
        }
    </style>
    <script type="text/javascript">
        var android2x = true;//navigator.userAgent.match(/Android 2/);

        $(document).ready(function(){
            var wrapperDiv = $('#wrapperDiv');
            var content = $('#content');
            content.css({
                position: 'absolute',
                top: '0px'
            });


            var clientY, endY, disY;
            var ableDistance, contentTop;
            var autoMove = 0;

            // Android 2.x 버전에서만 해당 기능이 수행되도록..
            // 이외의 버전에서는 overflow:auto 기능을 이용한다.
            if (android2x) {

                //해당 컨텐츠의 이동 가능한 범위
                ableDistance =
                        -parseInt(content.css('height').replace('px', ''))
                        + parseInt(wrapperDiv.css('height').replace('px', ''));

                content.bind('touchstart', function(event) {
                    disY = 0;
                    clientY = event.originalEvent.touches[0].clientY;
                });
                content.bind('touchmove', function(event) {
                    disY = event.originalEvent.touches[0].clientY - clientY;
                    clientY = event.originalEvent.touches[0].clientY;
                    contentTop = parseInt(content.css('top').replace('px', '')) + disY;
                    if (contentTop < 0 && contentTop > ableDistance) {
                        content.css({'top' : contentTop + 'px'});
                    }

                });
                // 플리킹 기능 구현 (easing:easeOutExpo 을 사용하기 위해 jquery ui 가 필요)
                content.bind('touchend', function(event) {
                    autoMove = disY * 5;
                    contentTop += autoMove;
                    if (contentTop > 0) {
                        contentTop = 0;
                    }
                    if (contentTop < ableDistance) {
                        contentTop = ableDistance;
                    }
                    if (-2 > disY || disY > 2) {
                        content.animate({
                            'top' : contentTop + 'px'
                        }, 500, 'easeOutExpo');
                    }
                });
            }
        });
    </script>
</head>
<body>
    <div id="wrapperDiv">
        <div id="content">
            1111111111<br/>
            2222222222<br/>
            3333333333<br/>
            4444444444<br/>
            5555555555<br/>
            6666666666<br/>
            7777777777<br/>
            8888888888<br/>
            9999999999<br/>
            0000000000<br/>
            1111111111<br/>
            2222222222<br/>
            3333333333<br/>
            4444444444<br/>
            5555555555<br/>
            6666666666<br/>
            7777777777<br/>
            8888888888<br/>
            9999999999<br/>
            0000000000<br/>
            1111111111<br/>
            2222222222<br/>
            3333333333<br/>
            4444444444<br/>
            5555555555<br/>
            6666666666<br/>
            7777777777<br/>
            8888888888<br/>
            9999999999<br/>
            0000000000<br/>
            1111111111<br/>
            2222222222<br/>
            3333333333<br/>
            4444444444<br/>
            5555555555<br/>
            6666666666<br/>
            7777777777<br/>
            8888888888<br/>
            9999999999<br/>
            0000000000<br/>
        </div>
    </div>
</body>
</html>



PS. 
iframe 또한 scroll 이 되지 않으므로 해당 페이지에서 scroll 처리가 필요하다. 
http://1004lucifer.blogspot.kr/2014/06/android-android-2x-iframe-scroll-height.html



[Facebook] FB.Canvas.setAutoGrow() 가 IE 에서 정상적으로 동작하지 않는 문제




페이스북 앱 개발 후 페이지에 앱을 넣으면 보통은 앱의 길이가 더 길기 때문에
FB.Canvas.setAutoGrow(); 를 사용하여 페이지의 길이를 자동으로 맞춰준다.
(Scrollbar 를 없애기 위해..)

// 2014.06.05
하지만 이상하게도 IE 에서만 해당 기능을 이용했는데도 스크롤이 없어지지 않았다.


예제소스는 다음과 같다.

        var uid;
        var accessToken;
        var name;

        (function(d, s, id){
            var js, fjs = d.getElementsByTagName(s)[0];
            if (d.getElementById(id)) {return;}
            js = d.createElement(s); js.id = id;
            js.src = "//connect.facebook.net/ko_KR/sdk.js";
            fjs.parentNode.insertBefore(js, fjs);
        }(document, 'script', 'facebook-jssdk'));

        window.fbAsyncInit = function() {
            FB.init({
                appId      : '000000000000000',
                xfbml      : true,
                version    : 'v2.0'
            });

            FB.Canvas.setSize({ width: 810, height: 1400 });
            FB.Canvas.setAutoGrow();

            FB.getLoginStatus(function(response) {
                if (response.status === 'connected') {
                    uid = response.authResponse.userID;
                    accessToken = response.authResponse.accessToken;
                } else if (response.status === 'not_authorized') {
                } else {
                }
            });
        };


위의 부분에서 문제가 되었던 부분은 name 이라는 전역변수 때문에 스크롤이 없어지지 않았다.
3~4시간 노가다를 하면서 겨우 찾은 방법.. ㅠ
그리고 facebook sdk 를 동적으로 삽입하는 방법 또한 하단에 있다가 위로 올렸는데
정확하게 다시 테스트 해보지는 못했지만 아래에 있을때 스크롤이 없어지지 않는것 같기도!?
(원래는 상관 없어야 하지만..;;)


결론적으로는 페이스북에서 IE 브라우저에서 특별한 처리를 하지 않았다면 IE의 버그라고 밖에 생각을 할 수가 없는데..
IE9 에서 이런 치명적인 버그가 있단 말인가? (진실은 저너머에..)

페이스북 자체에서 전역변수로 name을 쓴다고 해도 어차피 페이지에 있는 앱은 iframe으로 들어와 있기 때문에 변수명이 겹치지 않는다.

아니면 facebook 에서 iframe 내부에 있는 변수를 건드리는게 있는걸까??



by http://www.socialkorea.co.kr/

하이브네스트의 김현진대표와 소셜코리아가 없었다면 페북 개발에 대해서 관심이 없었을테니..
이렇게라도 광고를..ㅎㅎ

둘다 모두 잘 되기를..ㅋ


[Android] Samsung Galaxy Emulator (삼성 갤럭시 시리즈 에뮬레이터)



최근 모바일 작업을 하다보니 회사에서 나오는 시료 단말기로 테스트를 진행을 하는데
모든 단말기에 대해서 구비를 할 수 없어서 보통 AVD(Android Virtual Device)
많이 이용한다.

하지만 같은 OS버전이라도 단말기마다 해상도가 다르고 각각 요상한(!?)
특징이 있다보니 완전히 일치하는 결과를 내기가 쉽지가 않다.


인터넷을 돌아댕기다 삼성 개발자페이지에서 삼성 단말기의 에뮬레이터를
지원해 주는것을 찾았다.

링크: http://developer.samsung.com/remotetestlab/rtlDeviceList.action#




1. 사이트에 들어가면 다운받을 수 있는 에뮬레이터 목록을 볼 수 있다.
   (다운로드 받으려면 삼성개발자 페이지에 회원가입을 해야 한다.)






2. 다운받을 단말기의 OS버전이나 사용 시간을 선택한다.






3. 단말기(Host)에 대해서 'Start' 클릭하면 jnlp 확장자 파일이 다운로드 된다.






4. 해당 파일을 java로 실행시키면 다음과 같은 화면이 나온다.

  - 우분투의 경우 (출처: 링크)
    1) 설치: sudo apt-get install icedtea-netx
    2) 실행: sudo javaws ./<파일명>.jnlp

  - 보안설정으로 실행할 수 없는경우 => 링크 참조






5. 처음 에뮬레이터가 나타났을때의 모습.






6. 잠금화면을 풀고나서의 모습






7. 혹시나 싶어서 adb 연결이 되나 봤는데 역시나.. 되지 않는다.
    DDMS와 같은 기능은 이용할 수 없으며 APK를 에뮬레이터에서 다운로드 받아
    정상적으로 작동되는지의 여부를 확인하거나..
    OEM Browser(Webview) 에서 레이아웃이 깨질 때 확인용으로 사용이 가능하다.







======================
2014.06.23 추가

기기의 위에서 오른쪽 버튼을 누르면 다음과 같은 기능을 사용할 수 있다.







인증이 되지 않아서 APK를 넣을 수가 없었다.




















'Test - Logs' 클릭 시 위와같이 DDMS에서 보는것과 같이 로그를 보는것이 가능하다.









'Test - Terminal' 클릭 시 adb shell 로 접속할 수 있는 포트를 알려주는데
IDE(eclipse 같은) 툴에서 DDMS확인하려 위와같이 Connect 를 하게되면
연결은 되지만 1초도 되지 않아 끊어지고 만다.

아직까지 실질적으로 DDMS에 연결 할 수 있는 방법을 알아내지 못했다.
======================






PS.
해당 사이트에서 현재 지원 가능한 단말기의 종류는 다음과 같다.
단말기 이름뒤에 있는 대괄호는 OS version 을 뜻한다.

1. Premium Galaxy (WVGA)
  - Galaxy S II [2.3.3]
  - Galaxy S II [4.1.2]

2. Premium Galaxy (WXGA)
  - Galaxy Note [2.3.6]
  - Galaxy Note [4.1.2]

3. New Tablet Galaxy (WSVGA)
  - Galaxy Tab 3(7.0) [4.1.2]

4.Tablet Galaxy (WXGA)
  - Galaxy Tab 10.1 [3.2]
  - Galaxy Tab 3(10.1) [4.2.2]
  - Galaxy Note 8.0 [4.1.2]
  - Galaxy Note 8.0 [4.2.2]
  - Galaxy Note 10.1 [4.1.1]
  - Galaxy Note 10.1 [4.1.2]

5. Tablet Galaxy (WQXGA)
  - Galaxy Note 10.1 2014 Edition [4.3]
  - Galaxy Note 10.1 2014 Edition [4.4.2]

6. Premium Galaxy (HD)
  - Galaxy Note II [4.1.1]
  - Galaxy Note II [4.3]
  - Galaxy S III [4.1.1]
  - Galaxy S III [4.1.2]
  - Galaxy S III [4.3]

7. Premium Galaxy (Full HD)
  - Galaxy Note 3 [4.3]
  - Galaxy Note 3 [4.4.2]
  - Galaxy S4 [4.2.2]
  - Galaxy S4 [4.3]
  - Galaxy S4 [4.4.2]
  - Galaxy S5 [4.4.2]



[JAVA][OSX] 사용자의 보안 설정에서 자체 서명된 응용 프로그램이 오래되거나 만료된 Java 버전으로 실행되는 것을 차단했습니다.



OSX 에서 Java 프로그램 구동 시 다음과 같은 멘트가 나오면서 실행이 되지 않았다.

사용자의 보안 설정에서 자체 서명된 응용 프로그램이 오래되거나 만료된 Java 버전으로 실행되는 것을 차단했습니다.






방법은 다음과 같다.


1. 시스템 환경설정의 Java 클릭





2. Java 제어판에서 '보안' 탭을 클릭





3. 보안레벨을 '중간' 으로 변경 후 확인 클릭





4. 프로그램을 다시 실행 시 아래와 같이 나오는데 체크박스에 체크 후 실행하면 실행 가능.




2014년 6월 4일 수요일

[Tomcat] https 페이지(html,jsp) 호출 시 파일(html,jsp) 자체가 다운로드 되는 문제



로컬 피씨에 https 설정을 이전에 해 놓았었는데 이상하게도 다음과 같이

localhost:8443/index.html

이라고 입력 시 해당 페이지가 보여지는게 아니라 파일이 다운로드가 되어버리는 증상이 발생..




피씨도 껐다켜보고 server.xml 파일도 다시한번 봤지만 문제되는 부분은 없었다.
알고나니 허무해버린 문제의 원인은 다음과 같았다.

https://localhost:8443/index.html
이라고 입력해 주지 않아서..;;

8443 포트로 https 요청을 날려야 하는데 http 요청만 날려대고 있으니
정상적으로 처리될리가 없었다.;;; -_-