슈퍼드로이드 카페의 안드로이드 강좌가 책으로 나왔습니다.
도서명 : 이것이 안드로이드다.
도서링크 : http://www.yes24.com//24/goods/13950202
================================================================================================
이전 강좌에서 start Service의 생존에 대해서 알아 보았다.
그런데 한가지 의문이 생기지 않는가?
그러하다면 정말 강의를 깊게 생각하고 보신 분이 분명하다.
그 것이 무엇인지 확인해 보자.
아래의 생존 구간을 보면
start Service의 경우 0nStartCommand 함수가 있어
리턴으로 생존 타입을 전달할 수 있었다.
하지만 bindService의 경우 0nStartCommand가 호출되지 않는다.
그렇다면 bindService의 경우 시스템이 강제로 서비스 프로세스를
죽인다면 다시 살릴 방법이 없을까?
물론 있다.
그 해답은 서비스 쪽에 있지 않고
서비스를 사용하는 Client 쪽에 있다.
이전에 작성했던 Client 소스를 잠시 보자.
bindService를 호출할때 3번째 전달 인자로 BIND_AUTO_CREATE를 보았을 것이다.
이 값이 바로 생존과 연관이 있다.
우선 서비스 코드에서 0nBind 함수에도 역시 로그를 남겨 두자.
intent 값을 찍는 로그를 추가한 것이다.
자 두 패키지를 모두 실행하자.
이전과는 달리 Start Service는 절대 하지 않는다.
만일 이전에 Start Service를 했다면
프로그램 관리자에서 강제 종료를 하던,
아니면 Client에서 Stop Service를 하던 서비스를 종료해 두자.
1번에서 Bind Service를 선택하여 서비스를 바인딩한다.
2번 로그를 보면 0nStartCommand 함수가 호출되지 않고 바로 0nBind가 호출됨을 알수 있다.
자 이제 해당 서비스를 죽여 보도록 하자.
방법은 이전과 동일하다.
3번까지의 과정에서 Service 가 죽었을 것이다.
그런데 이전에 0nStartCommand 함수의 START_REDELIVER_INTENT 타입의 동작과 유사하게
4번을 보면 자동으로 서비스가 시스템에 의해서 재 구동되고 Intent 역시 전달 되었다.
그렇다면 정말 BIND_AUTO_CREATE 속성을 사용하지 않으면
bindService 시에 정말 서비스가 구동되지 않을까?
아래와 같이 수정해 보자.
이전과 동일하게 Start Service 버튼을 누르지 말고
바로 Bind Service 버튼을 눌러보자.
아무리 눌러도 서비스가 로딩되지 않는다.
만일 서비스가 로딩 되었다면
로그에 0nCreate 와 0nBind 가 호출되어야 하지만 로그가 출력되지 않을 것이다.
하지만 영원히 Binding 되지 않는 것은 아니다.
이제 Start Service 버튼을 아래와 같이 눌러보자.
그제서야 서비스가 시작되고
2번과 같이 로그가 출력될 것이다.
여기서 중요한 점은 startService를 시도 했는데 0nBind까지 호출된다는 것이다.
그 이유는 이전에 bindService 시도가 있었고 서비스가 시작되지 않았으므로
바인딩 시도는 취소된 것이 아니라 서비스가 시작될때까지 pending 상태로 유지한 것이다.
대충 BIND_AUTO_CREATE 에 대해서 이해가 될 것이다.
○ BIND_AUTO_CREATE
하는 일은 총 2가지 이다.
1) 서비스가 시작되지 않은 상태에서 startService를 호출하지 않아도
bindService 만으로 자동으로 서비스가 시작된다.
(!!! 서비스가 시작되지만 0nStartCommand 는 절대 호출되지 않는다.)
2) 시스템에 의해 강제로 종료되더라도
시스템의 리소스가 충분해 지면 바로 시스템에 의해서
다시 서비스가 구동된다. 뿐만아니라 이전에 0nBind() 함수에서
Intent를 다시 전달 받을 수 있다.
○ BIND_NOT_FOREGROUND (API Level 8 에서 추가)
본 속성은 Service가 Foreground로 구동되지 않도록 하는 속성이다.
Foreground? 무슨의미 일까?
Android Framework에서는 실행중인 프로세스들을
크게 두가지로 관리한다.
바로 Foreground Process, Background Process 이다.
Background 상태의 Process는 Low Memory Killer에 의해
메모리 자원이 부족할때 강제 종료 대상이 되며,
Foreground Process는 대부분 강제 종료 되지 않는다.
BIND_NOT_FOREGROUND 속성으로
서비스 바인딩을 하면 무조건 서비스는 Background 상태라는 것이다.
즉 메모리가 부족할때 정리되겠다는
시스템 안정성을 위한 속성이다.
자 그렇다면 서비스는 어떤 경우에 Foreground 상태가 되고
Background 상태가 되는지 알아야 정확히 이해가 될 것이다.
이전에 사용했던 패키지를 그대로 이용하도록 하자.
아래와 같이 ClientCountTest 패키지를 실행하자.
1번 버튼을 눌러서 서비스를 실행하자.
2번과 같이 두가지 Process가 구동될 것이다.
이때 두가지 Process 상태가 무엇인지 보자.
실행중인 Process 상태를 보기 위해서는 간단한 ADB 명령어가 필요하다.
adb.exe 실행파일은 android SDK를 설치하면
sdk\platform-tools 폴더에 존재한다.
아래와 같이 명령어를 실행해 보자.
"adb shell dumpsys activity" 명령어는
ActivityManagerService의 상태로그를 화면에 보여주는 명령어이다.
이어 뒤에 붙은 "> log.txt" 는 화면에 출력하지 말고 파일로 저장하도록 하는 명령어이다.
위와 같이 실행하면 log.txt 라는 파일명으로 내용이 저장된다.
해당 파일을 열어보자.
1번과 같이 실행중인 Process의 상태 정보 부분이 있을 것이다.
2번에 Process LRU list 가 보인다.
이것이 의미하는 것은 (LRU : Least Recently Used) list를 말하며,
즉 가장 최근에 사용된 Process list 이다.
해당 리스트를 이용하여 Andoird Framework의 부족메모리해결사(LMK : Low Memory Killer)는
메모리가 부족할때 가장 오랫동안 사용하지 않았고 중요성이 떨어지는
Process를 찾아 강제 종료하는 것이다.
자 이제 그 리스트들을 보자.
3번에 우리가 실행했던 두가지 Process를 찾을 수 있을 것이다.
4번을 보면 Client 패키지는 "/FA" 라고 표시된다.
"F"는 Foreground 상태를 의미하고 "A"는 Activity란 의미이다.
즉 Client는 Foreground 상태임을 알 수 있다.
해당 Client가 왜 Foreground일까? 당연히 현재 화면에 보여지는
Activity이므로 중요도가 아주 높은 것이다.
상세한 설명은 이전 강좌에서 OOM Killer 강좌를 꼭 보자.
5번을 보면 서비스 Process의 상태은 "/B" 라고 표시된다.
바로 Background Process란 의미이다.
우선 순위가 낮으며, 차후 메모리 부족시 정리 대상에 있다.
자 그럼 어떤 경우에 Service 가 Foreground가 될까?
좀더 살펴 보자.
아래와 같이 이어서
1번 Bind Service까지 연결하자.
이제 Client 패키지와 Service 패키지는 서로 바인딩 되었을 것이다.
다시 아래와 같이 로그를 남겨보자.
로그의 결과를 보자.
1번을 보면 서비스가 Foreground로 변경되었다.
그 이유는 3번을 보면 알 수 있다.
3번에 등호 앞뒤를보면 서비스 프로세스보다 클라이언트 프로세스가 우선순위가 높거나 같다는 의미를 나타낸다.
즉 서비스와 클라이언트는 binding 되었으므로 서로 밀접한 관계를 맺고 있고,
그 둘은 같은 상태가 되는 것이다.
그러므로 Client가 Foreground라면 그 연결을 맺은 Service도 Foreground로 변경되는 것이다.
이해가 되는가?
자 그럼 "BIND_NOT_FOREGROUND" 속성을 사용해 보자.
아래와 같이 Client 쪽 소스를 수정하자.
Client를 실행하자.
1,2번을 선택하여 바인딩 상태를 만들자.
다시 로그를 추출하자.
로그의 결과를 보자.
1번을 보면 서비스와 Client가 연결상태임에도 불구하고 Background Process 상태이다.
즉 BIND_NOT_FOREGROUND 속성을 사용하면 절대 서비스는 Foreground 상태가 되지 않는 것이다.
해당 속성도 사용할 일이 있을지 모르겠다.
개인적으로는 사용한 적이 없다.
Framework 쪽에는 SyncManager 쪽에서는 사용하고 있으며,
아마도 Background에서 단말기의 사용자 정보등을 서버와 동기화 할때
메모리가 부족한 경우 정리 대상을 의도적으로 만들고 있는 것 같다.
그러므로 해당 속성은 단말 제조사(삼성,LG 등) 측에서 기본 android 내장 패키지나 시스템 패키지에서
시스템의 안정성을 위해 사용될 것 같다.
단말 제조사에 근무하는 사람이라면 해당 속성을 이해하고
크게 중요치 않은 서비스가 Foreground 상태가 되지 않도록 하여,
시스템 자원 안정화에 노력해야 할 것이다.
○ BIND_AUTO_CREATE ; 하는 일은 총 2가지 이다. 1) 서비스가 시작되지 않은 상태에서 startService를 호출하지 않아도 bindService 만으로 자동으로 서비스가 시작된다. (!!! 서비스가 시작되지만 0nStartCommand 는 절대 호출되지 않는다.)
2) 시스템에 의해 강제로 종료되더라도 시스템의 리소스가 충분해 지면 바로 시스템에 의해서 다시 서비스가 구동된다. 뿐만아니라 이전에 0nBind() 함수에서 Intent를 다시 전달 받을 수 있다. ○ BIND_NOT_FOREGROUND (API Level 8 에서 추가) ; 본 속성은 Service가 Foreground로 구동되지 않도록 하는 속성이다.
아래는 현재는 중요치 않아서 차후에 설명토록 한다. ============================================================================= ○ BIND_DEBUG_UNBIND ; ??? ○ BIND_ABOVE_CLINET (API Level 14 에서 추가) ; ??? ○ BIND_ADJUST_WITH_ACTIVITY (API Level 14 에서 추가) ; ??? ○ BIND_ALLOW_OOM_MANAGEMENT (API Level 14 에서 추가) ; ??? ○ BIND_IMPORTANT (API Level 14 에서 추가) ; ??? ○ BIND_WAIVE_PRIORITY (API Level 14 에서 추가) ; ??? |
이제 마지막으로
시스템이 메모리 부족이나 30분마다 강제로 서비스를 종료하지 않도록 할 수는 없을까?
예로 이전에 테스트 했던 1초에 1씩 Background에서 증가 시키는 서비스의 경우
강제로 종료되면 자동으로 재 시작을 하여도 증가된 상태 값을 잃어버릴 수 있다.
물론 파일로 저장하거나 DB로 저장해 두면 복원은 할 수 있을지 몰라도
정지된 순간부터 재시작까지 값을 증가시킬 수는 없을 것이다.
서비스가 종료되지 않으려면
Foreground Process면 가능하다.
그럼 Foreground Process 상태로 만들면 되지 않을까?
!!! 잠시만 주의하자.
절대 아래에서 설명될 방법을 최대한 사용하지 않았으면 좋겠다.
서비스를 Foreground로 많은 사람이 구동해 버리면
단말기의 메모리는 급격히 부족해 질 것이고,
윈도우처럼 사용하면 할 수록 점점 느려지게 될 것이다.ㅋㅋㅋ
정말 필요한 경우만 사용하고
사용하더라도 메모리를 최대한 적게 유지하도록 해야한다.
차라리 개인적으로는 Android에서 해당 방법을 제공하지 않았으면 하는 바램이다.
Android Service에서는 startForegound() 라는 함수를 제공한다.
해당 함수를 호출만 해 주면 서비스는 강제로 종료되는 경우가 아주 희박하다.
물론 Foreground Process도 우선 순위에 따라 죽을 수는 있다.
그렇지만 만일 Foreground Process가 죽을 정도로 메모리가 부족하다면
단말기 상태가 정상이 아닐것이다.
아주 간단히 바로 전에 사용했던 테스트 패키지를 수정하도록 하겠다.
전에 사용했던 Service 패키지에서 한줄을 추가해 보자.
1번과 같이 Foreground로 서비스를 시작해 달라는 것이다.
설명에 앞서 결과를 보자.
우선 Client를 실행해 보자.
(당연히 작업전 Client와 Service를 모두 종료한 상태에서 진행하자)
1번을 눌러 서비스를 시작한다.
서비스가 시작되었을 것이다.
바로 로그를 출력해 보자.
이전과 로그를 저장하는 방법은 동일하다.
로그내용을 살펴 보자.
1번에 "prcp" 라고 출력된다. 이것의 의미는 아래에서 설명하겠다.
2번에 "FS" 라고 되어 있다. 이 의미는 Foreground Service 라는 의미이다.
어떤가 Foreground Process가 된 것이다.
해당 서비스는 죽을일이 없어졌다.
적어도 시스템에 의해 죽을일은 극히 드물다.
참고로 여러 프로세스 관리 어플리케이션을 설치해 보면
Process를 정리하는 어플이 많다.
그런 어플리케이션에서도 해당 어플은 종료되지 않을 것이다.
왜냐하면 Foreground Process는
특정 App에서 강제로 종료할 수 없기 때문이다.
즉 무적이다.
startForeground 함수는 무엇을 하기에 그럴수 있을까?
그 해답은 위에서 1번에 표시되었던 "prcp"에 있다.
그 의미는 Perceptible Process 상태를 의미한다.
Perceptible Process는 이미 OOM Killer 관련 강좌에서 설명하였다.
혹시 보지 못한 분들은 아래를 참조하자.
아래의 링크를 참조하자. 11. Application의 상태와 OOM(Out Of Memory) Killer 에 대해서 위의 링크에서 하기 부분 참조 1.5 PERCEPTIBLE_APP_ADJ
본 상태는 보이지는 않으나 지각될 수 있는 Process의 상태를 말한다. ...
|
그렇다 Perceptible Process는 지각할 수 있는 Process이다.
perceptible Process 상태는 Foreground에 해당한다.
그런데 이상하지 않은가?
우리가 만든 서비스는 Background에서 1초에 1씩 증가하고만 있으며,
사용자가 그 서비스가 동작하고 있다는 어떠한 지각도 할 수 없다.
그런데 왜 Perceptible process 상태일까?
그 답은 우리가 사용한 함수에 있다.
바로 startForeground () 함수이다.
해당 함수의 원형을 잘 살펴보자.
public final void startForeground(int id, Notification notification) |
함수의 인자로 Notification 객체를 전달해야만 한다.
Notification은 무엇일까?
아래의 그림으로 이해하자.
위의 그림에서
1번 영역이 StatusBar 영역이고 좌측에 표시되는 몇몇 아이콘들이 Notification에 해당한다.
2번과 같이 아래로 내리면
3번과 같이 좀더 상세한 내용이 나오고
각 등록된 Notification 항목을 선택할 수도 있다.
좀 이해가 되는가?
startForeground() 함수를 호출할 때는 무조건 Notification 객체를 꼭 등록해야만한다.
그 말은 Notification 영역에 어떠한 그림을 표시해야 한다는 것이다.
해당 서비스를 Foreground로 구동되게 하려면 해당 서비스가 구동되고 있다는 눈에 보이는 무엇인가를
표시해야 하는 것이다.
그러므로 해당 서비스는 Perceptible Process 상태가 되는 것이다.
즉 지각할 수 있는 서비스라는 것이다.
자 그런데 우리는 아래와 같이
Notification 객체를 생성해서 전달은 해 주었지만,
아무런 Notification에 셋팅은 해 주지 않았다.
그래서 Notification 영역에 아무런 내용도 표시되지 않는다.
이 것은 Android Framework의 헛점이다.
분명 셋팅되지 않은 Notification 객체를 전달할때
에러가 발생해야 하지만 발생되지 않고 무시한다.
그래서 위에서 해당 방법은 최대한 사용하지 말아야 한다고 한 것이다.
언제 구글 측에서 수정할지는 모르겠지만 분명히
구글의 의도와는 맞지 않는다.
Notification의 등록 방법은 Notification Service를 설명하는 강좌에서 진행토록 하겠다.
자 그럼 서비스를 죽지 않도록 하는 방법은 이것이 전부일까?
그렇다. 일반 개발자 입장에서는 전부이다.
( 가끔 인터넷에서 서비스를 죽지 않도록 하는 방법에 대해서 다룬것을 보았다.
Alarm을 등록해서 주기적으로 Service를 살리는 방법이다.
하지만 앞에서 말했듯 LMK에 의해 강제로 서비스가 내려가는 경우
자동으로 살려주기 때문에 Alarm을 등록해서 살리는 방법을
왜 권장하는지 솔직히 모르겠다. 혹시나 다른 이유가 있다면
알려 주셨으면 한다.)
하지만 단말 제조사에 종사하는 개발자들에게는 분명 다른 방법이 있다.
(!!! 단말을 루팅 한 사람들도 아래에 방법을 사용할 수 있다.)
하기 내용부터는 단말 제조사에 근무하는 사람들을 위해
추가적으로 서비스를 죽지 않도록 하는 방법에 대해서 설명토록 하겠다.
(!!! 단말을 루팅한 사람도 포함)
필요한 사람이나 궁금한 사람들만 참조하도록 하자.
이전 서비스 패키지를 수정할 것이다.
가장 먼저 단말기에 설치된 서비스 패키지를 삭제하자.
다음 위에서 startForeground 를 추가했었다면 주석이나 제거하자.
다음 AndroidManifest.xml을 수정한다.
<application> 속성중에 android:persistent="true" 로 설정한다.
먼저 설명하자면 이 속성은 절대 시스템이 강제로 Process를 죽이지 않도록 하는 속성이다.
아래에서 좀더 설명하겠다.
하지만 일반 개발자들은 해당 속성을 추가할 수는 있어도 무의미 하다.
즉 해당 속성을 주어도 서비스는 강제 종료된다는 것이다.
그다음 패키지를 리빌드하면
아래와 같이 소스의 bin 폴더에 패키지 파일이 생성될 것이다.
다음은 위에서 생성된 apk 파일을 단말기의 특정 폴더로 복사하는 과정이다.
이 과정 이후부터 단말 제조사에 근무하는 사람들만 가능한 환경이므로
일반 사용자는 사용할 수 없는 것이다.
위의 과정을 하기 위해서는 일단 단말의 바이너리가 eng 혹은 userdebug 모드로 빌드된 단말이어야 한다.
제조사에 종사하는 사람이라면 user 모드, userdebug 모드, eng 모드 에 대해서 알고 있을 것이다.
eng, userdebug 모드에서는 단말의 모드 정보를 볼 수 있고 단말내에 잠긴 모든 폴더를 접근 및
각종 Process를 디버깅 할 수 있다.
자 더욱 쉽게 말하면 eng, userdebug 상태는 폰을 루팅된 상태라고 보면된다.
1번과 같이 서비스 apk를 단말기로 복사한다.
대부분 read-only 파일 시스템이라 에러가 날 것이다.
" adb push ServiceCountTest.apk" /system/app "
(위의 의미는 adb 명령어를 이용하여 PC의 파일을 단말기로 복사하는 push 속성을 주고
ServiceCountTest.apk를 단말기의 /system/app 폴더로 복사해라는 의미이다.)
이 경우
2번과 같이 다시 파일시스템 마운트를 하면된다.
!!! 만일 루팅하신 분들이 adb remount 명령어가 안먹는 경우 해당 강좌에 댓글을 올려주신 jae-Goo 라는 분께서 아래와 같은 글을 남겨 주셨습니다. 안녕하세요. 강좌 잘보고 있습니다. 테스트로 옵티머스 마하 폰에서 루팅해가지고 adb push test.apk /system/app 하니 안들어가길래 보니깐 /system/app 이 ro(read only) 더군요. 저랑 똑같은 상황이신분 아래와 같이 rw모드로 전환해주시고 apk 넣으면 되네요. # mount (현재 디바이스명 이랑 fstype보신 후 아래와 같이 입력) # mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system |
3번과 같이 다시 서비스 apk를 단말기로 복사해 보자.
eclips의 DDMS 에서 File Explorer을 이용하면
잘 복사되었는지 확인할 수 있다.
아래는 잘 복사 되었다.
(물론 adb shell ls /system/app/ServiceCountTest.apk 라고 치면 볼 수 있지만 말이다.)
자 여기서 한가지 알고 넘어가야 할 것이 있다.
위의 단순히 system/app에 복사하는 과정만으로
해당 apk를 설치가 된다.
분명 해당 apk를 설치한 적은 없다.
Android의 서비스 중 어플리케이션을 설치하고
각종 패키지 정보를 저장해 주는 서비스가 있다.
그 것은 바로 PackageManagerService이다.
바로 PackageManagerService에서는
/system/app 폴더에
패키지 파일이 복사되면 자동으로 감지하여 설치한다.
그런데 /system/app 폴더 하나만 그럴까?
아니다. 아래의 그림을 보자.
위의 1,2,3번의 폴더에 저장하면 모두 자동으로 설치해 준다.
그리고 해당 폴더에 저장된 패키지는 모두 system 패키지라고 부른다.
참고로 PackageManagerService는 해당 폴더의 패키지를 내부적으로
PackageParser.PARSE_IS_SYSTEM_DIR 속성과
(시스템 폴더에 존재하는 패키지라는 의미)
PackageParser.PARSE_IS_SYSTEM 속성을 부여한다.
(시스템 패키지 라는 의미)
그 이유는 시스템 패키지는 여러가지 강력한 권한을 가질 수 있기 때문이다.
참고로 시스템 application의 강력한 권한 중에 한가지만 설명하자면 특정 패키지를 설치하는 함수를 사용할 수 있다. 아래와 같다. (일반 어플은 사용할 수 없다.) getPackageManager().installPackage() 어떤 사람들은 일반 개발자들도 패키지 설치를 할 수 있다고 생각할 수 있다. 물론 맞다. 하지만 위의 함수로 직접적으로 설치하는 것이 아니라, 안드로이드에서 기본적으로 제공하는 패키지를 설치하는 Activity를 호출하는 방식이다. 그 Activity는 패키지를 간접적으로 설치하도록 유도한다. 하지만 간접적으로 패키지를 설치하는 방식은 조금 문제가 있다. 아는 사람이 많겠지만 패키지를 설치하는 Activity를 구동했을때, 알 수 없는 출처의 application을 설치한다고 에러가 뜨고 환경설정에서 알수 없는 출처의 application 설치 가능을 체크해야만 한다. 추가적인 기능으로 삭제도 가능하다. |
이러한 시스템 패키지는 단말 제조사에서 미리 탑재시켜서 판매하고
제조사에서는 Preload 패키지라고 부른다.
어쨌든 글이 너무 길었다.
자 그 다음 단말을 리부팅하자.
리부팅 해야지만 설치된 서비스 앱의 정보가
정상적으로 설정된다.
리부팅후 Client 패키지를 실행하여
서비스를 구동해 보자.
아마도 서비스가 정상적으로 실행되었을 것이다.
자 이제 아래와 같이 로그를 출력해 보자.
출력된 로그에 Service 패키지가 어떠한 우선순위로 실행되었는지 살펴 보자.
1번과 같이 "PERS" 라고 표기되고 adj 는 "pers" 일 것이다.
또한 "/F" 와 같이 Foreground process 에 해당한다.
PERS는 무엇을 의미할까?
이는 PERSISTENT 라는 의미이고
LMK에서 프로세스를 정리 하지 않을 정리 대상의 우선순위에서
거의 최고봉이다.
해당 Process는 앞에서 말한 startForeground 보다 훨씬 높다.
어쨌든 해당 내부적인 우선순위는
PERSISTENT_PROC_ADJ에 해당한다.
과거 버전에서는 CORE_SERVER_ADJ라고 부르기도 한다.
PERSISTENT_PROC_ADJ의 우선순위 확인은 제 강좌에 OOM Killer를 꼭 참조하라.
정리하자면 해당 권한을 지정하기 위해서는 두가지가 필요하다.
1. AndroidManifest.xml에서 android:persistent="true" 을 설정해야하고
2. System 패키지 속성을 가져야 한다. ==> 해당 부분 때문에 일반 사용자는 해당 기능을 사용할 수 없다.
자 여기서 Service 생존편을 마치도록 하겠다. ^^;;;;;
!!! 위의 주제에 해당하는 적당한 예를 댓글로 남겨 주세요. ^^
활용 방안의 예는 다른 개발자들에게 많은 도움이 됩니다.
!!! 카페의 활성화를 위해 추천 버튼을 눌러 주세요.
댓글
댓글 리스트-
작성자525dms 작성시간 15.02.22 질문이 있어 댓글 남깁니다 ㅠㅠ 다음의 두 가지 경우에 대한 차이점이 무엇인가요?
1. Activity에서 startService로 서비스를 시작한 후, Service의 onCreate()에서 startForeground로 포그라운드 서비스 설정을 한다. 그 후, 해당 어플리케이션을 종료하고 메모리 킬러 앱을 눌러도 서비스가 동작중이다.
2. Activity에서 bindService에 BIND_AUTO_CREATE 플래그를 주어 스타티드 서비스가 실행되지 않은 상태에서 바운드 서비스를 사용한다. Service의 onCreate()에서 startForeground로 포그라운드 서비스 설정을 한다. 하지만 이 경우에는 어플리케이션을 종료하고 메모리 킬러 앱을 누르면 서비스가 죽는다... -
답댓글 작성자슈퍼성근 작성자 본인 여부 작성자 작성시간 15.02.23 안녕하세요.
바운드 서비스는 foreground로 구동될 수 없습니다.
스타티드 서비스로 서비스를 실행상태로 둬야만 foreground로 실행이 가능합니다.
그리고 포그라운드 서비스가 아닌 서비스는 강제 종료가 될 수 있습니다.
스타티드 서비스는 서비스 자체를 유지할 수 있는 것이죠.
하지만 바운드 서비스는 서비스 자체를 유지하는 것이 아니라
마치 라이브러리 처럼 그때 그때 서비스 API를 쓸수 있도록 하는 것입니다.
그리고 바운드 서비스는 그 서비스를 사용하는 앱의 우선순위를 따라 갑니다.
예를 들자면 특정 앱의 액티비티에서 해당 서비스를 바인딩 하면
그 서비스는 자동으로 포그라운드가 됩니다.
-
답댓글 작성자슈퍼성근 작성자 본인 여부 작성자 작성시간 15.02.23 그 이유는 간단합니다.
서비스의 API를 쓰기 위해 바인딩 했기 때문에
그 API를 쓰는 앱과 같은 우선순위에 놓여지죠.
그리고 액티비티가 종료되면 바인딩은 끊어지고 서비스는 백그라운드가 됩니다.
이렇때 바운드 서비스를 유지하려면
스타티드 서비스로 돌리면 됩니다.
스타티드 서비스를 사용하는 것은 서비스를 스스로 생존을 유지하기 위함이죠.
바운드 서비스는 서비스 스스로 생존을 유지하는 것이 아니라
그 서비스를 사용하는 컴포넌트(액티비티, 또 다른 서비스..)와 일치되어
생존을 유지하는 것입니다. -
작성자흐규흐규흐규 작성시간 15.04.07 안녕하세요 서비스에 startForeground(123123, new Notification()); 추가시 statusbar 영역에 notification이 추가 되가되는데 강좌내용과 다른 부분이어서 댓글달아봅니다. "ServiceCountTest1이(가) 실행 중입니다. 자세한 정보를 보거나 앱을 중지라혀면 터치하세요" 터치하면 앱을 강제종료하고 제거 할수있는 설정화면으로 넘어갑니다.
startForeground(0, new Notification()); , id를 0으로 설정하면 notification이 추가되지 않습니다. -
답댓글 작성자슈퍼성근 작성자 본인 여부 작성자 작성시간 15.04.07 안녕하세요. 아쉽게도 해당 내용이 최신화 되지 않았네요.
책을 쓰면서 너무 많은 일들이 생겨나면서 소홀하게 되네요.
해당 내용은 책에 상세히 설명했습니다.
감사합니다.