출처 : http://tjandroid.blogspot.com/2011/06/adb.html
usb 악세서리를 개발하게 되면 폰이 악세서리와 usb 로 연결 되어 있기 때문에 디버깅 하기가 여간 힘든게 아니다.

만약 PC 와 안드로이드 폰이 같은 네트워크 안에 있다면 예를 들어 같은 무선 공유기에 접속해 있다면 adb 를 usb 연결 없이 네트워크로 사용할 수 있다.

참조: http://developer.android.com/guide/topics/usb/index.html 의 Debugging considerations 부분

일반적인 방법
1. PC 와 폰 모두 같은 공유기에 접속한다.
2. PC 와 폰을 usb 로 연결한다.
3. PC 의 terminal 창을 열고 adb 명령을 다음과 같이 수행한다.
 - adb tcpip 5555
 - 이후 부터 usb 연결을 해제해도 된다.
4. 폰의 ip 주소를 확인한다.
 - settings > wireless & networks > wifi settings > 연결된 AP 를 터치 하면 할당된 ip 주소를 확인할 수 있다.
5. PC 의 terminal 창에서 다음과 같이 adb 명령을 수행한다.
 - adb connect [ip address]:5555
 - 예를 들어 폰의 ip address 가 192.168.1.15 이면 adb connect 192.168.1.15:5555 를 수행한다.
6. usb 연결을 해제하고 adb logcat 을 수행해 본다.
 - usb 로 연결할 때와 똑같이 앱 설치 등의 adb 의 모든 명령어를 사용할 수 있다.

안드로이드 폰 벤더가 위 기능을 허용하지 않을 수 있다.
위 방법은 안드로이드 폰 벤더가 기능을 허용한 경우에만 가능한 방법이다.
대부분의 안드로이드 2.2 버전을 포함한 이전 버전의 폰에서는 위 기능이 활성화 되어 있지 않다.
만약 폰을 루팅하였다면 adbWireless 를 다운로드 받아 설치한 후 실행하여 adb wireless 를 활성화 시킨 후 위 과정을 수행하면 무선으로 adb 를 사용할 수 있다.

결론
일반적인 방법을 사용해 보고 만약 연결이 되지 않는 다면 루팅하는 방법을 찾아보고 루팅이 가능하다면 adbWireless 를 사용한 상태에서 다시 위 과정을 수행하면 되겠다.

폰 벤더도 허용을 하지 않고 루팅도 할 수 없다면 사용할 수 없다.
출처 : http://blog.naver.com/mujjingun/60144443786

1. 이클립스 없이 안드로이드 개발환경 구축하기1 ( JDK 설치, 안드로이드 SDK 설치, 에뮬레이터 실행 )
 
 
2. 이클립스 없이 안드로이드 개발환경 구축하기2 ( 프로젝트 생성, 컴파일, 실행 )
 
 
2-1 프로젝트 환경 파일 재구성하기 - Update Project
 
 
3. 안드로이드 프로그래밍 시작하기
 
 
4. 버튼 사용하기
 
 
5. 에디트텍스트(EditText) 사용하기
 
 
6. 리스트뷰 사용하기 - 기초편
 
 
7. 리스트뷰의 사용하기 - 활용편
 
 
8. 쓰레드(Thread) 의 이해 - 기초편
 
 
9. 스트림(Stream)의 이해 - 바이트 스트림
 
 
10. 소켓(Socket) 통신의 이해 - 클라이언트
 
 
11. 소켓(Socket) 통신의 활용 - MFC 서버와 통신하기
 
 
12. TimerTask 클래스를 사용한 스톱워치
 
 
13. 서버 화면을 캡쳐하여 클라이언트에 전송하기
 
 
14. 액티비티(Activity)의 이해
 
 
15. 액티비티 전환하기 - 명시적 전환
 
 
16. 컨텍스트(Context)
 
 
17. 사진 촬영 후 이미지뷰에 출력하기
 
 
18. TTS ( TextToSpeech )
 
 
19. 사진 촬영 후 서버로 전송하기
 
 
20. 음성 인식(Voice Recognition) 
    http://www.tipssoft.com/bulletin/tb.php/FAQ/961
 
 
21. 음성인식을 이용한 발음 테스트 예제
 
 
22. 그림그리기의 기초와 구조
 
 
23. 사용자정의 뷰 생성 및 배치1
 
 
24. 사용자조작 처리하기 ( TouchEvent Handler )
    http://www.tipssoft.com/bulletin/tb.php/FAQ/973
 
 
25. 뷰의 터치위치 좌표로 출력하는 예제
 
 
26. 터치를 이용한 간단한 게임
 
 
27. 메뉴( Menu ) - 기초
    http://www.tipssoft.com/bulletin/tb.php/FAQ/980
 
 
28. 메뉴( Menu ) - Context Menu
 
 
29. 메뉴( Menu ) - Options Menu
 
 
30. 메뉴( Menu ) - Sub Menu
 
 
31. 탭 레이아웃(Tab Layout) 사용하기 - Intent 방식1
    http://www.tipssoft.com/bulletin/tb.php/FAQ/987
 
 
32. 탭 레이아웃(Tab Layout) 사용하기 - Intent 방식2
 
 
33. 어플리케이션에서 한글 사용하기
 
 
34. 간단한 대화상자( 다이얼로그 ) 사용하기
 
 
35. 대화상자의 이해 1
 
 
36. 대화상자의 이해 2
 
 
37. 대화상자에 리스트, 체크, 라디오 버튼 사용하기
 
 
38. 원형 프로그래스 대화상자
 
 
39. 바(Bar)형 프로그래스 대화상자
    http://www.tipssoft.com/bulletin/tb.php/FAQ/1007
 
 
40. "Back" 키 두번 터치하여 종료하기 
 
 
41. 꺼지지 않는 화면 설정하기
 
 
42. 토스트( Toast ) 사용하기 - 기본
 
 
43. 진동 울리기 ( 지정시간 진동과 패턴 진동)
 
 
44. 회전 방향별로 다른 레이아웃 적용하기
    http://www.tipssoft.com/bulletin/tb.php/FAQ/1031
 
 
45. 어플리케이션 회전 방지하기 (화면 방향 고정하기)
    http://www.tipssoft.com/bulletin/tb.php/FAQ/1032
 
 
46. 센서를 사용하기 위한 공통 루틴
    http://www.tipssoft.com/bulletin/tb.php/FAQ/1033
 
 
47. 센서 - 조도 측정하기
 
 
48. 센서 - 근접센서를 이용하여 거리 측정하기
 
 
49. 센서 - 방향센서 사용하기
 
 
*. 나침반 예제
 
 
50. 센서 - 가속도 센서 사용하기

출처 : http://whitet8899.egloos.com/1322431
ADB (Android Debug Bridge)



ADB의 구성

client : development machine에서 동작. shell에서 client를 invocation해서 command 실행 가능. ADT, DDMS도 client

server : development machine의 background process이며, client와 daemon 사이에서의 communication을 관리

daemon : 각각의 device에서 동작하는 background process

client를 시작하면, ADB server가 실행중인지 확인해서 실행중이지 않으면 server를 시작시킨다. server가 시작되면 TCP의 5037 port로 binding해서 adb client로부터의 command를 받아들이는데, 모든 client는 server와 communication 하기 위해 5037 port를 사용.

실행파일 : ${android_sdk_path}/tools/adb



Command 입력 형식

adb [-d | -e | -s <serialNumber>] <command>

adb devices : adb server와 연결된 device를 보여준다.
형식 : [serialNumber] [state]

serialNumber = type-consolePort (ex : emulator-5554)
state = offline (device가 adb와 아직 연결되지 않았거나 응답이 없는 상태)
            device (adb server와 연결된 상태)

-s option : 여러개의 device가 연결되어 있는 상태에서 특정 device에 command를 입력하고 싶을 때 사용
형식
adb -s <serialNumber> <command>

ex : adb -s emulator-5554 install sample.apk



Port forwarding

device의 port를 forwarding 하고 싶을 때 사용하는 명령

ex : port 6100에서 7100으로 forwarding 하고 싶은 경우
adb forward tcp:6100 tcp:7100



Copying files

pull
device에서 file을 copy해 올 때 사용 (recursively)
adb pull <remote> <local>

push
pull과 반대로 file을 device에 복사해 넣고 싶을 때 사용 (recursively)
adb push <local> <remote>

ex : adb push foo.txt /sdcard/foo.txt) (/sdcard/foo.txt 에서 /sdcard는 device에 존재하는 path



Listing of adb Commands

Options

-d
연결된 USB device에만 direct로 command 전송
USB device가 하나 이상이면 error return

-e
실행중인 device에만 command 전송
하나 이상의 device가 실행중이면 error return

-s <serialNumber>
특정 device에만 command 전송 (serialNumber 형식은 위 내용 참조)


General

devices
연결된 모든 device list 출력

help
제공되는 adb command list 출력

version
adb version 출력


Debug

logcat [<option>] [<filter-specs>]
log data 출력

bugreport
bugreport를 위한 dumpsys(system data dump), dumpstate(state dump), logcat data 출력

jdwp
특정 device의 JDWP process들의 list(pid) 출력


Data

install <path-to-apk>
application 설치

pull <remote> <local>
push <local> <remote>
위 내용 참조


Ports and Networking

forward <local> <remote>
특정 local port를 remote port로 fowarding
Scheme
tcp:<portnum>
local:<UNIX domain socket name>
dev:<character device name>
jdwp:<pid>

ppp <tty> [parm]...
USB로 PPP 실행
<tty> : PPP stream을 위한 tty
[parm] : PPP option


Scripting

get-serialno
adb의 serial number 출력

get-state
adb의 state 출력 (device / offline)

wait-for-device
device가 online일 때 까지 command 실행 정지

ex : adb wait-for-device shell getprop (state가 device가 되면 shell getprop command 실행

Note : 완전히 boot 된 이후에 사용 가능한 install 등의 command를 함께 사용할 경우 wait-for-device는 device state만 확인하므로 fully boot 되지 않았을 경우 error 발생 가능


Server

start-server
adb server가 실행중인지 확인해서 running 상태가 아니면 실행

kill-server
adb server process를 종료


Shell

shell
target device 안에서 remote shell을 시작

shell [<shellCommand>]
target device 안에서 shell command를 실행하고 remote shell을 빠져나간다



Shell Command 실행

ADB는 ash shell을 제공하는데, ash shell의 실행 바이너리는 device 내부의 /system/bin 경로에 존재

adb [-d | -e | -s <serialNumber>] shell로 remote shell을 실행한 후에 shell을 종료하고 싶으면 Ctrl + D or exit 입력



UI/Application Exerciser Monkey

User event의 random stream을 생성해 device에서 실행시키는 tool (stress test 용도)

ex : adb shell monkey -v -p packageName 500 (500가지의 random stream)



Other Shell Commands

device의 /system/bin 경로의 file들을 살펴보거나, adb -help로 확인

dumpsys
system data의 dump를 표시

dumpstate
state의 dump를 file로 저장

logcat [<option>]...[<filter-spec>]
logging을 가능하게 하거나 화면에 표시

dmesg
kernel debugging message를 화면에 출력

start
device를 시작(재시작)

stop
device 종료



Using logcat Commands

adb logcat
단순히 전체 log를 보고싶은 경우 사용 또는 remote shell에서 logcat 실행

Android에서 모든 log message는 tag와 priority를 가지고 있음
tag : system component를 짧은 문자열로 표현 (ex : view system의 경우 "View")
priority (ordered from lowest to highest)
V (Verbose)
D (Debug)
I (Info)
W (Warning)
E (Error)
F (Fatal)
S (Silent)

logcat 실행 후에 나타나는 log message에서 tag와 priority가 첫 column에 priority/tag 형태로 표시

ex : I/ActivityManager( 585) : Starting activity : Intent { action = android.intent.action... }

logcat의 filter는 tag:priority 형태로 표현하는데 tag는 표시하려는 tag의 이름을 입력하면 되고 입력한 priority와 상위 priority의 log들을 표시

ex : adb logcat ActivityManager:I MyApp:D *:S
ActivityManager의 I(Info) level 이상, MyApp의 D(Debug) level 이상의 log들만 표시


default filter expression

환경변수 ANDROID_LOG_TAGS에 default로 사용할 filter expression을 setting 후에 export 해서 사용

ex : export ANDROID_LOG_TAGS="ActivityManager:I MyApp:D *:S"

Note : remote shell을 사용해서 logcat을 실행하고 있을 경우 export 되지 않음 (?)


Controlling Log Output Format

-v option을 사용해서 출력되는 log의 format 변경 가능

output format
brief : priority/tag, PID 표시 (default)
process : PID only
tag : priority/tag only
thread : process:thread, priority/tag only
raw : 다른 metadata field 없이 raw log message 표시
time : date, invocation time, priority/tag, PID
long : 모든 metadata filed와 message 표시

ex : adb logcat -v thread


Viewing Alternative Log Buffers

Android logging system은 log message들을 위해 여러 개의 circular buffer를 가지고 있고 default circular buffer가 모든 log를 보관하지 않기 때문에 다른 circular log buffer의 내용을 보고 싶을 때에는 -b option을 사용해서 circular buffer를 변경해주어야 한다.

Buffers
radio : radio/telephony 관련된 log message를 보관하는 buffer
events : related-events
main : main log buffer (default)

ex : adb logcat -b radio



Viewing stdout and stderr
Android에서는 default로 stdout과 stderr ouput을 /dev/null로 내보내는데, file에 쓰도록 변경 가능하고 이 경우 변경 전에 device를 stop 후 setprop shell command를 실행해서 redirection 설정해야 한다. device start 이후에는 stop 전까지 설정이 유지된다. default로 설정을 유지하고 싶다면, /data/local.prop에 기록

ex :
adb shell stop
adb shell setprop log.redirect-stdio true
adb shell start



Listing of logcat Command Options

-b <buffer>
load log buffer

-c
모든 log를 clear하고 빠져나간다

-d
log를 화면에 dump하고 종료

-f <filename>
log를 <filename>에 기록. default는 stdout

-g
특정 log buffer의 size를 출력하고 종료

-n <count>
rotated log의 최대값을 <count>로 설정. default는 4, -r option이 필요

-r <kbytes>
log file을 <kbytes>씩 rotate. default는 16, -f option 필요

-s
default filter를 silent로 설정

-v <format>
log format을 <format>으로 설정. default는 brief format.



[출처] : https://docs.google.com/View?id=dhj7zms7_0cfm752gq

공유하기 버튼

 
싸이월드 공감트위터페이스북
출처 : http://codemuri.tistory.com/693

일반 개발자들은 주로 USB 를 이용하여 adb 를 사용합니다. 하지만 TCP 를 이용하여 adb 를 이용한 디버깅을 해본 사람들은 많지 않을 것입니다. 그도 그럴 것이 Rooting 또는 Engineering 빌드 버전이 아니면 TCP 설정이 적용되지가 않기 때문에 실 장치를 가지고 테스트를 해보기가 쉽지 않겠죠.

이 글을 읽고 계신 분들은 Rooting 폰 또는 Engineering 빌드 버전의 장치를 가지고 있다고 가정하겠습니다.

TCP 를 이용하여 디버깅을 하면 USB 를 연결하지 않아도 adb 명령을 이용하여 app 을 설치하거나, logcat 의 로그를 모으는 등의 USB 와 연결된 것과 동일한 모든 adb 기능을 사용할 수 있습니다.

시중에 이러한 설정을 편리하게 해주는 (원클릭으로 Wireless 디버깅 on/off를 해주는) 유료 앱을 팔고 있던데, 이 App 은 알고보면 아무것도 아닙니다. Rooting 된 폰에서 TCP 디버깅 설정을 on/off 하는 것은 별로 어렵지 않기 때문이죠.

자 이제 adb 에서 제공하는 TCP 를 이용한 디버깅 설정방법을 알아 보겠습니다. 크게 매뉴얼 설정과 자동 설정 두가지로 나누어 살펴보겠습니다.

1. 매뉴얼 설정

먼저 안드로이드 장치의 디버깅 모드를 활성화 한 후 USB 를 연결합니다. TCP 를 이용한 Adb 를 설정하기 위해서는 adb shell 을 이용해야 하기 때문에 처음에 한번은 연결이 필요합니다. 이글 말미에 Rooting 된 폰에서 이를 자동화하는 방법을 소개하겠습니다. (구현은 제공하지 않고 숙제로 남겨두겠습니다.)

TCP 를 이용한 adb 디버깅을 하기 위해서는 현재 무선공유기등과 같은 Wifi 망이 이용가능해야 합니다.

1
$ adb devices

를 입력하여 현재 연결된 장치를 확인합니다.

그리고는 다음을 입력하여 adb 데몬(device 에서 adb 를 서비스하는 프로세스, adbd)의 설정을 변경합니다.

1
$ adb tcpip 5555

뒤의 5555 는 5555번 port 를 사용하겠다는 것을 의미합니다. 위와 같이 입력하면 adbd 데몬 프로세스(장치에서 실행되며 실질적인 adb 기능을 수행함)를 tcpip 모드로 재시작합니다. 이제 장치는 tcpip 를 연결할 수 있는 상태가 되었습니다.

(TCP 연결 성공을 체크하기 위해 기존에 연결된 USB 케이블을 해제하시기 바랍니다.)

PC 와 장치를 연결하기 위해서는 장치에 할당된 IP 를 확인해야 합니다. 이는
"설정 > 무선 및 네트워크 > Wi-Fi 설정" 에서 연결된 Wi-Fi 네트워크를 선택하면 확인할 수 있습니다.


저의 경우 192.168.0.4 입니다. 이제 PC 에서 장치로 연결하는 명령을 줍니다.

1
$ adb connect 192.168.0.4:5555

를 입력하면 연결 성공 메시지를 볼 수 있으며, 이렇게 연결된 이후에는 adb 명령을 동일하게 사용할 수 있습니다.

2. 자동 설정

원터치 Wireless 설정을 지원하는 방법을 살펴보겠습니다. 키포인트는 위에서 실행했던 "adb tcpip <port>" 명령을 어떻게 장치에서 수행하느냐 입니다.

그 명령은 아래와 같습니다.

1
2
3
4
$ su
# setprop service.adb.tcp.port 5555
# stop adbd
# start adbd

위 명령을 장치에서 실행하기만 하면 되는 것입니다. 위 예제와 같이 su 명령을 이용하여 root 권한을 얻게 되는데, 바로 이런 권한이 필요하기 때문에 production 장치에서는 수행할 수 가 없는 것입니다.

끝으로 안드로이드 App 에서 su 권한을 체크하는 방법을 소개해 드리며, 이 예제 코드와 tcp 설정 스크립트를 이용하면 시중에 돌고 있는 원터치 Wireless Adb 설정 App 을 개발할 수 있습니다. (이 예제도 당연 Rooting 된 폰에서만 root 권한을 얻습니다.) 
☞ su 명령이 수행된다고 가정을 하겠습니다. 만약 su 가 존재하지 않으면 su 는 검색하면 쉽게 구할 수 있습니다. 약간의 보안 방어막을 가한 super user 라는 app 도 있습니다.

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
Process p; 
try
   // Preform su to get root privledges 
   p = Runtime.getRuntime().exec("su");  
   
   // Attempt to write a file to a root-only 
   DataOutputStream os = new DataOutputStream(p.getOutputStream()); 
   os.writeBytes("echo \"Do I have root?\" >/system/sd/temporary.txt\n"); 
   
   // Close the terminal 
   os.writeBytes("exit\n"); 
   os.flush(); 
   try
      p.waitFor(); 
           if (p.exitValue() != 255) { 
              // TODO Code to run on success 
              toastMessage("root"); 
           
           else
               // TODO Code to run on unsuccessful 
               toastMessage("not root"); 
           
   } catch (InterruptedException e) { 
      // TODO Code to run in interrupted exception 
       toastMessage("not root"); 
   
} catch (IOException e) { 
   // TODO Code to run in input/output exception 
    toastMessage("not root"); 

이것만 가지고 어떻게 만들어요라고 되묻지 마시고, 한번 시도해 보시기 바랍니다. Just do it!


3. 기타

1
$ adb shell getprop

을 입력하면 현재 장치의 설정 정보를 볼 수 있습니다. 만약 tcpip 로 설정되어 있다면 getprop 에서도 그 목록이 나와야 합니다.

1
$ adb shell setprop service.adb.tcp.port -1

은 tcp 설정을 해제합니다.

참고:

su 권한을 크랙하는 방법은 아래 글을 참고하세요.


! 추가 확인 필요

아래 명령은 디폴트 설정을 변경한다고 합니다. (위에 설정은 장치가 리부팅되면 usb 모드로 돌아갑니다.) 이게 제대로 동작하는지 확인이 필요합니다. 안된다는 말도 있구요... 확인 요함.

1
$ adb shell setprop persist.adb.tcp.port 5555

관련글:

SAMSUNG, LG, Smart Phone Android Open Source

삼성 안드로이드폰 소스 입니다.
http://opensource.samsung.com/reception/reception_main.do?method=reception_list&menu_item=mobile


LG 안드로이드 소스 입니다.
http://opensource.lge.com

옵티머스 큐는 LU2300입니다

출처 : http://www.androidpub.com/index.php?mid=android_dev_info&search_target=title_content&search_keyword=%EB%A9%94%EB%89%B4&document_srl=1577289
안드로이드에  기본 내장되어 있는  QuickContactBadge 은   주소록에 한정해서 사용이 가능한듯합니다. 


http://developer.android.com/reference/android/widget/QuickContactBadge.html



검색해 보니까  같은 방식의 UI를  아무곳에나 적용기 가능한 소스를 공개한 사람이 있더군요.


http://www.londatiga.net/it/how-to-create-quickaction-dialog-in-android/



mina1.jpg mina2.jpg newqa.jpg theaters.jpg




위 는 예  스크린샷 입니다. 


수고하세요!

'Android > Tip&Tech' 카테고리의 다른 글

wiress 를 이용한 adb 통신  (0) 2011.10.19
삼성,LG 오픈소스  (0) 2011.10.16
[팁]android pdf 또는 hwp 소스 실행하기  (0) 2011.10.02
안드로이드 만보기 소스  (1) 2011.09.28
[펌]custom seek bar 만들기  (3) 2011.09.26

Intent intent = new Intent();
  intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  intent.setAction(android.content.Intent.ACTION_VIEW);
  intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
  if (file.getName().endsWith(".pdf")){
 intent.setDataAndType(Uri.fromFile(file), "application/pdf");
  }else if (file.getName().endsWith(".hwp")){
intent.setDataAndType(Uri.fromFile(file), "application/hwp");
  }
  try{
   startActivity(intent);
  }catch(ActivityNotFoundException e){
   util.showLongToast("해당파일을 실항할 수 있는 어플리케이션이 없습니다.\n파일을 열 수 없습니다.");
   e.printStackTrace();
  }

안녕하세요~ 이번에 안드로이드에 대해 독학으로 공부하고 있는 학생입니다.

 

기본 지식이 많이 없는 편이라 이렇게 질문을 올리게 되었습니다.

 

귀찮더라두 끝까지 봐주시고 저에게 좋은 스승이 되어주세요

 

질문은 가속도 센서를 이용해서 만보기를 만들어 볼라고 하는데요

 

여차여차 소스를 구하게 되었습니다. 그래서 이것을 토대로 공부를 하고 싶어하는데요

 

소스들이 무엇을 의미하는지 몰라서 이렇게 질문을 하게 되었습니다 스승님들 저에게 가르침을 주세요~

 

자세한 설명 부탁드리겠습니다!! (__)꾸벅!

 

 

 

[MainActivity.java]

 

package com.androday.test;

import! android.app.Activity;


import! android.content.BroadcastReceiver;
import! android.content.Context;
import! android.content.Intent;
import! android.content.IntentFilter;
import! android.os.Bundle;
import! android.view.View;
import! android.view.View.OnClickListener;
import! android.widget.Button;
import! android.widget.TextView;
import! android.widget.Toast;

public class MainActivity extends Activity {
   
 
    Button btnStopService;
   
    Intent intentMyService;       

    BroadcastReceiver receiver;
   
    boolean flag = true;
   
    Toast toast;
   
    TextView CountText;
   
    String serviceData;
   
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);     
          
        intentMyService = new Intent(this,MyServiceIntent.class);   
        //실행되기 원하는 서비스 등록
               
      
        receiver = new MyMainLocalRecever();       
       
        CountText = (TextView)findViewById(R.id.TextView01);      
              
        btnStopService = (Button)findViewById(R.id.btnStopService);
        //서비스 중지
       
       
        btnStopService.setOnClickListener(new OnClickListener() {
   
   @Override
   public void onClick(View v) {
    
    
    if(flag)
    {
     
     
     btnStopService.setText("Stop !!");
     
     // TODO Auto-generated method stub
     try{
      
      IntentFilter mainFilter = new IntentFilter("com.androday.test.step");       
           
      registerReceiver(receiver, mainFilter);
      
      startService(intentMyService);     
      //txtMsg.setText("After stoping Service:\n"+service.getClassName()); 
      Toast.makeText(getApplicationContext(), "서비스 시작", 1).show();
     }
     catch (Exception e) {
      // TODO: handle exception
      Toast.makeText(getApplicationContext(), e.getMessage(), 1).show();
     }
    }
    
    
    else
    {

    
     btnStopService.setText("Go !!");
     
     // TODO Auto-generated method stub
     try{
      
      unregisterReceiver(receiver);
      
      stopService(intentMyService);      
      
      Toast.makeText(getApplicationContext(), "서비스 중지", 1).show();
      //txtMsg.setText("After stoping Service:\n"+service.getClassName());     
     }
     catch (Exception e) {
      // TODO: handle exception
      Toast.makeText(getApplicationContext(), e.getMessage(), 1).show();
     }     
    }  
    
    flag = !flag;
    
   }
  });
       
        }
   
   
    class MyMainLocalRecever extends BroadcastReceiver {

     @Override
     public void onReceive(Context context, Intent intent) {
      // TODO Auto-generated method stub
      
      serviceData = intent.getStringExtra("serviceData");
      
      CountText.setText(serviceData);
      
      Toast.makeText(getApplicationContext(), "Walking . . . ", 1).show();    

     }

    }
   
   
   
}


 

 

[MyServiceIntent.java]

 

package com.androday.test;

import! android.app.Service;


import! android.content.Intent;
import! android.hardware.Sensor;
import! android.hardware.SensorEvent;
import! android.hardware.SensorEventListener;
import! android.hardware.SensorManager;
import! android.os.IBinder;
import! android.util.Log;

public class MyServiceIntent extends Service implements SensorEventListener  {
 
 
 int count = values.Step;
 
 private long lastTime;
    private float speed;
    private float lastX;
    private float lastY;
    private float lastZ;
  

    private float x, y, z;
    private static final int SHAKE_THRESHOLD = 800;
  

    private static final int DATA_X = SensorManager.DATA_X;
    private static final int DATA_Y = SensorManager.DATA_Y;
    private static final int DATA_Z = SensorManager.DATA_Z;
  

    private SensorManager sensorManager;
    private Sensor accelerormeterSensor;
 
   
 @Override
 public IBinder onBind(Intent intent) {
  // TODO Auto-generated method stub
  return null;
 }

 @Override
 public void onCreate() {
  // TODO Auto-generated method stub  
  super.onCreate();
  Log.i("MyServiceIntent","Service is Create"); 
  
   sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
         accelerormeterSensor = sensorManager
                 .getDefaultSensor(Sensor.TYPE_ACCELEROMETER);    

     }    
 
 @Override
 public void onStart(Intent intent, int startId) {
  // TODO Auto-generated method stub
  super.onStart(intent, startId);
  Log.i("MyServiceIntent","Service is started"); 
  

        if (accelerormeterSensor != null)
            sensorManager.registerListener(this, accelerormeterSensor,
                    SensorManager.SENSOR_DELAY_GAME);
 }

 @Override
 public void onDestroy() {
  // TODO Auto-generated method stub
  super.onDestroy();    
  Log.i("MyServiceIntent","Service is destroy");  
  
    if (sensorManager != null)
             sensorManager.unregisterListener(this);

 }

 @Override
 public void onAccuracyChanged(Sensor sensor, int accuracy) {
  // TODO Auto-generated method stub
  
 }

 @Override
 public void onSensorChanged(SensorEvent event) {
  // TODO Auto-generated method stub
     if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
             long currentTime = System.currentTimeMillis();
             long gabOfTime = (currentTime - lastTime);
   

             if (gabOfTime > 100) {
                 lastTime = currentTime;
   

                 x = event.values[SensorManager.DATA_X];
                 y = event.values[SensorManager.DATA_Y];
                 z = event.values[SensorManager.DATA_Z];
   

                 speed = Math.abs(x + y + z - lastX - lastY - lastZ) / gabOfTime * 10000;

   

if (speed > SHAKE_THRESHOLD) {
                  
Log.e("Step!", "SHAKE");
                  
Intent myFilteredResponse = new Intent("com.androday.test.step");
                  
values.Step = count++;
                
String msg = values.Step + "" ;
                  myFilteredResponse.putExtra("serviceData", msg);
                  
                  sendBroadcast(myFilteredResponse);

                 }
                 lastX = event.values[DATA_X];
                 lastY = event.values[DATA_Y];
                 lastZ = event.values[DATA_Z];
             }
         }

 } 

}

 

[values.java]

 

package com.androday.test;

public class values {

 public static int Step = 0;
}

 

 

스승님들 좋은 가름침 부탁드리겠습니다!!

출처 : http://www.mokasocial.com/2011/02/create-a-custom-styled-ui-slider-seekbar-in-android/

Create a Custom-Styled UI Slider (SeekBar) in Android

MokaSocial-Blog-Headers-Slider

An Android slider (or a SeekBar as it’s called in the Android world) is a pretty slick UI tool which we recently used in our Call Your Folks! app as a means of choosing a reminder frequency between one day and three months.

I’ll walk you through creating a custom-styled seekbar for your Android application using nothing but a few XML and image drawables.

In this tutorial, I assume that you know how to implement a SeekBar in your app; if you don’t, check out the Android API demos, specifically SeekBar1.java and seekbar_1.xml.

Step 1: Create Your Image Drawables (9-Patch)

Before creating any XML drawables, make sure you create the image drawables (including one 9-patch drawable) needed for the seekbar background, handle, and progress sections. The 9-patch drawables will be put to use by the XML drawables in the steps below.

Create the following drawables and place them in your /res/drawable/ folder:

Step 2: SeekBar Progress Drawable

Now create an XML drawable for the Android seekbar progress (the blue-striped section in the example), call it seekbar_progress_bg.xml, and place it in your /res/drawable/ folder:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="utf-8"?>
 <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <clip>
            <shape>
                <gradient
                    android:startColor="#FF5e8ea3"
                    android:centerColor="#FF32a0d2"
                    android:centerY="0.1"
                    android:endColor="#FF13729e"
                    android:angle="270"
                />
            </shape>
        </clip>
    </item>
    <item>
        <clip>
        <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
            android:src="@drawable/stripe_bg"
            android:tileMode="repeat"
            android:antialias="true"
            android:dither="false"
            android:filter="false"
            android:gravity="left"
        />
        </clip>
    </item>
</layer-list>

The above XML first draws a semi-transparent, blue gradient, then layers the semi-transparent stripe image on top of the gradient. The highlighted line of code (line 20) refers to the stripe (semi-transparent) image inside your drawable folder, created in Step 1.

For more information on creating custom shapes via XML, check out the Android drawable resources docs, specifically the bitmap and shape sections.

Step 3: SeekBar Background Drawable

Next create the main seekbar progress drawable; it’ll assign a drawable to the seekbar progress and secondaryProgress actions inside your seekbar. Name your drawable something like seekbar_progress.xml, place it inside your /res/drawable/ folder:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@android:id/background">
        <nine-patch
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:src="@drawable/seekbar_background"
            android:dither="true"
         />
    </item>
    <item android:id="@android:id/secondaryProgress">
        <clip>
            <shape>
                <gradient
                    android:startColor="#80028ac8"
                    android:centerColor="#80127fb1"
                    android:centerY="0.75"
                    android:endColor="#a004638f"
                    android:angle="270"
                />
            </shape>
        </clip>
    </item>
    <item
        android:id="@android:id/progress"
        android:drawable="@drawable/seekbar_progress_bg"
    />
</layer-list>

The first bit of highlighted code above (line 8) is referring to the seekbar background image (9-patch drawable) created in Step 1 and (line 29) is referring to the drawable you created above in Step 2.

Step 4: Bringing it all together…

At this point, all you need to do is call your seekbar_progress drawable when declaring your seekbar:

01
02
03
04
05
06
07
08
09
10
<SeekBar
        android:id="@+id/frequency_slider"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:max="20"
        android:progress="0"
        android:secondaryProgress="0"
        android:progressDrawable="@drawable/seekbar_progress"
        android:thumb="@drawable/seek_thumb"
/>

The two lines of highlighted code are setting the progress and thumb drawables for the SeekBar item. The @drawable/seekbar_progress refers to the XML drawable created in the previous step.

See it in action!

For a “live demo” of the seekbar bar being used, download our Call Your Folks! app.

For more information on the Android SeekBar, check out the Android docs.


출처 : http://www.androidside.com/bbs/board.php?bo_table=B52&wr_id=7278
아래 싸이트를 보고 이미지만 편집해서 해봤는데요
nine-patch이미지 만드는게 쉽지 않네요.
리소스를 잘 만들지 못해서 깔끔하지가 않지만
찾으시는 분이 많은 것 같아서 해봤습니다.
커스텀 토글 만드실 분은 아래 링크 참고 하셔서 만드시면 되겠습니다.
그리고 이렇게 토글로 만들면 이미지만 변경되는 것일 뿐 슬라이드 처리가 되지 않기 때문에
seekbar로 만들면 더 효과가 비슷할 것으로 보이네요. 위에 링크 걸어놓은 싸이트로 들어가시면 custom seekbar 만드는 법도 가능합니다

- 화면 해상도 알아내기 -

방법 #1
 
1 DisplayMetrics metrics = new DisplayMetrics();
2 getWindowManager().getDefaultDisplay().getMetrics(metrics);
3   
4 int ScreenWidth  = metrics.widthPixels
5 int ScreenHeight = metrics.heightPixels


방법 #2
 
1 WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
2 Display dsp = wm.getDefaultDisplay();
3   
4 int height = dsp.getHeight();
5 int width = dsp.getWidth();

- 화면 상태 확인하기 -

현재 화면이 가로인지 새로인지 확인하는 방법은 화면 해상도를 확인하는 방법도 있겠지만 API 에서 제공하는 함수로도 확인 할 수 있다. 가로 혹은 세로 해상도가 같은 경우에는 API 함수를 이용하는 것이 보다 정확할 것이다.

Android 2.1 이하에서는 getOrientation() 만 동작하며 Android 2.2 이상에서는 getOrientation() 과 getRotation() 이 동작을 한다.

Android 2.1 이하
 
1 WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
2 Display disp = wm.getDefaultDisplay();
3   
4 int orientation = disp.getOrientation(); // Android 2.1
5 Log.i( "Orientation", "orientation : " + orientation );            

Android 2.2 이상
 
01 WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
02 Display disp = wm.getDefaultDisplay();
03   
04 int rotation = disp.getRotation(); // Android 2.2
05 Log.i( "Rotation", "rotation : " + rotation );
06   
07 switch ( rotation )
08 {
09 case Surface.ROTATION_0: 
10     Log.i( "Roation", "Portrait : 0" ); 
11     break;
12       
13 case Surface.ROTATION_90:
14     Log.i( "Roation", "Landscape : 90" );
15     break;
16       
17 case Surface.ROTATION_180:
18     Log.i( "Roation", "Portrait : 180" );
19     break;
20       
21 case Surface.ROTATION_270:
22     Log.i( "Roation", "Landscape : 270" );
23     break;
24 }    
출처 : http://kpbird.blogspot.com/2011/08/android-check-application-is-running.html

Android: Check application is running ?

| Wednesday, August 17, 2011
Android has different application lifecycle, Many times user press Home hardware button and application goes in background, Application is still running but it's in background, Now We want to identify that application is running in background or not. It require when we don't want to create new instance of Activity. Android SDK provide class named ActivityManager. Using ActivityManager we can check application is running in background.

Here is the simple code for the same. you just need to change package name as per your requirement.

01 ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
02  // get the info from the currently running task
03 List < ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(1);
04   
05 Log.d("current task :", "CURRENT Activity ::" + taskInfo.get(0).topActivity.getClass().getSimpleName());
06   
07 ComponentName componentInfo = taskInfo.get(0).topActivity;
08 //if  app is running
09 if(componentInfo.getPackageName().equalsIgnoreCase(*Package Name*))
10 {
11  //do the implementation for if your app is running
12 }

Reference:
http://developer.android.com/reference/android/app/ActivityManager.html

자답입니다.

출처 : http://blog.naver.com/kkamci25?Redirect=Log&logNo=10098212677

각 위젯에서 제공하는 setTextSize Method는 2가지를 제공하고 있다.


1. Pixel 값으로 설정하는 방법

setTextSize(float size) : size는 pixel value를 입력하면 된다.


2. Unit Type을 함께 설정하는 방법

setTextSize(int unit, float size)

unit 값은 TypedValue class에 정의되어 있는 값으로 다음과 같은 값을 갖는다.


/** {@link #TYPE_DIMENSION} complex unit: Value is raw pixels. */
public static final int COMPLEX_UNIT_PX = 0;
/** {@link #TYPE_DIMENSION} complex unit: Value is Device Independent
* Pixels. */
public static final int COMPLEX_UNIT_DIP = 1;
/** {@link #TYPE_DIMENSION} complex unit: Value is a scaled pixel. */
public static final int COMPLEX_UNIT_SP = 2;
/** {@link #TYPE_DIMENSION} complex unit: Value is in points. */
public static final int COMPLEX_UNIT_PT = 3;
/** {@link #TYPE_DIMENSION} complex unit: Value is in inches. */
public static final int COMPLEX_UNIT_IN = 4;
/** {@link #TYPE_DIMENSION} complex unit: Value is in millimeters. */
public static final int COMPLEX_UNIT_MM = 5;

'Android > Tip&Tech' 카테고리의 다른 글

android 해상도 및 가로/세로 알아내기  (1) 2011.09.26
[펌]Android: Check application is running  (0) 2011.09.21
c2dm php 팁#1  (3) 2011.09.21
크롬용 웹 개발툴 설치 주소.  (0) 2011.09.20
[펌]안드로이드 C2DM 소스  (0) 2011.09.20
출처 : http://blog.naver.com/yjsplay2002?Redirect=Log&logNo=50109135158

어플 -> c2dm -> 어플

 

다음과같은경우 구글 검색으로 얻을수 있는 소스로 수행해보면

 

한글 수신이 문제 없다.

 

 

하지만

 

어플 -> 별도서버 -> c2dm -> 어플

 

다음과 같이 서버로 메시지를 전송하고,

 

서버에서 c2dm 으로 전송하는 방법에서 한글이 보내지지 않았다.

 

http://www.xhost.co.kr/bbs/?id=iphone,16

 

다음 링크에서 curl 을 이용하여 c2dm 으로 전송하는 소스를 이용할때

 

한글이 전송 안되는 현상 발견

 

파일 문자셋을 바꾸고 별별짓을 해도 안됨..

 

그러다가

 

$ch = curl_init();   
   
curl_setopt($ch, CURLOPT_URL, "https://www.google.com/accounts/ClientLogin");   
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);   
   
$data = array('accountType' => 'HOSTED_OR_GOOGLE',   
'Email' => '아이디',   
'Passwd' => '비번',   
'source'=>'test-1.0',   
'service'=>'ac2dm');   
    
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);   
curl_setopt($ch, CURLOPT_POST, true);   
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);   
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);   
 
$result = curl_exec($ch); 
$auth = substr(strstr($result, "Auth="), 5);  
$auth = substr($auth, 0, strlen($auth)-1); 
 
curl_setopt($ch, CURLOPT_URL, "https://android.apis.google.com/c2dm/send"); 
 
$data = "registration_id=등록아이디"."&collapse_key=1"."&data.msg=메세지"; 
curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 
 
$headers = array( 
    "Content-Type: application/x-www-form-urlencoded", 
    "Content-Length: ".strlen($data), 
    "Authorization: GoogleLogin auth=$auth" 
); 
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);  
 
$result = curl_exec($ch); 
echo $result."\n"; 
 
curl_close($ch); 

 

 

위의 메세지를 담는 부분을 인코딩하니 해결..

 

다음과 같이 바꿔준다.

 

$data = "registration_id=등록아이디"."&collapse_key=1"."&data.msg=".urlencode($메시지); 

 

 

저같이 고생하시는분들 없길 바라며...

 

원래 한글을 urlencode 하면 이상한 문자들이 나오는데,

 

c2dm 에서 재변환 하는 과정을 수행해 주나보다..

 

 

c2dm 전송 php 소스를 공개하신 로빈아빠님 감사드립니다.


원본이 아니었군요...;;

 

민상K 님 감사드립니다.


출처 : http://minsangk.com/blog/main/116


-------------------------------------------------------------------------------------------------------------------------------------------


추가사항 


위으 소스로 push 를 빠르게 보내면 20개쯤 보내지고 잘 안보내지는 현상이 발생한다.


이유는 collapse_key=1


이것 때문인데


구글서버에서 이 키가 같은 값으로 계속오면


중복 메시지로 판단하고 연속으로 올 경우 무시해 버린단다.


이 키를 랜덤 숫자로 바꿔주면 매우 빠르게 보내도 처리해 준다.


srand((double)microtime()*1000000);

$collapse_key = rand(1,99);


$data = "registration_id=$phoneID"."&collapse_key=$collapse_key"."&data.msg=".urlencode($sendText);


이부분을 반드시 수정하여 사용하시길...

Android Cloud to Device Messaging
[이 포스트는 이 기능을 구현하는데 기여한 Wei Huang 에 의해 작성되었습니다. — Tim Bray]

새롭게 발표된 안드로이드 2.2 에서, 우리는 Android Cloud to Device Messaging (C2DM) 서비스를 추가하였습니다. 이 서비스는 개발자들이 서버와 모바일 어플리케이션간에 데이타를 쉽게 싱크할 수 있도록, 서버쪽 에서에서 안드로이드 폰 상의 어플리케이션으로 데이타를 손쉽게 전달할 수 있도록 도와줍니다.

 유용한 휴대폰 어플리케이션들은 대부분 사용자가 인터넷과 연결되도록 유지합니다. 이를 위해 전통적으로 많은 어플리케이션들은 주기적으로 데이터를 가져오기 위해 폴링 방식을 사용합니다. 예를들어 POP 이메일 클라이언트의 경우 15분 마다 이메일 서버와 연결되어 새로운 이메일을 가져오도록 구현될 수 있습니다. 이러한 폴링 방식은 비교적 구현하기가 용이하고, 대부분의 경우 잘 작동합니다. 하지만, 어떤한 주기로 폴링 작업을 수행할지 결정하는 것은 조금 애매한 구석이 있습니다. 폴링을 너무 자주하게 되면, 새로운 데이타가 없는데도 불구하고 불피요한 작업이 수행되며 서버와 네트워크에 부하를 줄 수 있습니다. 너무 드물게 폴링을 수행하면 어플리케이션이 갖고 있는 데이터가 전혀 갱신되지 않는 것 처럼 느껴질지도 모릅니다. 특히나 모바일 디바이스에서 효율적으로 폴링 작업을 수행하는 것은 중요한 문제입니다. 왜냐하면 폴링 작업은 귀중한 네트워크 밴드위스와 베터리를 소모시키기 때문입니다.

 폴링 방식을 사용하는 대신, 비동기적으로 클라이언트에 메세지를 푸쉬해주는 서버를 갖추는 것은 어플리케이션이 효율적으로 새로운 데이터를 전달 받을 수 있는 훨씬 좋은 선택이 될 수 있습니다. 하지만 훌륭한 푸쉬 솔루션을 구현하는 것은 어려운 일이며, 서버측과 특정한 연결을 유지하고 있어야 하는 오버헤드가 발생합니다. 특히 안드로이드폰과 같은 모바일 디바이스에서 이를 구현하는데는 네트워크 상태(고르지 못한 네트워크 커버리지, 무선망 상황이 좋지 않아 커넥션을 시도해도 타임아웃에 걸리고 마는 좀비 커넥션등) 에관한 고려가 필요하기 때문에, 교묘한 기술이 필요합니다. 

 G-메일, 주소록, 캘린더와 같은 안드로이드용 구글 어플리케이션은 데이터를 항상 최신으로 유지하기 위해 이미 푸시 방식을 사용하고 있습니다. 안드로이드 2.2 부터 C2DM 를 사용하면 서드파티 개발자들도 구글 어플리케이션과 동일한 서비스를 사용할 수 있습니다.

C2DM 에 대해서 몇 가지 기본적으로 알아야 하는 사항이 있습니다. 
  • 안드로이드 2.2 버전이 필요합니다. 
  • C2DM 은 '구글 서비스'를 사용합니다. 이 서비스는 안드로이드 마켓을 사용하는 모든 디바이스에 존재합니다.
  • C2DM 은 '구글 서비스' 를 위해 이미 존재하는 커넥션을 사용합니다.
  • C2DM 은 안드로이드 폰 상에서 사용자가 구글 계정으로 로그인 해야 사용이 가능합니다.
  • C2DM은 서드파티 서버가 간단한 메세지를 자신들의 어플리케이션으로 전달하는 것을 허용합니다.
  • C2DM 서비스는 대량의 컨텐츠를 푸쉬하도록 설계되지 않았습니다. 대신 특정 어플리케이션에게 새로운 데이타가 있음을 '쿡' 하고 알려 주고, 어플리케이션이 해당 서버에 접속해서 데이타를 다운로드 받을 수 있도록 하는데 사용되어야 합니다. 
  • 어플리케이션은 메세지를 받기 위해 작동중일 필요가 없습니다. 시스템은 전달해야할 데이타가 도착하는 경우에, 브로드캐스트 인텐트를 이용해 해당 어플리케이션을 깨울 것 입니다. 따라서, 어플리케이션은 적절하게 브로드캐스트 리시버와 Permission 을 설정해야 합니다.
  • 데이타 메세지를 전달 받기 위해 사용자 인터페이스가 필요하지는 않습니다. 물론 어플리케이션이 원한다면 알림창에 노티피케이션을 날릴 수도 있을 것 입니다.

C2DM API 를 사용하는 것은 쉽습니다. C2DM 은 아래와 같이 작동합니다.
  • C2DM 을 사용하기 위해 디바이스 상의 어플리케이션은 우선 구글에 등록해 Registration ID 를 발급 받아야 합니다. 해당 ID 를 자신의 서버에 전달해야 합니다. 
  • 만일 자신의 서버가 푸시하고 싶은 메세지가 있을 경우, 메세지를 HTTP 를 통해 구글의 C2DM 서버에 전달합니다. 
  • C2DM 서버는 메세지를 디바이스에 라우팅 하고, 디바이스는 브로드캐스트 인텐트를 어플리케이션에 전달 할 것 입니다. 
  • 타켓 어플리케이션은 브로드 캐스트 인텐트를 통해 깨어나고 메세지를 처리합니다. 
  • 어플리케이션은 사용자가 더이상 푸시 서비스를 받고싶지 않을 경우 등록을 취소할 수 있습니다. 
 거의 다 되었습니다. 개발자에게 필요한 것은 HTTP를 전달할 수 있는 서버와 Intent API 를 어떻게 사용해야하는지 알고 있는 안드로이드용 어플리케이션 뿐입니다. 아래는 간단한 예제 코드입니다.

// Use the Intent API to get a registration ID
// Registration ID is compartmentalized per app/device
Intent regIntent = new Intent(
        "com.google.android.c2dm.intent.REGISTER");
// Identify your app
regIntent.putExtra("app",
        PendingIntent.getBroadcast(this /* your activity */, 
            0, new Intent(), 0);
// Identify role account server will use to send
regIntent.putExtra("sender", emailOfSender);
// Start the registration process
startService(regIntent);

Registration ID 는 개발자의 어플리케이션으로 com.google.android.c2dm.intent. REGISTRATION 이라는 액션값을 갖는 브로드 캐스 인텐트를 통해 전달되어 집니다. 다음은 Registration ID 를 전달 받기위한 예제 코드 입니다.

// Registration ID received via an Intent
public void onReceive(Context context, Intent intent) {
  String action = intent.getAction();
  if (“com.google.android.c2dm.intent.REGISTRATION”.equals(action)) {
    handleRegistration(context, intent);
  }
}

public void handleRegistration(Context context, Intent intent) {
  String id = intent.getExtra(“registration_id”);
  if ((intent.getExtra(“error”) != null) {
    // Registration failed.  Try again later, with backoff.
  } else if (id != null) {
    // Send the registration ID to the app’s server.
    // Be sure to do this in a separate thread.
  }
}

 서버측을 살펴보면, 개발자의 서버는 C2DM 서버와 통신하기 위해 ClientLogin Auth 토큰을 가져야합니다. 토큰을 이용해서, 서버가 디바이스에 메세지를 푸시하고 싶을 때, 다음과 같은 인증된 HTTP Post 를 통해 메세지를 전달 할 수 있습니다. 
  • Authorization: GoogleLogin auth=<auth token>
  • Registration ID 와 키/벨류 쌍으로 이루어진 데이타, Google C2DM 서버에서 동일한 키값을 갖고 있는 오래된 메세지를 가로채기 위해 사용되는 'Collapse Key' 등몇 가지 옵셔널한 파라매터들을 포함하도록 인코딩된 URL.
 개발자가 C2DM 서비스를 사용하면, 골치아픈 모바일 데이타 커넥션을 직접 처리할 필요가 없으며, 사용자가 인터넷과 연결되어있는지 신경쓸 필요도 없습니다. (Airplane 모드와 같이). C2DM 은 서버 스토어에 메세지들을 보관하고, 디바이스가 온라인 상태로 될 때 해당 메세지를 전달합니다. 기본적으로 개발자는 견고한 푸시서비스를 위해 온갖 복잡하고 어려운 일들을 모두 구글에게 맡길 수 있습니다. 어플리케이션은 구글이 이미 구축하고 검증한 푸시 서비스의 이점을 취하고, 인터넷에 연결되어진 상태로 유지될 수 있습니다. 무엇보다도 좋은 것은 여러분이  배터리 소모에대해 비난을 받지 않아도 됩니다.

어떻게 C2DM 이 가능한 어플리케이션을 만들 수 있는 가에 관한 정보는 Code Lab 에 있으며, 서비스 일반 릴리즈가 다가올 수록 보다 다양한 정보가 공개될 것 입니다. 

'Android > Tip&Tech' 카테고리의 다른 글

c2dm php 팁#1  (3) 2011.09.21
크롬용 웹 개발툴 설치 주소.  (0) 2011.09.20
[팁]Merge layout 에 관한 팁  (0) 2011.09.16
[펌]안드로이드 apk decompile 하기 완결판  (0) 2011.09.14
[펌] Android Cookkie 와 Session 관련  (1) 2011.09.08

http://blog.naver.com/man8408/110111707630

* 안드로이드을빨리이해하기위한방법

1. OpenSource활용

- http://code.google.com/hosting/

- http://google.com/codesearch

 

2. Reverse Engineering 활용하여 학습하기

- 자바 클래스 리버싱

 

- 안드로이드 실행파일 구조와 리버싱

 

 

 

* APK파일 디컴파일(Decompile)하는 방법

1. 디컴파일을 위한 툴 설치

1.ApkTool

- 다운로드 : http://code.google.com/p/android-apktool/downloads/list

- 압축풀기 : android-sdk가 설치된 platform-tools디렉토리안에 apktool디렉토리를 만들어 압축을 푼다.

apktool1.4.1.tar.bz2

apktool-install-windows-r04-brut1.tar.bz2

 

2.Dex2Jar

- 다운로드 : http://code.google.com/p/dex2jar/downloads/list


- 압축풀기 : android-sdk가 설치된 platform-tools디렉토리안에 dex2jar디렉토리를 만들어 압축을 푼다.

dex2jar-0.0.7.10-SNAPSHOT.zip

 

3.Java Decompiler

- 다운로드 : http://java.decompiler.free.fr/?q=jdgui

- 압축풀기 : 실행하기 편한 곳에 압축을 풀어 놓는다.

 

2. 환경변수 잡기

- adb, apktool, dex2jar 명령어를 사용하기 위한 환경변수를 잡는다.

%ANDROID_SDK%\platform-tools

%ANDROID_SDK%\platform-tools\apktool

%ANDROID_SDK%\platform-tools\dex2jar

 

 

3. apk 파일 추출

- 폰에 설치된 모든 패키리를 리스트로 보인다.

 

- 리스트 중에 디컴파일 할 APK파일을 정한다.

 

- APK파일을 추출한다. (adb shell을 종료 후 수행한다.)

 

4. ApkTool 실행 (java파일 외 xml, image, db등을 추출할 수 있다.)

- apktool 명령어를 사용하여 apk파일에 있는 파일을 디코딩하여 out폴더에 내보낸다.

 

- xml파일을 열어 내용을 확인한다.

 

5. Dex2Jar 실행 (Java파일을 추출할 수 있다.)

- apk파일의 확장자를 zip으로 변경한다.

 

- 추출한 zip파일의 압축을 풀어 classes.dex 파일을 추출한다.

 

- Dex2Jar를 실행한다.

 

- Dex2Jar를 실행하면 아래 jar파일이 생긴다.

 

6. JD-GDI 실행

- JD-GDI실행하여 classes.dex.dex2jar파일을 열어 소스를 분석한다.

 

7. Enterprise Architect를 이용하여 클래스 다이어그램으로 분석한다.

- 다운로드 : http://www.sparxsystems.com.au/products/ea/trial.html

 

- 설치

 

- 실행

 

- Java Decompiler에서 open할 파일을 추출한다.

 

- zip파일을 압축을 푼다.

 

- Enterprise Architect에서 classes.dex.dex2jar.src디렉토리를 import 한다.

 

- 클래스 다이어그램을 보고 분석한다.

 

 

 

-----------------------------------------------------------------------------------------------------------------------

 

 

제 11회 한국자바개발자 컨퍼런스에서 트랙1, 3번째 세션에서 Reverse Engineering, 안드로이드 학습이란 주제로 발표를 진행합니다.

리버싱이 무엇인지,  안드로이드 리버싱을 통해서 어떻게 학습을 할 수 있는지 다양한 도구와 팁들을 소개합니다.

학습을 목적으로 리버스엔지니어링이 허용되지만 기술을 복제 유혹을 받을 수도 있습니다.

법적이나, 윤리적으로 문제가 된다는 것을 명심하고, 공부한 내용을 서로 공유하며 미소 지을 수 있는 개발문화가 되길 바래봅니다. :D

발표자료와 함께 사용된 동영상 공유합니다.

 

발표자료 : Reverse Engineering, 안드로이드 학습

 

자바 클래스 리버싱

 

안드로이드 실행파일 구조와 리버싱

 

Reverse Engineering 활용한 학습 예제

  1. 분석할 앱선정과 APK 파일 추출
  2. 디컴파일 후 분석
  3. 클래스 다이어그램으로 - Enterprise Architect
  4. 의존성 검사를 통해 쉽게 - xDepend

'Android > Tip&Tech' 카테고리의 다른 글

[펌]안드로이드 C2DM 소스  (0) 2011.09.20
[팁]Merge layout 에 관한 팁  (0) 2011.09.16
[펌] Android Cookkie 와 Session 관련  (1) 2011.09.08
webview 에 배경화면 설정  (0) 2011.09.07
[펌]깔끔한 팝업창 만들어보기  (0) 2011.09.07
출처 : http://blog.suromind.com/27

웹뷰를 이용한 간단한 어플을 하나 만들었는데.. 세션이 안되서 삽질을 많이 했습니다.
구글링을 통해 소스는 많이 있지만 자바코드에서 특정 웹페이지를 호출해서 session.getId() 를 찍어본 결과
호출 할 때 마다 다른 값이 나오더군요..뭐 근데.. 방법은 의외로 간단한 거였더군요.. 어쩌면 당연한 거였다는..

일단은 session.getId() 값이 같은 값이 나와야 합니다.. 이 값이 계속 바뀐다면 아무리 삽질을 한들 안되겠지요..
HttpClient httpclient =  new DefaultHttpClient();  이부분을 멤버변수로 바로 선언해 버립니다...
보통 다른 소스들은 호출할 때 마다 계속 재 생성하는데.. 재생성을 안하니 유지가 됩니다..ㅋ 그리고 JSESSIONID를 쿠키로 구우면 OK...

setSyncCookie() 안에 들어 있는 코드는 구글링을 통해 얻은 소스입니다.. 많이들 보셨을듯..하네요.. 바뀐부분은   List<Cookie> cookies = ((DefaultHttpClient)httpclient).getCookieStore().getCookies();
이부분인데.. HttpClient 는 getCookieStroe 메소드가 없어서 위처럼 형변환 해줬습니다..

쿠키로 구을 때 Log 찍어보시면 token값과 JSESSIONID도 같이 구워집니다..
그리고 CookieSyncManager.getInstance().startSync(); 가 되면
웹뷰와 연동 됩니다..  이렇게 안하면 웹뷰에서 접속하는 것과 HttpClient에서 접속하는 것이 따로 놀더군요...

응용해 보시길 바랍니다.. 더 좋은 방법이 있다면 조언해주시구요^^


public class AndroidTet extends Activity {
public static WebView webview;
public HttpClient httpclient =  new DefaultHttpClient();  //멤버변수로 선언
public CookieManager cookieManager;
public String domain = "http://192.168.0.44";
public void onCreate(Bundle savedInstanceState) {
   ...
        CookieSyncManager.createInstance(this);
        cookieManager = CookieManager.getInstance();
        CookieSyncManager.getInstance().startSync();
   ...
        setSyncCookie();
   ...
public void onResume() {
        super.onResume();
        CookieSyncManager.getInstance().startSync();
}

public void onPause() {
        super.onPause();
       
        if (CookieSyncManager.getInstance() != null) {
        CookieSyncManager.getInstance().stopSync();
        }
}
protected void onDestroy() {
        super.onDestroy();
       
        if (cookieManager != null) {
        cookieManager.removeAllCookie();
        }
}
public void setSyncCookie() {
        Log.e("surosuro", "token transfer start ---------------------------");
        try {
            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
            nameValuePairs.add(new BasicNameValuePair("token", "TEST");// 넘길 파라메터 값셋팅token=TEST
               
            HttpParams params = new BasicHttpParams();
           
            HttpPost post = new HttpPost(domain+/androidToken.jsp");
            post.setParams(params);
            HttpResponse response = null;
            BasicResponseHandler myHandler = new BasicResponseHandler();
            String endResult = null;

            try {
                post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

            try {
                response = httpclient.execute(post);
            } catch (ClientProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                endResult = myHandler.handleResponse(response);
            } catch (HttpResponseException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

            List<Cookie> cookies = ((DefaultHttpClient)httpclient).getCookieStore().getCookies();
           
            if (!cookies.isEmpty()) {
                for (int i = 0; i < cookies.size(); i++) {
                    // cookie = cookies.get(i);
                    String cookieString = cookies.get(i).getName() + "="
                            + cookies.get(i).getValue();
                    Log.e("surosuro", cookieString);
                    cookieManager.setCookie(domain, cookieString);
                }
            }
            Thread.sleep(500);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}
출처 : http://muzesong.tistory.com/42

이번에 PopupWindow로 팝업창을 만들어서 사용 할 일이 있었는데 팝업뷰를 처음 써봐서 

서투르기도 했겠지만, 굉장히 불안정하더군요 , 개인적으로..

예를들면 팝업뷰 xml 에 WebView를 추가하여 팝업에 웹페이지를 띄울라치면 뜨긴하지만 

터치 조금만 하면 badtokenexception 을 뱉어내며 죽어버립니다. 정말 딱 팝업창처럼,

뜬거 보고 확인 후 닫기. 이 기능만 할 수 있더군요 .

그러다가 알게 된 것이 액티비티를 팝업창만하게 띄워서 좀 더 쓸만한 팝업창을 만드는걸

알게 되었습니다.

우선 액티비티이니 팝업창으로 쓸 액티비티를 만듭니다 .

public class WebDialog extends Activity implements OnClickListener {

@Override

protected void onCreate(Bundle savedInstanceState) {

// TODO Auto-generated method stub

super.onCreate(savedInstanceState);

requestWindowFeature(Window.FEATURE_NO_TITLE);

getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,

WindowManager.LayoutParams.FLAG_BLUR_BEHIND);

setContentView(R.layout.webpopup);

WebView webView = (WebView)findViewById(R.id.webPopup);

webView.setWebViewClient(new myWebViewClient());

WebSettings webSettings = webView.getSettings();

webSettings.setJavaScriptEnabled(true);

webSettings.setBuiltInZoomControls(true);

  webView.loadUrl("http://www.google.com");


}

class myWebViewClient extends WebViewClient {


@Override

view.loadUrl(url);

return true;

}

}

public void onClick(View arg0) {

}

} 


이렇게 구글닷컴으로 가는 액티비티를 만들어 줍니다. 여기서 흔히 못보시던게 두가지 있는데 

requestWindowFeature(Window.FEATURE_NO_TITLE); 

이 놈은 나중에 설명드리겠지만 매니페스트에 이 액티비티 테마를 다이얼로그 테마로 잡습니다.

다이얼로그 테마면 상단에 다이얼로그 제목바가 생기는데 이를 없애주는 명령어 입니다.

getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,

WindowManager.LayoutParams.FLAG_BLUR_BEHIND);

두번째로 이것은 그냥 취향인데 이 팝업이 뜨면 뒷 배경이 블러 효과가 납니다. 뿌옇게 이쁘게..

무튼,해당 액티비티의 ContentView인 webPopup.xml(실질적인 팝업구성 xml입니다)을 보면 

  <RelativeLayout 

android:layout_centerInParent="true"

    android:layout_width="300dip"

    android:layout_height="240dip"

    android:background="#50FFFFFF">

        <android.webkit.WebView android:layout_width="fill_parent" 

        android:id="@+id/webPopup" 

        android:layout_height="fill_parent" 

        android:layout_alignParentLeft="true">

        </android.webkit.WebView>

    </RelativeLayout> 


보면 뭐 없습니다. 웹만 띄우기 때문에 웹뷰 하나 있습니다.

그리고 액티비티 이기 때문에 매니패스트에 등록을 해주어야 하는데요 

<activity

android:name="net.oshelp.Info.WebDialog"

android:screenOrientation="landscape" android:theme="@android:style/Theme.Dialog"

android:windowSoftInputMode="stateHidden" android:configChanges="orientation|keyboardHidden">

</activity>


순서대로 액티비티명, 화면가로지정, 다이얼로그테마, 키보드 가리기, 가로세로전환시 키보드가리기 

순서입니다. 중요한건 theme 정도가 있겠네요 

이렇게 하고 이 팝업을 호출하는 곳에서 액티비티 부르듯 

Intent intent = new Intent(detailView.this, WebDialog.class);

startActivity(intent);


이렇게 인텐트 시켜 버리면 


이렇게 이쁜 팝업창이 뜹니다. 뒤에 블러효과 뭔지 아시겠죠?

이렇게 쓰면 배드토큰익셉션도 덜 날 뿐더러 액티비티 이므로 따로 백키를 오버라이딩해서 

dismiss()로 꺼지게 해야할 필요없이 그냥 누르면 꺼집니다, 그리고 아까 만든

webDialog.java 에서 보면 액티비티를 상속받은 클래스이므로 여기다 터치리스너를 달던 

클릭리스너를 달던 아무이상없이 잘되더군요.  앞으로 유용하게 사용 할 것 같습니다 ^^

안드로이드 E-BOOK 제작관련 -펌- 팁 / ANDROID

2011/01/13 17:44

복사 http://blog.naver.com/hnc21/100119926502

첨부파일 (2)

http://sanchang.springnote.com/pages/6620703

 

 

 

안드로이드에서의_eBook_개발_프로세스_이해_1.pptx

 

java 설치: ftp://ebook:android@codesolutions.kr/java-tools /jdk-6u21-windows-i586.exe

eclipse 설치: http://www.eclipse.org/downloads/

Android 설치 : http://developer.android.com/sdk/index.html

Emulator 띄우기

AVD 생성

  • 안드로이드 버전 지정

  • 화면 해상도 지정

  • SD카드 용량 지정

AVD Launch - eclipse 활용

ebook reader apk 설치 : apk 설치 방법 링크 참조

adb install com.aldiko.android.apk

adb install com.chaozh.iReaderFree.apk

sd카드에 디렉토리 만들기

adb shell

cd sdcard

mkdir ebooks

mkdir ebooks/import

adb push로 epub 파일 보내기  sd카드에 파일 보내는 방법 링크 참조

adb push time-machine.epub sdcard/ebooks/import

adb push ebookTest.txt sdcard/ebooks/import

 

FBReaderJ 실습

FBReaderJ 소스 다운로드: http://www.fbreader.org/FBReaderJ/FBReaderJ-sources-0.7.11.zip

                                      https://github.com/geometer/FBReaderJ

FBReaderJ 압축 풀기

http://stackoverflow.com/questions/3726679/how-to-import-and-compile-android-fbreaderj-source-code-into-eclipse-windows

 

CatholicMass.zip

CatholicMass 압축 풀기

eclipse 실행

Android Plugin 설치 : http://developer.android.com/sdk/index.html

eclipse에서 android SDK 지정

Windows ->Preferences -> Android

API Demo http://ko.wikipedia.org/wiki/API

 

개발 관련 용어:

XML: http://ko.wikipedia.org/wiki/XML

JSON: http://ko.wikipedia.org/wiki/JSON http://json.org/json-ko.html

JSON 예제: http://www.samsungsports.net/app/schedule/list.ashx?sport=CD001008_BSB&league=CD002003_FST&schedule=2010-10-01

RDBMS: http://ko.wikipedia.org/wiki/RDBMS

 

애자일 개발 관련:

애자일 관련 자료

애자일관련 책

 

연관 자료:

AutoPub

FBReaderJ

http://jhus.wordpress.com/2010/07/13/um_androidebook/

이북(e-book)과 안드로이드폰이 결합

구글인수회사목록

UI가이드라인

안드로이드 개발 가이드 한글화 : http://www.kandroid.org/board/kandroid_dev.php

 

 

연락처:

 

Email: seeyoung@gmail.com

Twitter: seeyoung21

Facebook: http://www.facebook.com/seeyoung.chang

출처 : http://raftwood.net/blog/3973

오늘 보니까 ‘구글 지도 서비스 유료화 … 기업들 ‘대책 마련 분주’라는 기사가 떴다. 기사를 설렁설렁 읽으면 마치 이제 돈을 내지 않으면 구글 맵으로 어떤 서비스도 만들 수 없던 것처럼 되어 있더라.

기사에도 ‘기업이 상업용 혹은 내부 업무용으로 이용할 때 라이선스 비용을 지불해야 한다’는 내용이 나오고 틀린 말은 아니다. 하지만 ‘상업용 혹은 내부 업무용’이 어떤 의미를 가지는지는 대한 상세한 내용이 없다. 구글지도/구글 어스 API 이용 약관을 한 번 보자. 발번역이지만 번역도 붙여 봤다.

9.1.1 General Rules. 일반 규칙.

(a) Free Access (No Fees). Your Maps API Implementation must be generally accessible to users without charge and must not require a fee-based subscription or other fee-based restricted access. This rule applies to Your Content and any other content in your Maps API Implementation, whether Your Content or the other content is in existence now or is added later. (a) 무료 액세스 (비용 없음). 귀하의 지도 API 구현물은 비용 없이 사용자들의 일반적 접근이 가능해야 하며, 과금을 기반으로 한 가입이나 과금을 기반으로 제한된 액세스를 요구해서는 안 됩니다. 귀하의 콘텐츠와 귀하의 구글 지도 API 구현물 내에 있는 다른 콘텐츠들이 현재 존재하든 이후에 추가되든, 이 규칙은 귀하의 콘텐츠와 귀하의 구글 지도 API 구현물 내에 있는 다른 콘텐츠에 대해 적용됩니다.

(b) Public Access (No Firewall). Your Maps API implementation must not (i) operate only behind a firewall; or (ii) only on an internal network (except during the development and testing phase); or (iii) in a closed community (for example, through invitation-only access). (b) 공공 액세스 (방화벽 없음). 귀하가 지도 API로 구현한 것은 (i) 방화벽 뒷단에서만 혹은, (ii) (개발 및 테스트 기간을 제외하고) 내부 네트워크에서만 혹은, (iii) 폐쇄 커뮤니티(예로, 초대를 통한 접근)에서만 동작해서는 안 됩니다.

9.1.2 Exceptions. 예외.

(a) Enterprise Agreement with Google. The rules in Section 9.1.1 (Free Access, Public Access) do not apply if you have entered into a separate written agreement with Google (such as a Google Enterprise agreement) or obtained Google’s written permission. (a) 귀하가 구글과 별도의 서면 계약(구글 엔터프라이즈 계약과 같은)을 맺거나 구글의 서면 허가를 얻은 경우에는 9.1.1항(무료 액세스, 공공 액세스)의 규칙이 적용되지 않습니다.

(b) Mobile Applications. The rule in Section 9.1.1(a) (Free Access) does not apply if your Maps API Implementation is used in a mobile application that is sold for a fee through an online store and is downloadable to a mobile device that can access the online store. (b) 모바일 애플리케이션. 귀하가 지도 API로 구현한 것이, 온라인 스토어를 통해 유료로 판매되고 온라인 스토어에 접근할 수 있는 모바일 기기로 다운로드할 수 있는 모바일 애플리케이션 내에서 사용된다면 9.1.1(a)항(무료 액세스)의 규칙은 적용되지 않습니다.

9.1.3 Examples. 예.

(a) You can require users to log in to your Maps API Implementation if you do not require users to pay a fee. (a) 귀하가 사용자에게 비용을 요구하지 않는다면, 귀하는 귀하의 지도 API 구현물에 사용자들이 로그인을 하도록 요구할 수 있습니다.

(b) You can charge a fee for your Maps API Implementation if it is an Android application downloadable to mobile devices from the Android Market. (b) 귀하의 지도 API 구현물이 안드로이드 마켓에서 모바일 기기로 다운로드 가능한 안드로이드 애플리케이션이라면 과금이 가능합니다.

(c) If you are a consultant who creates or hosts Maps API Implementations for third party customers, you may charge such customers a fee for your consulting or hosting services (but not for the Maps API Implementations themselves, except as permitted under Section 9.1.2 (Exceptions)). (c) 귀하가 서드 파티 고객을 위해 지도 API 구현물을 제작하거나 호스팅하는 컨설턴트라면, 귀하의 컨설팅 혹은 호스팅 서비스에 대한 비용을 각각의 고객에게 청구할 수 있습니다.  (그러나 9.1,2항에서 허용된 것이 아니라면 지도 API 구현물 자체에 대해서는 비용을 청구할 수 없습니다.)

무리한 내용 요약을 시도하자면, "공짜로 제한없이 서비스할 거면 구글맵 API 공짜로 써!" 이거다. 게다가 모바일 앱이면 유료 앱으로 제공해도 되고, 안드로이드 앱 내에서라면 사용자한테 별도 과금해도 된단다.

이런 내용은 ‘구글맵 API 제품군 FAQ’에도 나와 있다. 주요한 내용은 아래의 ‘상업용 웹사이트에서 Google Maps API를 사용할 수 있나요’ 항목을 보면 된다.

상업용 웹사이트에서 Google Maps API를 사용할 수 있나요?

일반적으로 사이트에 사용자가 무료로 접근할 수 있다면 Google Maps API를 사용할 수 있습니다. 예를 들어, 광고를 통해 유지되는 웹사이트는 Google 지도 API 이용약관에 부합할 가능성이 큽니다. 지도에 정보를 올리는 사람(부동산 매물 정보 등록 등)에게 비용을 받더라도 해당 정보를 Google 지도 API를 사용하여 사이트의 무료 영역에 표시한다면 Google 지도 API 이용약관에 부합합니다.

하지만 모든 상업용 사용이 허용되는 것은 아닙니다. 다음 기준 중에서 하나라도 해당되는 내용이 있는 사이트는 Google 지도 API 고급형을 사용해야 합니다.

  • 유료 고객만 사이트를 사용할 수 있는 경우.
  • 회사나 인트라넷 안에서만 사이트에 액세스할 수 있는 경우.

Google은 Google 지도 API 사용을 언제든지 일시 중지하거나 종료할 수 있는 권리를 가지고 있습니다. 이용약관을 자세히 읽어주세요.

자, 이 정도 내용이라면 사실 왠만한 기업들에는 문제가 될 것이 별로 없다.

그런데 위의 기사에 나오는 기업들은 왜 대책 마련에 분주한 것일까. 기사에도 나오는 내용이지만 이번에 발등에 불이 떨어진 기업은 대부분 ‘내부 업무 시스템’에 구글맵을 사용하기 때문이다. 그리고 부동산 업계의 경우 정확하게는 나와 있지 않지만 관련 서비스 일부를 유료로 제공하는 부분이 있기 때문에 유료 계약을 맺어야 하는 케이스인 듯 하다.

그리고 기사에 LG유플러스의 스마트폰 앱 ‘딩동’ 얘기가 나오는데 이 부분은 잘못된 것으로 보인다. 위의 이용약관에도 보이듯이 스마트폰 앱은 기본적으로 구글맵 API를 무료로 사용하는 데 문제가 없으니까.

이 기사가 나오고 대상이 아닌 기업이나 개발자들도 유료화에 대해 걱정하거나, 심지어는 구글이 이제 자신들의 서비스를 무료로 제공하는 정책을 완전히 버린 것으로 오해하는 모습(심지어는 평소 구글의 오픈 정책을 지지하던 사람들에 대한 비아냥까지!)도 보여서 한 번 정리해 보았다.

아, 물론 이용약관 어디 구석에 이런 내용도 있긴 하다. "언제든지 변경되거나 중단될 수 있다". 하지만 아직까진 구글은 구글이다.

글 쓰면서 검색하다 보니 미니~ 님의 블로그에도 정리가 잘 되어 있어서 링크


소스1(그냥 DTO만 넘기는 소스)


소스2(DTO를 담은 List)

출처 : http://enjoydev.co.kr/65?category=18

하루에 한개의 포스트를 업로드 하기도 힘들... (지금도 힘들다) 지만, 오늘 두개째 글을 쓴다.

안드로이드 Parcelable 이라는 인터페이스가 있다.
이놈은 인텐트를 이용해 객체를 넘겨줄때에 써먹을 수가 있는데, 보통은 아래처럼 번들을 이용해 하나씩 꺼내오지만

  Bundle bundle = this.getIntent().getExtras();
  data1 = bundle.getString("TEST1");
  data2 = bundle.getString("TEST2");

객체를 주고받는다면, 좀 더 쉽게 개발을 할수 있을것만 같다!! +_+
이럴때 Parcelable이란놈을 이용한다. 비트맵 형태의 데이터를 주고받는 경우도 가능하리라 생각된다.
일단은 나도 인터넷을 통해 찾아본 자료등을 통해 샘플을 만들어 보았다. 필요한 분들은 참고하기 바란다.

001aa

이미지를 보면 알겠지만, 절대로 샘플코드를 복잡하게 만들지 않는다 -_-
언뜻보면 레이아웃 (main.xml/sub.xml 등)이 좀 복잡해 보일지 모르지만, 입력상자가 몇개있을뿐 복잡할 건 없다.
입력상자 세군데에 데이터를 입력받아 객체를 생성한뒤, 객체를 넘겨주는 식이다.
두번째의 화면에서는 객체를 넘겨받아, 다시 getter 메서드를 이용해 출력해주는 부분이다.

설명을 더이상 할것도 없다.
코드를 보자.

Student.java - 객체(모델)이 되는 클래스
package com.test.vo;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * @author sungsik81
 *
 */
public class Student implements Parcelable {
 public String name;
 public int age;
 public String birthday;
 
 public Student() {
 
 }

 public Student(Parcel in) {
  readFromParcel(in);
 }
 
 public Student(String name, int age, String birthday) {
  this.name = name;
  this.age = age;
  this.birthday = birthday;
 }

 /* (non-Javadoc)
  * @see android.os.Parcelable#describeContents()
  *
  *  Parcel 하려는 오브젝트의 종류를 정의한다.
  *  어떤 특별한 객체를 포함하고 있는지에 대한 설명을 리턴값으로 표현 하는 것이라고 보면된다.
  *  bit mask 형식의 integer를 리턴 하며,값을 체크 할 때 bit mask 체크를 해서 어떤 것들이 들어 있는지 알 수 있다.
  */
 @Override
 public int describeContents() {
  return 0;
 }
 
 /* (non-Javadoc)
  * @see android.os.Parcelable#writeToParcel(android.os.Parcel, int)
  *
  * Parcel에 데이터를 쓰는 부분.
  */
 @Override
 public void writeToParcel(Parcel dest, int flags) {
  dest.writeString(name);
  dest.writeInt(age);
  dest.writeString(birthday);
 }

 private void readFromParcel(Parcel in) {
  name = in.readString();
  age = in.readInt();
  birthday = in.readString();
 }
 
 /**
  * @author sungsik81
  *
  * Parcelable.Creator<T> 클래스는 createFromParcel() 과 newArray() 메소스가 필요하다.
  * Parcel로 부터 값을 읽어 오기 위해서는 Parcelable.Creator Interface 가 필요하다.
  */
 public static final Parcelable.Creator<Student> CREATOR = new Parcelable.Creator() {

  //writeToParcel() 메소드에서 썼던 순서대로 읽어 오는 것입니다.
  @Override
  public Object createFromParcel(Parcel source) {
   return new Student(source);
  }

  @Override
  public Object[] newArray(int size) {
   return new Student[size];
  }
 
 };

 /*
  * 이하, Getter/Setter
  */
 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public int getAge() {
  return age;
 }

 public void setAge(int age) {
  this.age = age;
 }

 public String getBirthday() {
  return birthday;
 }

 public void setBirthday(String birthday) {
  this.birthday = birthday;
 }
}

MainActivity.java

package com.test;

import com.test.vo.Student;

import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends Activity {
 Button submitButton;
 EditText myTextView;
 EditText myAge;
 EditText myBirthday;
 String myText;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        myTextView = (EditText) findViewById(R.id.myName);
        myAge = (EditText) findViewById(R.id.myAge);
        myBirthday = (EditText) findViewById(R.id.myBirthday);

        submitButton = (Button) findViewById(R.id.ok);
        submitButton.setOnClickListener(new OnClickListener(){

        String inputMyName;
        int inputMyAge;
        String inputMyBirthday;
         
        Student student = null;
       
   @Override
   public void onClick(View v) {
          inputMyName = myTextView.getText().toString();
          inputMyAge = Integer.valueOf(myAge.getText().toString());
          inputMyBirthday = myBirthday.getText().toString();
 
          student = new Student(inputMyName, inputMyAge, inputMyBirthday);
         
    Intent intent = new Intent(MainActivity.this, SubActivity.class);
    intent.putExtra("STUDENT", student);
    startActivity(intent);
   }
         
        });
    }
}

SubActivity.java

package com.test;

import com.test.vo.Student;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class SubActivity extends Activity {
 Button backBtn;
 Bundle bundle;
 TextView resultMyNameTextView;
 TextView resultMyAgeTextView;
 TextView resultMyBirthdayTextView;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sub);
       
        bundle = this.getIntent().getExtras();
  Student student = bundle.getParcelable("STUDENT");
       
  resultMyNameTextView = (TextView) findViewById(R.id.resultMyName);
  resultMyAgeTextView = (TextView) findViewById(R.id.resultMyAge);
  resultMyBirthdayTextView = (TextView) findViewById(R.id.resultMyBirthday);
 
  resultMyNameTextView.setText(student.getName());
  resultMyAgeTextView.setText(String.valueOf(student.getAge()));
  resultMyBirthdayTextView.setText(student.getBirthday());
 
        backBtn = (Button) findViewById(R.id.back);
        backBtn.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    onBackPressed();
   }
         
        });
 }

}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <LinearLayout
     android:orientation="horizontal"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     >
     <TextView
   android:layout_width="150dip"
   android:layout_height="wrap_content"
   android:text="name : "  
   />
  <EditText
   android:id="@+id/myName"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="sungsik"
   />
 </LinearLayout>
    <LinearLayout
     android:orientation="horizontal"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     >
     <TextView
   android:layout_width="150dip"
   android:layout_height="wrap_content"
   android:text="age : "  
   />
  <EditText
   android:id="@+id/myAge"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="30"
   />
 </LinearLayout>
    <LinearLayout
     android:orientation="horizontal"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     >
     <TextView
   android:layout_width="150dip"
   android:layout_height="wrap_content"
   android:text="birthday : "  
   />
  <EditText
   android:id="@+id/myBirthday"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="0810"
   />
 </LinearLayout>  
 <Button
  android:id="@+id/ok"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="Submit To SubActivity"
  />
</LinearLayout>


sub.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <LinearLayout
     android:orientation="horizontal"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     >
     <TextView
   android:layout_width="150dip"
   android:layout_height="wrap_content"
   android:text="name : "  
   />
  <TextView
   android:id="@+id/resultMyName"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   />
 </LinearLayout>
    <LinearLayout
     android:orientation="horizontal"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     >
     <TextView
   android:layout_width="150dip"
   android:layout_height="wrap_content"
   android:text="age : "  
   />
  <TextView
   android:id="@+id/resultMyAge"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   />
 </LinearLayout>
    <LinearLayout
     android:orientation="horizontal"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     >
     <TextView
   android:layout_width="150dip"
   android:layout_height="wrap_content"
   android:text="birthday : "  
   />
  <TextView
   android:id="@+id/resultMyBirthday"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   />
 </LinearLayout>  
 <Button
  android:id="@+id/back"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="Submit To SubActivity"
  />  
</LinearLayout>


AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.test"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".MainActivity" android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".SubActivity" android:label="@string/app_name" />
    </application>
    <uses-sdk android:minSdkVersion="7" />
</manifest>


sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
출처 : http://android-ignition.tistory.com/1

허니콤 어플을 개발하기 위해 

정말 많은 사이트들을 방문하여 조금씩 조금씩 정보들을 모았다.

아직은 정리해서 내것으로 만들수는 없는 단계이기 때문에

우선 참조했던 사이트들의 주소들을 목록화 하여 기록하기로 한다.

 
1. 구글의 Fragment 소개 번역 - 한국안드로이드테스터그룹
http://atg.or.kr/blog/tag/fragment 

2. 커니`s 블로그 Fragment 소개 및 샘플 - 커니님의 블로그
http://androidhuman.tistory.com/470

3. 모토로라 모바일 Fragment 소개 
http://www.slideshare.net/motodev/introducing-fragments-8306530

4. ListFragment + WebView 샘플 - tutorial.vn
http://tutorial.vn/android-compatibility-working-with-fragments.html

5. 가장 활발한 Honeycomb 개발 커뮤니티(질/답, 영문)
http://stackoverflow.com
출처 : http://karyurid.tistory.com/97

현재 진행하는 프로젝트를 위해 죽어도 다시 바로 살아날 수 있는 서비스가 필요하여 간단한 서비스가 죽게 되면은 AlarmManager를 이용하여 다시 살아날 수 있는 서비스를 만들어보았다.

 

시작은 우선 기본적인 서비스 시작과 중지를 담당하는 MainActivity가 있다.(ImmortalServiceMainActivity)

 

주가되는 것은 PersistentService.java & RestartService.java 두 가지가 있다. 이 두개를 이용하여 서비스가 중지가 되면 AlarmManager를 이용하여 서비스를 다시 실행하게 만들어준다. 위의 것을 사용하기 위해서는 Service의 생명주기를 알아야 한다.


그러면 이제 부터는 소스를 살펴보자.

PersistentService.java

@Override

public void onCreate() {

        // TODO Auto-generated method stub

        Log.d(TAG, "Service Create");

        unregisterRestartAlarm(); //등록된 알람은 제거

        super.onCreate();

}

 

@Override

public void onDestroy() {

        // TODO Auto-generated method stub

        Log.d(TAG, "Service Destroy");

        registerRestartAlarm(); // 서비스가 죽을 때 알람 등록

        super.onDestroy();

}

 

void registerRestartAlarm() {

        Log.d(TAG, "registerRestartAlarm");

        Intent intent = new Intent(PersistentService.this, RestartService.class);

        intent.setAction(RestartService.ACTION_RESTART_PERSISTENTSERVICE);

        PendingIntent sender = PendingIntent.getBroadcast(

                       PersistentService.this, 0, intent, 0); // 브로드케스트할 Intent

        long firstTime = SystemClock.elapsedRealtime();  // 현재 시간

        firstTime += 1 * 1000; // 10초 후에 알람이벤트 발생

        AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE); // 알람 서비스 등록

        am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime,

                       10 * 1000, sender); // 알람이

}

       

RTC_WAKEUP : 알람 설정 시 지정된 시계 시간에 Intent를 생성하도록 장치를 깨움

RTC : 명시적인 시간에 Intent를 발생시킬 것이지만, 장치를 깨우지는 않음

ELAPSED_REALTIME : 장치가 부팅되고 난 이후로 경과된 시간의 양에 기반해 Intent 발생. 장치를 깨우지는 않음. 절전상태도 포함

ELAPSED_REALTIME_WAKEUP : 장치가 부팅된 이후로 지정된 길이의 시간이 지나면 intent발생 후 필요한 경우 장치를 깨움

 

void unregisterRestartAlarm() {

        Log.d(TAG, "unregisterRestartAlarm");

        Intent intent = new Intent(PersistentService.this, RestartService.class);

        intent.setAction(RestartService.ACTION_RESTART_PERSISTENTSERVICE);

        PendingIntent sender = PendingIntent.getBroadcast(

               PersistentService.this, 0, intent, 0);

        AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);

        am.cancel(sender);    

}

 

RestartService.java

@Override

public void onReceive(Context context, Intent intent) {

        //TODO Auto-generated method stub

        Log.d("ImmortalService", "RestartService called!@!@@@@@#$@$@#$@#$@#");

       

        if(intent.getAction().equals(ACTION_RESTART_PERSISTENTSERVICE)) {

               Intent i = new Intent(context, PersistentService.class);

//Intent i = new Intent(this, PersistentService.class);

                context.startService(i);

        }      

}

 

AndroidManifest.xml

<receiver android:name="RestartService" android:process=":remote">

       <intent-filter>

                       <action android:name="ACTION.Restart.PersistentService"></action>

        </intent-filter>

</receiver>



위와 같이 다 코딩을 완료하였으면 최초에 서비스를 실행하고 서비스를 죽일 경우

1.     AlarmManager 등록

2.     정해진 시간이 흐른 뒤 Intent BroadCasting

3.     BroadcastReceiver Broadcast Intent를 받고 미리 정의한 행동(PersistentService 살리기)을 수행

+ Recent posts