본문 바로가기

구글과인터넷/안드로이드

안드로이드 개발 - 종료 관련 (home, back키)

홈키 잡는법  안드로이드 

void Activity.onUserLeaveHint ()

이 메서드는 사용자에 의해 액티비티가 백그라운드로 전환되기 직전에 onPause 바로 앞에 호출된다. Home 키를 누르기 직전에 호출되며 Back키를 누르거나 전화 통화 앱이 올라올 때, 타이머에 의해 종료될 때는 호출되지 않는다. Home키는 키입력 이벤트로 전달되지 않아 검출이 어려운데 이 메서드가 호출될 때 Home키에 의해 백그라운드가 됨을 알 수 있다. 이 두 메서드는 상태란의 통지를 관리할 때 사용될 수 있으며 액티비티가 통지를 취소할 시점을 결정하는데 도움을 준다. 다음 예제는 사용자가 5초 이상 관심을 보이지 않으면 즉시 종료한다.

 

검증완료

사이클 순서

 onCreate
 onStart
 onResume
 홈키 클릭
 onUserLeaveHint
 onPause
 onStop

 

activity에서만 가능하므로 다른 java파일은

 PhoneWindowManager.java 파일에서 처리하는 해 줘야 한다

 

 

홈키시 actvity 종료시키는 방법으로는

androidmanifast.xml에

<activity android:name=".ClassName"

  android:launchMode="singleTask"
  android:clearTaskOnLaunch="true"

/>

 

android:launchMode="singleTask"
android:clearTaskOnLaunch="true"

두개의 속성을 추가해준다

[출처] 홈키 잡는법|작성자 콰이콰이


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


출처: http://blog.naver.com/schweine7?Redirect=Log&logNo=40124982560

[Android/안드로이드] Manifest <activity> clearTaskOnLaunch  안드로이드(Android) / 프로그래밍 

이번에 살펴볼 attribute 는 clearTaskOnLaunch = "true" | "false"


 자.. 요놈은 어렵지 않기 때문에 부연 설명 없이 바로 developers 를 참조할까요?

- Home Screen 에서 re-launch 될때, task에서 root activity 를 제외하고 모두 제거한다. ( clear )
 (따라서 이 attribute 는 task 의 root 를 차지하는 경우에만 유효하죠 )

- "true" 값일 때 root activity 만 남기고, 이놈은 root activity 를 실행 시킬 때만 작용합니다.

- default 값은 "false" 입니다. 그래서 보통 re-launch 하면 last state 가 보여지는 것이죠.



자 developers 에서는 친절하게 예제도 제공해주네요.

1. user 가 Homescreen 을 통해 P activity 를 띄웁니다.
2. P 에서 Q activity 를 띄웁니다.
3. Q activity 에서 Home 키를 누릅니다.
4. 다시 Homescreen 에서 P activity 를 띄웁니다.
5.
 5-1. false (default) 일 때는 P 가 아닌 Q 가 보여집니다. ( last state )
 5-2. true 일 때는 Q 는 날아가고 P 를 보여줍니다.


자 이해가 되셨죠?

activity 의 마스터가 되기 위해서는 실험도 해보면 더 좋겠죠? ㅋ


참고로,

이놈은 alwaysRetainTaskState = false 값에, 30분의 시간이 아닌 0초의 시간으로 설정된 것이라 볼 수 있겠습니다.

//////////방식은 아래 이런식

    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
    <uses-permission android:name="android.permission.BATTERY_STATS" />
    <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
    <uses-permission android:name="com.android.launcher.permission.WRITE_SETTINGS" />
    <application android:label="@string/settings_label" android:icon="@drawable/ic_launcher_settings" android:taskAffinity="">
        <activity android:label="@string/settings_label" android:name="Settings" android:taskAffinity="com.android.settings" android:clearTaskOnLaunch="true" android:launchMode="singleTop" android:screenOrientation="portrait">

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

안드로이드 어플 완전 종료 (Process Kill)

이번 포스팅은 안드로이드에서 실행된 어플의 프로세스 종료에 대해 정리를 해보려고 합니다.

참고 : Android Developers Dev Guide - Framework Topics Activities

위의 링크는 안드로이드 Develop 공식 사이트이며, 그중에 Activity에 대한 내용을 링크해놓은 것입니다. 참고를 하면 도움이 될 것 같습니다.

본격적으로,

Activity를 종료 시키는 방법을 나열한다면, 


1
2

1
2

1
2

1
2
3

1
2
3
// 첫번째 방법
finsish();

// 두번째 방법
System.exit(0);

// 세번째 방법
android.os.Process.killProcess(android.os.Process.myPid());

// 네번째 방법
ActivityManager am  = (ActivityManager)getSystemService(Activity.ACTIVITY_SERVICE);
am.restartPackage(getPackageName());

// 다섯번째 방법
ActivityManager am  = (ActivityManager)getSystemService(Activity.ACTIVITY_SERVICE);
am.killBackgroundProcesses(getPackageName());


여기서 첫번째 방법은 Activity가 종료되지만 Task 상에서 Process는 실제 종료된 상태는 아닙니다. 따라서 두번째와 세번째를 사용하면 Process까지 종료를 시키게 됩니다.

하지만 두번째 세번째 방법도 Activity를 둘 이상을 사용하게 된다면 Process가 종료되었다가 이전 Activity로 Process가 다시 실행되어 Process가 종료되는 것이 아니라 다시 실행되고 이전 Activity로 돌아가되 됩니다.

네번째 방법과 다섯번째 방법은 구글로 검색하고 포럼에서 게시글을 찾아보고 나온 방법인데요. 이것도 현재 Froyo 버전 이후부터는 작동되지 않는 것을 확인했습니다.(저는 테스트를 2.3.3 버전의 넥서스 원으로 테스트를 하여 확인했습니다.)

따라서 둘 이상의 Activity를 사용할 때는 이전 Activity도 함께 finish를 하고 두번째나 세번째 방법으로 종료를 해야 다시 Process가 살아나지 않는 것으로 확인하였습니다.

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


출처: http://uiandwe.tistory.com/238

아마 네이년을 찾아보면은 

System.exit(0) 또는 android.os.Process.killProcess(android.os.Process.myPid()); 을 쓰세요^-^/

하고 나와있는데..-0- 위의 두개는 현재 실행중인 activity 를 죽이는 것이다. 

하지만 대부분의 프로그램이 하나의 activity 를 쓰진 않는다. 

Intent 되어 새로운 activity 를 생성하기 떄문에 뒤에 가려있떤 activity 가 다시 올라오는것이다.

(고로 프로세서가 죽지를 않는다)

그러면 어떻게 해야되는냐!

모든 activity 에게 동일한 권한을 주고 프로세스를 한꺼번에 죽이는것이다.

사용법은 아주 간단하다는~~ AndroidManifest.xml 파일에 
<uses-permission android:name="android.permission.RESTART_PACKAGES"></uses-permission>
추가하고

소스파일엔(뭐 버튼정도 되겠쬬?)
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
am.restartPackage(getPackageName());
추가해주고 버튼 지그시 눌러주면은 프로세서가 죽는것을 볼수 있다.!!

(찾느라..정말 고생햇따는...ㅜㅡㅜ )


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


출처: http://www.sjava.net/276
Android에서 앱의 Activity Stack을 일정 숫자만큼 유지를 하는 클래스입니다..
이 클래스를 통해서 앱의 종료도 detect할 수 있습니다.. 

* ActivityManager클래스..
코드가 너무 간단해서 설명 생략.. 
import java.util.concurrent.LinkedBlockingQueue;
import android.app.Activity;
/**
 * Activity Manager Class
 * @author mcsong@gmail.com
 *
 */
public class ActivityManager {
    private static final int max = 13;
    private static final int size =12;
    private static LinkedBlockingQueue<Activity> queue = new LinkedBlockingQueue<Activity>(max);
    private static final String CNAME = ActivityManager.class.getSimpleName();
    
    public static void createActivity(Activity activity) {
        if(activity == null)
            return;

        queue.add(activity);
        if(queue.size() > size) {
            try {
                queue.take().finish();
            } catch (Exception e) {
                LogUtil.e(CNAME, LogUtil.TAG, ExceptionUtil.getException(e));                
            }
        }
    }
    
    public static boolean isRootActivity(Activity activity) {
        if(activity == null)
            return false;
        
        try {
            if(activity == queue.peek())
                return true;
        } catch (Exception e) {
            LogUtil.e(CNAME, LogUtil.TAG, ExceptionUtil.getException(e));                
        }
        
        return false;
    }

    public static void clear() throws InterruptedException {
        while(queue.size() > 0) {
            queue.take().finish();
        }
    }
}

* 사용방법
- Activity 생성(onCreate 메소드에서)시에 createActivity()를 호출한다. 자연스럽게 size만큼 Activity Stack이 관리가 된다. 
- 앱 종료 detect는 isRootActivity()로 확인을 하면 된다.. ture인 경우 각 Activity 클래스에서.. onBackPressed()를 Override해서 확인하면 된다.. 참고로, AbstractActivity 클래스를 만들어서 상속을 사용하면 코드가 깔끔해 지겠다..
- 앱을 종료하면서 clear()를 호출해서 Activity stack에 있는 Activity들을 다 날려주셔야 Activity 관리가 명확해 집니다.. ^^ 

* 안드로이드 activity의 동작형태는 android:launchMode="standard" 에서 잘 동작합니다.. ^^

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
출처: http://www.androidpub.com/560851
홈 버튼을 누르면 application이 종료 되기 직전의 상태를 저장을 하고 

추후에 다시 프로그램을 실행하면 종료 되지 전의 상태를 복원을 하는 것 같습니다. 

제가 원하는 것은 홈 버튼을 누를 때 프로그램을 완전이 종료하고 추후에 다시 실행 할 경우 처음 부터 실행이 되도록 하는 것입니다. 

방법 알고 계시면 부탁드립니다^^

 
댓글
2010.07.20 08:34:15
Ryunzae
(추천: 1 / 0)
Activity에서 onKeyDown 메소드를 오버라이드하셔서
홈버튼(KeyEvent.KEYCODE_HOME)이 눌러졌을 때 
finish() 메소드를 호출하시면 됩니다.
댓글
2010.07.20 08:51:51
정가정가
감사합니다. finish 함수를 적용하니 잘 종료가 됩니다. 정말 감사합니다^^
댓글
2010.07.20 10:43:03
초보개발자
홈버튼을 누르는 것은 앱에서 제어할 수 없는 것으로 알고있는데요, 잘 되시던가요?


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

출처: http://www.androidpub.com/358075


app을 홈버튼으로 종료하고 다시 실행할 때 처음부터 실행시키는 방법을 알고 싶습니다.

제 app은 여러가지 액티비티가 있는데 액티비티를 막 이동하다가 거기서 홈버튼으로 종료하고

다시 app을 실행시키면 그 종료된 시점의 액티비티에서 부터 시작됩니다.

처음부터 시작되게 하는방법 없나여

 
댓글
2010.05.18 10:17:08
침노
액티비티 생명주기를 보시면 될듯. onCreate에서 다 구현된것을 onStart, onResume등에서 처리하면 될듯 합니다.
댓글
2010.05.18 10:50:29
codgear
ㅇㅇ 침노님 답변감사합니다.

해결 되었습니다.

clearTaskOnLaunch를 설정해 주니 한방에 되네여
댓글
2010.05.19 10:47:53
SSamDDak
정석으로 해결 하셨네요 ^^;
댓글
2010.06.17 15:17:27
소혼
감사합니다. 궁금했던 부분이었는데 덕분에 해결되었습니다.


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

출처: http://www.androidpub.com/396804

프로그램 실행 순서입니다. (A,B,C는 Activity입니다.)
A->B->C-> Home key ->A ->E-> Back Key ->C->Back Key->B->Back key->A

프로그램을  실행하여서 위와 같은 순서로 실행하면 home키를 눌렀을 시에 스택에 Activity가 남아 있는 것 같습니다.
제가 원하는 순서는 A->B->C-> Home key ->A ->E-> Back Key ->A입니다. (수정하였습니다.)

1. home키를 눌렀을 시에 이전에 남았는 Activity를 제거할 수 있는 방법이 있을 까요?

2. Home키를 입력 받을 수 있는 키 이벤트가 존재하나요? (KeyDown,Keyup으로는 안들어 오더군요. )

 검색하여서 manifest파일에 finishOnTaskLaunch, cleartaskonlaunch , launchMode라는 속성을 바꾸어 가며 
적용하였지만 동작이 잘 되지 않는 군요.  방법을 아시는 분은 알려주시면 감사하겠습니다. ^^
 

그럼 좋은 하루 되세요~~~


추가 정리 사항,
각 Activity 속성
A Activity.
android:launchMode="singleTask"
android:clearTaskOnLaunch="true"
B Activity.
android:launchMode="singleTask"
android:finishOnTaskLaunch="true"
C Activity.
android:launchMode="singleTask"
android:finishOnTaskLaunch="true"
E Activity.
android:launchMode="singleTask"

이외는 name, theme, configChanges 정도 밖에 없습니다. 




공지사항을 다 읽었음.

 
댓글
2010.05.31 09:06:44
yally
1. android:launchMode="singleTask"     
   android:clearTaskOnLaunch="true"
    이 두가지 속성 추가 해보시길...단..A가 Home에 등록되어있어야합니다.

2. Home key는 어플단에서 불가능합니다. 직접 소스를 빌드하신다면 프레임웍단에서 변경 가능합니다.


댓글
2010.05.31 09:13:18
휴우
음.. 우선 아쉽게도 홈키 이벤트를 가로챌 수 있는 방법은 없습니다. (구글에서 어플리케이션 UX 일관성을 위해 Home 키만큼은 막아두었다고 하더군요.) 

두번째로, Task 에 남기지 않으시려면 Launcher Activity 속성에 clearTaskOnLauch 값을 설정해 주면 되는게 맞습니다. 근데 잘 작동하지 않는 다니까 좀 이상하네요. 

제가 조금 헷갈리는 거는... 원하시는 바가
A->B->C->Home Key->A->E->Back Key->Home Screen 이라고 하셨는데...
Task 의 유지 여부와는 관련없이 A->E->Back Key->A 가 되는게 당연한게 아닌가.. 라는 생각이 듭니다.

만일 E 에서 Back Key 를 눌렀을 때 바로 Home Screen 이 되려면,
A Activity 가 시작된 정보가 Task 에 남아 있어서는 않되며, 실행될 때, FLAG_ACTIVITY_NO_HISTORY 값이 설정되어야 합니다.


댓글
2010.05.31 10:48:55
안드로메다로달리기
얄리님과 휴우님 정말 빠른 실시간 답변 감사드립니다. ^^
복받으실거에요. ㅎㅎ

A  Activity에 clearTaskOnLaunch값과 singleTask값을 설정해주었지만 그래도 Activity가 남아있네요. 
B Activity도 singleTask여서 여기에는 finishOnTaskLaunch를 설정해주었습니다. 
속성값이 있는 것이 도움받기 편할 듯 합니다. 
다시 속성값과 함께 수정하여 올리겠습니다.

아래의 내용은 제가 이해하고 있는 내용인데 맞게 이해한 것 인가요?
clearTaskOnLaunch는 루트 Activity를 제외한 나머지를 제거한다. 단 루트 Activity의 속성에만 해당한다. 
finishOnTaskLaunch는 루트 Activity를 포함한 태스크를 제거한다. 

댓글
2010.05.31 11:18:26
yally
(추천: 1 / 0)
clearTaskOnLaunch 속성
  task의 root activity에 이 속성을 set하면 task를 나가고 돌아올때 clear된다.
finishOnTaskLaunch
  clearTaskOnLaunch와 유사하나 이 속성은 하나의 activity에만 유효하다. root activity를 포함하여 현재 세션인 경우에만 살아있고 task를 떠나면 clear된다

댓글
2010.05.31 12:59:47
yally

도움이 될지 모르겠지만..

저같은 경우에는 singleTask와 clearTasgOnlaunch 속성을 home이 되는 activity에만 지정하여 

사용했었습니다..

댓글
2010.05.31 19:16:11
안드로메다로달리기

yally님 무슨 말씀을 그렇게 하셔요.ㅎㅎ
엄청 많이 많이 도움이 됩니다. 
저같은 생초보에게는 꿀같은 단비입니다.  ㅋ
우선 singleTask사용하는 Activity를 줄여봐야겠군요. 
singleTask로 하면 Task가 하나 더 생겨서 실행되는 Activity가 Root로 가는 것으로 예상이 되네요. 
그래서 흠.. 처음에 실행하는 것만 singleTask와  clearTaskOnLaunch속성을 넣어서 해보겠습니다. 
잘 조합하면 될 듯 한데... 안되네요. ㅎㅎ
Home키만 처리할 수 있으면 이런 고민 안해도 될텐데요.. 
아쉽네요. ㅎㅎ 그럼 즐거운 하루 되시고요. 앞으로도 자주 도와 주셔요. ㅋ
또 열심히 해보고 해결한 다음 다시 올리겠습니다. 언젠가는 되겠죠? ㅎㅎ

삭제 수정 댓글
2010.06.05 16:09:07
혜마
HOME키를 가로챌 수는 없지만, HOME키가 눌렸는 지 여부는 확인 할 수 있습니다.

해당 Activity의 startActivity (startActivityForResult..) / finish / startService 등을 override하여

해당 task가 유지되는 case를 제외하고,

onUserInteraction / onUserLeaveHint 등을 override하여

시스템에서 task를 switch하는 case (전화수신등)을 제외하고,

onPause / onStop 에서 HOME키가 눌렸다고 볼 수 있습니다.
__
혜마


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


출처: 
http://stackoverflow.com/questions/6693896/home-key-press-event-listener

Possible Duplicate:
How can I detect user pressing HOME key in my activity?

I am using below lines of code to find if the use press the backkey from android phone,its working fine .

But I want to detect home key Button press event,Anyone can guide how it is possible ?

@Override
public void onBackPressed() 
{
    Toast.makeText(getApplicationContext(),"BackKeyPressed", Toast.LENGTH_LONG).show();
    super.onBackPressed();
}

Thanks . . .

share|improve this question

50% accept rate
1 
What do you want to do when home button is clicked? – LordTwaroog Jul 14 '11 at 13:31
take a look at my answer below, it may work for you dependent on what you want to do when you detect that it's happened. – Idistic Jul 14 '11 at 19:12
feedback

closed as exact duplicate by Tim Post Sep 19 '11 at 9:01

This question covers exactly the same content as earlier questions on this topic; its answers may be merged with another identical question. See the FAQ for guidance on how to improve it.

You cannot "detect home key Button press event", sorry.

share|improve this answer
Hi Joel Martinez I want to save newly reset Options of user.I have a option screen,when user changes its old options setting and go on Mobile Main Home screen I want to save newly changed values at that time .... – aftab Jul 14 '11 at 13:35
2 
@aftab: Then "save newly changed values" in onPause() of your activity. That will cover BACK, HOME, the user getting a phone call, the user tapping on a Notification, the user long-pressing HOME and going back to some other application, etc. – CommonsWare Jul 14 '11 at 13:37
thanks,But I test it with peer view,I override all onResume,OnPostResume,OnStart and Restart of my activity,I notice when control comes in my activity for the 1st time it goes on onResume method and when I press Home key it go onStop method not on onResume method,means when I press Home button it does not go in onResume method . . . – aftab Jul 14 '11 at 14:02
why do you want to run onResume method when you press Home key? if you want to do something when you press Home key, overide onPause() method.. although the app still minimized after that. – Tek Yin Jul 14 '11 at 17:35
@CommonsWare - technically your correct but you can get a pretty good idea that when it happens, not 100% full proof (well it's always worked for me but ... ) which may or may not meet the needs of the poster above, see my answer below. – Idistic Jul 14 '11 at 19:11
show 2 more comments
feedback

While technically the people who responded are correct here is a simplistic way to detect the home key press by monitoring two events in your activity, it has worked for my simple needs and maybe it will work for yours as well.

I use a 100ms fence around the two events which I find always works for me. NOTE: I have only tested on a handful of phones, like all things in Android your mileage will vary dependent on OS / Hardware (heck even the stuff that's documented and supposed to work sometimes doesn't)

long userInteractionTime = 0;

@Override
public void onUserInteraction() {
    userInteractionTime = System.currentTimeMillis();
    super.onUserInteraction();
    Log.i("appname","Interaction");
}

@Override
public void onUserLeaveHint() {
    long uiDelta = (System.currentTimeMillis() - userInteractionTime);

    super.onUserLeaveHint();
    Log.i("bThere","Last User Interaction = "+uiLag);
    if (uiDelta < 100)
        Log.i("appname","Home Key Pressed");    
    else
        Log.i("appname","We are leaving, but will probably be back shortly!");  
}
share|improve this answer
This strikes me as being unreliable. Anything that involves subtle timing is going to be prone to failure some percentage of the time. Moreover, I would consider any application that needs to handle the HOME button separately from other events to be broken -- there should be no difference between HOME, an incoming phone call, an alarm clock alarm, etc. – CommonsWare Jul 14 '11 at 19:14
@CommonsWare As to your last point perhaps, I kind of agree but then again my needs have to do with analytic's, not behavior, still I am not going to say outright that there is no other reason to use it. – Idistic Jul 14 '11 at 19:27
@CommonsWare - As to timing that was my first thought also, but after testing it pretty extensively in an attempt to break it I could not, that does not mean it is 100% reliable of course, could be any number of untested scenarios that would result in a fail. After some thought I don't think the timing is that subtle since the home key generates that first event, then the second, again it could fail and I certainly would not depend on it for anything critical. Typically in my testing the delta between the two events is 1 or 2 ms as reported by the system timer. – Idistic Jul 14 '11 at 19:32
"my needs have to do with analytic's, not behavior" -- ah, OK. For that, even if you are +/- on events occasionally, you're probably OK. – CommonsWare Jul 14 '11 at 20:28
@Idistic thanks for new idea.your solution looking quite ok,But its onUserInteraction() method working for Back-key press or when I scroll-over the UI,its not working when press the home key I moves among the different tabs,2nd in Debug mode control not go into onUserLeaveHint() method in any case. – aftab Jul 16 '11 at 9:33
show 1 more comment
feedback

No, it is not possible. From the documentation of the Home keycode:http://developer.android.com/reference/android/view/KeyEvent.html#KEYCODE_HOME

public static final int KEYCODE_HOME

Key code constant: Home key. This key is handled by the framework and is never delivered to applications.

share|improve this answer
hi videre thanks,I just read a page from discussion as on below URL,Read the make dg comments on page,but I am not understanding what he/she saying in his/her comments , groups.google.com/group/android-developers/browse_thread/thread/… – aftab Jul 14 '11 at 13:40
He is saying that you can simulate the EFFECT of pressing the home button, setting the right action and category on your intent. It is not relevant to you because you want to REACT to a click on the home button. – Videre Jul 14 '11 at 14:09



/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

출처: http://kimeunseok.com/archives/1006

안드로이드에서 기본적으로 사용자가 홈 키나 파워키는 핸들링 할 수 없도록 되어있습니다. 이는 플랫폼 상에서 개발자가 악의적인 용도로 사용하는 것을 미연에 방지하기 위함인데 커널 단에서는 이런 부분 역시 수정이 가능합니다, 보안이나 기타적인 이유로 중요하다고 판단되는 키들은 framework layer에서 핸들링할 수 있습니다.

Path는 frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java이고 해당 파일을 열어보면 아래와 같은 코드가 존재합니다.

if (keyCode == KeyEvent.KEYCODE_HOME) {

            if (!down) {
                final boolean homeWasLongPressed = mHomeLongPressed;
                mHomePressed = false;
                mHomeLongPressed = false;
                if (!homeWasLongPressed) {
                    try {
                        IStatusBarService statusbar = getStatusBarService();
                        if (statusbar != null) {
                            statusbar.cancelPreloadRecentApps();
                        }
                    } catch (RemoteException e) {
                        Slog.e(TAG, “RemoteException when showing recent apps”, e);
                        mStatusBarService = null;
                    }
                    mHomePressed = false;
                    if (!canceled) {
                        boolean incomingRinging = false;
                        try {
                            ITelephony telephonyService = getTelephonyService();
                            if (telephonyService != null) {
                                incomingRinging = telephonyService.isRinging();
                            }
                        } catch (RemoteException ex) {
                            Log.w(TAG, “RemoteException from getPhoneInterface()”, ex);
                        }
                        if (incomingRinging) {
                            Log.i(TAG, “Ignoring HOME; there’s a ringing incoming call.”);
                        } else {
                            launchHomeFromHotKey();
                        }
                    } else {
                        Log.i(TAG, “Ignoring HOME; event canceled.”);
                    }
                    return -1;
        }
}

 

위 코드를 보면 홈 버튼에 대한 액션이 들어왔을 때 launchHomeFromHotKey()라는 함수를 호출하는데 이 함수를 다시 살펴보면 mKeyguardMediator.verifyUnlock() 를 다시 호출합니다. 여기서 if (!mUpdateMonitor.isDeviceProvisioned())가 T/F이냐에 따라 Home Key에 대한 처리가 이루어지는데 무조건 false를 return하게 되면 Home key에 대한 액션은 무시하게 됩니다!

단순히 홈키 하나를 핸들링 하기 위해 위와 같은 작업을 하는 것은 상당히 무모한 일이지만, 어쩌면 어플을 개발하는 분들의 입장에서 Home과 Power 키를 핸들링 할 수 없을까라는 고민들을 많이 하시는 것 같아 최악이지만, 유일한 방법을 소개해드려 봅니다~안드로이드 커널을 만진지 얼마되지 않았는데 다양한 분야에서 사용할 수 있을 것 같다는 생각이 드네요!



///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


출처: http://gogorchg.tistory.com/entry/Android-%ED%99%88%ED%82%A4-%EB%88%8C%EB%A0%80%EC%9D%84-%EB%95%8C-%EC%B2%98%EB%A6%AC

오늘 머리가 도저히 안돌아가서.. 안드로이드 펍에서 돌아다니다가 알게되었습니다.

전엔 홈키를 어떻게 처리할 방도를 몰라서
 
OnResume에 플래그값을 줘서 했었는데..

엄청 유용한 함수가 있네요.

void Activity.onUserLeaveHint ()

 

이 메서드는 사용자에 의해 액티비티가 백그라운드로 전환되기 직전에 onPause 바로 앞에 호출된다. Home 키를 누르기 직전에 호출되며 Back키를 누르거나 전화 통화 앱이 올라올 때, 타이머에 의해 종료될 때는 호출되지 않는다. Home키는 키입력 이벤트로 전달되지 않아 검출이 어려운데 이 메서드가 호출될 때 Home키에 의해 백그라운드가 됨을 알 수 있다. 이 두 메서드는 상태란의 통지를 관리할 때 사용될 수 있으며 액티비티가 통지를 취소할 시점을 결정하는데 도움을 준다. 다음 예제는 사용자가 5초 이상 관심을 보이지 않으면 즉시 종료한다.

 
출처: http://www.androidpub.com/?mid=android_dev_qna&document_srl=1694637&rnd=1694734#comment_1694734 

저같은고민 안하시길 바랍니다^^


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

출처: http://www.androidpub.com/?mid=android_dev_qna&document_srl=1694637&rnd=1694734#comment_1694734


화면 A,B,C,D,E가 있습니다  (물론 각 화면에는 또 다시 서브 화면이 여러개 있습니다)

 

홈키를 눌러 밖으로 나갔다가

 

다시 돌아오면.... 무조건 E화면이 우선 보이게 하려 합니다. (패스워드 묻는 화면임)

 

그런데 잘 안되네요...

 

제가 해본 방법은

 

1. onResume 이용

     onResume에 화면E를 불러오는걸 넣어봤습니다 ---> 화면 전환 할때 마다 E화면이 뜨더군요 .ㅠㅠ

 

2. onFocusChanged이용

     이것 역시 포커스가 벗어날때 마다 발생하므로 위의1번과 같은 결과가져옴

 

3. onKeyDown이용

    onKeyDown에서 홈키를 눌렀을때... 우선E 화면을 띄워 놓고 나가면 돌아올때 무조건 E화면이 뜨지 않을까 해서 시도해봤습니다만..

   E화면이 안뜨네요.. ㅠ.ㅠ

 

고수님들 무슨 방법이 없을련지요~!..

  

 

 

 


 
댓글
2011.08.08 15:53:33
그렇다고 하네요

void Activity.onUserLeaveHint ()

 

이 메서드는 사용자에 의해 액티비티가 백그라운드로 전환되기 직전에 onPause 바로 앞에 호출된다. Home 키를 누르기 직전에 호출되며 Back키를 누르거나 전화 통화 앱이 올라올 때, 타이머에 의해 종료될 때는 호출되지 않는다. Home키는 키입력 이벤트로 전달되지 않아 검출이 어려운데 이 메서드가 호출될 때 Home키에 의해 백그라운드가 됨을 알 수 있다. 이 두 메서드는 상태란의 통지를 관리할 때 사용될 수 있으며 액티비티가 통지를 취소할 시점을 결정하는데 도움을 준다. 다음 예제는 사용자가 5초 이상 관심을 보이지 않으면 즉시 종료한다.


위의 메서드를 사용하시어서 홈키로 정지 상태인것을 확인이 가능하실 것입니다.

추후 onResume() 에서 홈키로 종료 되었다는 boolean 형식의 플래그 하나 사용 하심은 어떠신지요??

댓글
2011.08.08 16:12:36
PeterMan

@그렇다고 하네요

와우~! 이런게 있었군요.... 정말 고맙습니다.

지푸라기라도 잡을 심정에서.. 통나무를 잡은듯 합니다..

우선 해봐야겠네요... 감사요~~!

 

댓글
2011.08.08 16:14:54
[GS]BOB

오!! 좋은 정보 ^^ 감사! ㅋ

댓글
2011.08.08 16:25:00
PeterMan

@그렇다고 하네요

음~! 방금 해봤습니다만....뜻대로 안되네요.. 이유인즉

 

"onUserLeaveHint 메서드가 호출되었다는 것은 아직 액티비티가 살아는 있지만 잠시 백그라운드로 전환되었다는 뜻이다."

출처 : http://www.winapi.co.kr/android/annex/19-3.htm

 

저의 경우는 A~D화면 각각에 onUserLeave를 넣어줬습니다.

Home로 나갔다가 들어왔을때 E가 실행되기에.. 성공이구나 생각했는데...

ABCD화면 전환 할때 마다 E가 불러지더군요... (이유는 위에 적어놨습니다.)

 

결과적으론 안되었지만... 아무튼 좋은거 하나 배워 갑니다 감사합니다~!

댓글
2012.04.17 13:12:52
스페이스양

이 부분은.. 슬립모드시에도 문제가 됩니다.


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

출처: http://www.winapi.co.kr/android/annex/19-3.htm

3.전원 관리

1.화면 유지

항상 안정적인 전원에 연결되어 있는 PC와는 달리 모바일 장비는 배터리에만 의존하므로 전원 절약은 모두가 관심을 가져야 할 치명적인 문제이다. 앱은 불필요한 동작을 최대한 자재하며 시스템은 사용자가 관심을 가지지 않을 때 화면이나 키보드 조명을 냉큼 차단하고 WiFi 네트워크 연결도 무자비하게 끊어 버리며 심지어 일정 시간이 지나면 CPU까지도 잠재워 버린다. 스크린 세이버가 반 강제적으로 적용되며 매번 화면을 다시 켜야 하는 불편함이 있지만 사용자들도 너그럽게 이해하는 편이다.

모든 앱이 전원 절약에 협조적인데 비해 배터리를 아무리 많이 소모하더라도 CPU나 화면을 강제로 유지해야 하는 특수한 앱도 존재한다. 대표적인 예가 동영상 재생기인데 영화를 감상하는 중에 배터리 아끼자고 화면을 꺼 버릴 수는 없는 노릇이다. 네비게이션이나 DMB 등 사용자가 지속적으로 화면을 봐야 하는 앱은 화면 유지가 필수적이며 카메라나 카운터 처럼 자주 화면을 봐야 하는 프로그램도 사정은 비슷하다. 백그라운드 작업을 하는 앱은 화면이 꺼지더라도 CPU는 계속 동작해야 한다.

장비의 전원은 시스템이 설정값에 따라 자동으로 관리하지만 일시적으로 예외를 적용해야 하는 경우가 예상외로 빈번하다. 배터리 먹는 하마라는 악평을 듣더라도 기능의 특성상 본질적으로 전원을 소모할 수밖에 없다. 이럴 때는 장비의 전원을 관리하는 PowerManager 클래스로 별도의 정책을 임시적으로 적용한다. 시스템 서비스이므로 객체를 따로 생성할 필요없이 다음 호출문으로 쉽게 얻을 수 있다.

 

getSystemService(Context.POWER_SERVICE);

 

전원 관리자 자체는 몇 가지 유틸리티 메서드만 제공할 뿐 전원을 관리하는 기능이 없으므로 다음 메서드를 호출하여 WakeLock 객체를 생성한다. WakeLock 객체는 이름 그대로 장비가 계속 깨어 있도록 잠그는 역할을 한다. 즉, 여기서 잠근다(Lock)의 의미는 끈다는 것이 아니라 화면이나 CPU가 켜진 상태를 유지하도록 강제한다는 뜻이다.

 

PowerManager.WakeLock newWakeLock (int flags, String tag)

 

WakeLock 객체를 생성할 때 플래그 인수를 지정함으로써 이후의 전원 관리 수준이 결정된다. 두번째 인수 tag는 디버깅용 정보로만 사용되므로 큰 의미는 없으며 로그상에서 구분 가능한 이름만 부여하면 된다.

 

잠금수준

CPU

화면

키보드 조명

PARTIAL_WAKE_LOCK

부분적 동작

SCREEN_DIM_WAKE_LOCK

동작

흐리게 

SCREEN_BRIGHT_WAKE_LOCK

동작

밝게 

FULL_WAKE_LOCK

동작

밝게 

 

아래쪽으로 내려올 수록 잠금의 강도가 높아지며 배터리 사용량도 비례해서 늘어난다. CPU만 계속 가동하고 싶다면 PARTIAL_WAKE_LOCK으로도 충분하며 화면이나 키보드까지 필요하면 더 높은 잠금 수준을 적용해야 한다. 잠금 수준 외에 화면 관리 방식에 대한 두 개의 옵션을 OR 연산자로 연결하여 추가로 더 지정할 수 있다. 두 플래그는 화면에 대한 옵션이므로 CPU만 동작하는 PARTIAL_WAKE_LOCK에서는 아무 효과가 없다.

 

■ ACQUIRE_CAUSES_WAKEUP : 화면 잠금 기능은 켜진 화면을 계속 유지하게만 할 뿐이지 꺼진 화면을 켜지는 않는다. 이 플래그를 지정하면 화면이나 키보드 조명을 강제로 켠다. 알람이나 착신 통화처럼 사용자에게 즉시 통보를 하는 앱에 적합하다.

■ ON_AFTER_RELEASE : 화면 잠금이 끝난 후에 화면 타이머를 리셋한다. 잠금이 끝난 후부터 설정의 화면 켜짐 시간만큼은 계속 유지함으로써 화면이 켜진 시간을 좀 더 연장하는 효과가 있으며 잠금과 풀림을 반복할 때 화면이 너무 빨리 꺼지지 않도록 한다.

 

WakeLock 객체는 전원 관리 방식에 대한 정보만 가질 뿐이어서 이 객체를 생성한다고 해서 바로 잠금이 동작하는 것은 아니다. 객체를 미리 생성해 놓고 필요할 때 다음 메서드로 잠금과 해제를 지시한다. 여러 개의 잠금 객체를 만들어 놓고 선택적으로 사용하는 것도 물론 가능하다.

 

void acquire ([long timeout])

void release ()

boolean isHeld ()

 

acquire 메서드를 호출하면 이후부터 객체의 설정 정보대로 전원이 관리된다. timeout 인수는 잠금을 자동으로 풀 시간을 지정하는데 생략시는 별도의 지시가 있을 때까지 잠금이 유지된다. release는 잠금을 해제하며 isHeld 메서드는 현재 잠금 상태인지 아닌지를 조사한다. acquire를 호출한 이후부터 release를 호출할 때까지 CPU, 화면, 키보드 조명이 유지된다고 할 수 있다. 이 기능을 사용하려면 다음 퍼미션이 필요하다.

 

<uses-permission android:name="android.permission.WAKE_LOCK" />

 

화면을 강제로 유지하는 것은 배터리 비용을 유발하므로 특별한 퍼미션을 요구한다. 다음 예제는 별다른 작업은 하지 않지만 시스템 설정에 상관없이 화면을 항상 켜진 채로 유지한다.

 

hard_WakeAlways

public class hard_WakeAlways extends Activity {

     PowerManager mPm;

     WakeLock mWakeLock;

     public void onCreate(Bundle savedInstanceState) {

          super.onCreate(savedInstanceState);

          setContentView(R.layout.hard_wakealways);

 

          mPm = (PowerManager)getSystemService(Context.POWER_SERVICE);

          mWakeLock = mPm.newWakeLock(PowerManager.FULL_WAKE_LOCK,

                   "hard_WakeAlways");

     }

 

     protected void onResume() {

          super.onResume();

          mWakeLock.acquire();

     }

 

     protected void onPause() {

          super.onPause();

          if (mWakeLock.isHeld()) {

              mWakeLock.release();

          }

     }

}

 

레이아웃에는 기능을 안내하는 텍스트 뷰 하나가 배치되어 있고 코드도 지극히 간단하다. 실행해 봤자 텍스트 뷰 하나만 나올 뿐이지만 화면이 꺼지지 않는다는 면에서 다른 앱과 다르다.



onCreate에서 WakeLock 객체를 생성하되 CPU, 화면, 키보드 조명을 모두 켜 두는 최상위의 잠금으로 설정했다. 액티비티가 시작되는 onResume에서 잠그고 백그라운드로 전환되는 onPause에서 해­제하므로 액티비티가 실행중인 동안에는 화면이 항상 유지된다. 시스템 설정과 무관하게 화면이 항상 켜질 것이며 액티비티를 종료하면 시스템의 설정대로 화면 타이머가 동작한다.

WakeLock 객체는 화면 가용성을 높여준다는 면에서는 편리하지만 배터리 수명에는 중대한 영향을 끼치므로 꼭 필요할 때만 가급적 짧게 사용해야 한다. 위 예제에서는 편의상 액티비티 실행중인 동안 계속 유지하도록 했지만 작업 시작할 때 켰다가 작업 끝난 후 가급적 빨리 해제하는 것이 바람직하다. 동영상 재생기의 경우 동영상을 실제로 재생하지 않을 때는 굳이 잠금을 유지할 필요가 없다. 다음은 PowerManager 클래스의 전원 관리 기능 메서드들이다.

 

boolean isScreenOn ()

void goToSleep (long time)

void reboot (String reason)

void userActivity (long when, boolean noChangeLights)

 

화면의 켜짐을 조사하거나 즉시 화면을 끄거나 재부팅하는 등의 기능을 제공한다. 화면을 강제로 끄는 goToSleep 메서드는 전원 버튼을 누르지 않아도 프로그램이 소프트웨어적으로 슬립 모드로 들어갈 수 있어 실용성이 있다. 그러나 아무나 사용할 수 있는 메서드는 아니므로 엄격한 제한이 따른다. 이 메서드를 사용하려면 DEVICE_POWER 퍼미션이 필요하며 또 시스템 앱으로 서명을 해야 한다.

참고로 WakeLock과 유사한 개념의 WifiLock 도 제공된다. 대기 모드로 들어가면 WiFi 네트워크는 자동으로 꺼지는데 이 상태에서 백그라운드 통신을 수행하면 3G 데이터 사용량이 많아지는 문제가 있다. 대기 모드에서도 WiFi를 계속 유지하려면 WifiLock 객체를 사용하며 방법은 WakeLock과 거의 동일하다.

2.독서 도우미

독서 도우미는 책 읽는 것을 도와주는 간단한 유틸리티 프로그램이다. 시작 페이지, 끝 페이지 그리고 각 페이지를 읽을 시간을 미리 입력해 두면 역 카운터를 세면서 빨리 읽어라고 제촉함으로써 일정한 속도로 책을 읽도록 한다. 전에 윈도우즈용으로 만들었던 것인데 도서관에서 사용할 수 있도록 모바일용으로 포팅해 보았다.

무슨 놈의 책을 시간 재가며 읽는가 싶겠지만 따분한 기술 서적이나 원서처럼 의무적으로 읽어야 하는 책은 그럴 필요가 있다. 내용이 지루해서 읽다 보면 책장은 넘어가는데 뭘 읽었는지 머리 속에는 아무 것도 남아 있지 않다거나 30분째 같은 페이지에서 노닥거리기 십상이다. 이럴 때는 목표량을 정해 놓고 읽으면 긴장도를 높일 수 있으며 나름대로 책 읽는 재미도 있어서 본인은 아주 실용적으로 잘 사용하고 있다.

독서뿐만 아니라 일정한 시간 간격으로 해야 할 작업이 있을 때도 나름대로 유용하다. 1시간에 밤 60개를 까야 한다거나 30초에 아빠 흰머리를 하나씩 뽑아 홈 아르바이트를 할 때 실용적이다. 실생활에서나 개발 현장에서나 단순 반복 작업을 해야 할 경우는 예상외로 많은데 시간을 재 가며 진행하면 딴짓거리를 안하게 되고 짧은 시간에 과업을 완수할 수 있어 효율이 증가하고 신바람도 난다.

이 프로그램의 구조나 논리는 아주 단순해서 더 설명이 필요없을 정도다. 시작, 끝 범위 입력받고 타이머 돌리며 역카운트만 해 주면 그만이다. 그러나 모바일 환경에서는 카운트를 하는동안 화면이 꺼져 버려 카운트를 계속 볼 수 없는 문제가 있으며 그렇다고 이 프로그램을 쓸 때만 설정을 조정하기도 귀찮다. 이럴 때 사용하는 기능이 바로 WakeLock이며 앞 예제와 동일한 코드를 사용한다.

 

hard_ReadingCounter

==== 소스 생략 ====

 

레이아웃을 잡는 방법, 입력받은 값의 유효성을 점검하는 방법, 페이지 넘길 때마다 소리를 내고 옵션값을 프레퍼런스에 저장하는 코드 등이 포함되어 있어 예제치고는 코드가 꽤 긴 편이다. 책 읽다가 갑자기 뱃속에서 긴급 신호가 오는 예외 사항을 고려하여 잠시 중지 기능도 애써 작성해 넣었다. 특별히 어려운 논리는 없으므로 지면 절약을 위해 소스 덤프는 생략했다. 주석도 많이 달아 놨으므로 직접 분석하기에 전혀 무리가 없을 것이다. 실행 모습은 다음과 같다.






가급적이면 배터리를 아끼기 위해 어두운 색상을 사용했다. 표준 위젯만 사용해서 UI가 그다지 예뻐 보이지는 않지만 나름대로 실용성있게 만들었으며 본인은 이 예제를 종종 애용한다. 페이지 넘길 때마다 현재 페이지를 예쁘장한 소녀 음성으로 알려 주면 좀 더 활용성이 높아질 것이다. 유료 앱으로 출시해볼까 하다가 돈 내고 쓸 사람은 드물 것 같아 그냥 관두기로 했다. 여기서 소개하고자 하는 것은 이 예제처럼 화면을 항상 유지할 필요가 있을 때 WakeLock 기능을 사용하라는 것이다.

3.사용자 액션 추출

WakeLock 객체는 화면을 켜 둘 수 있어서 편리하기는 하지만 배터리 사용 측면에서는 부작용이 있다. 모바일 장비에서 배터리를 가장 많이 소모하는 부품이 액정이어서 불과 한시간만 켜 놓아도 배터리가 다 소진된다. 기능 구현상 불가피하게 배터리를 소모하는 것은 상관없지만 실수로 켜 둔채로 방치하거나 또는 관리 소홀이나 예외로 인해 잠금을 풀지 않아 배터리가 방전되어 버리면 이는 치명적이다.

카메라의 경우 사진을 찍으려고 대기하는 중에 화면이 꺼져 버리면 곤란해져 보통 촬영중에는 화면을 켜 둔다. 그러나 사용자가 카메라를 켠 둔 채로 그대로 방치했다거나 또는 미스 터치로 인해 카메라가 기동되었다면 의도하지 않게 배터리가 방전될 것이다. 비록 사용자가 허락을 했더라도 일정한 시간동안 사용자가 관심을 가지지 않는다면 잠금을 해제하고 슬립 모드로 들어가도록 허락하는 것이 안전하다.

그렇다면 지금 사용자가 프로그램을 조작하고 있는 중인지, 방치 상태인지는 어떻게 구분할 수 있을까? 이전 버전에서는 onKeyDown이나 onTouchEvent 등이 호출될 때를 감지하여 사용중임을 알아냈었다. 그러나 이 방식은 완벽하지도 않고 여러 군데서 체크를 해야 하므로 불편하기도 하다. 트랙볼이 있는 장비는 트랙볼도 감시해야 하며 뷰 계층이 복잡하면 입력을 받는 모든 뷰를 다 감시해야 한다. 이런 불편함을 해소하기 위해 1.5 버전부터 다음 메서드가 추가되었다.

 

void Activity.onUserInteraction ()

 

이 메서드는 키입력이나 터치 입력, 트랙볼 이벤트가 발생할 때마다 호출된다. 어떤 키를 눌렀는지, 화면의 어디를 눌렀는지에 대한 추가 정보는 없으며 단지 사용자가 기기를 조작하고 있는 중이라는 것만 알려줄 뿐이다. 여러 군데서 조사해야 하는 번거로운 작업을 한 메서드에서 일괄적으로 처리할 수 있어 편리하고 완벽하다. 다음 메서드도 유사한 이유로 1.5 버전에서 새로 추가되었다.

 

void Activity.onUserLeaveHint ()

 

이 메서드는 사용자에 의해 액티비티가 백그라운드로 전환되기 직전에 onPause 바로 앞에 호출된다. Home 키를 누르기 직전에 호출되며 Back키를 누르거나 전화 통화 앱이 올라올 때, 타이머에 의해 종료될 때는 호출되지 않는다. Home키는 키입력 이벤트로 전달되지 않아 검출이 어려운데 이 메서드가 호출될 때 Home키에 의해 백그라운드가 됨을 알 수 있다. 이 두 메서드는 상태란의 통지를 관리할 때 사용될 수 있으며 액티비티가 통지를 취소할 시점을 결정하는데 도움을 준다. 다음 예제는 사용자가 5초 이상 관심을 보이지 않으면 즉시 종료한다.

 

hard_UserInteraction

public class hard_UserInteraction extends Activity {

     public void onCreate(Bundle savedInstanceState) {

          super.onCreate(savedInstanceState);

          setContentView(R.layout.hard_userinteraction);

     }

 

     protected Handler mFinishHandler = new Handler() {

          public void handleMessage(android.os.Message msg) {

              finish();

          }

     };

 

     void registerFinish() {

          mFinishHandler.sendEmptyMessageDelayed(0, 5 * 1000);

     }

 

     void unRegisterFinish() {

          mFinishHandler.removeMessages(0);

     }

 

     void RefreshFinish() {

          unRegisterFinish();

          registerFinish();

     }

 

     protected void onResume() {

          super.onResume();

          registerFinish();

     }

 

     protected void onPause() {

          unRegisterFinish();

          super.onPause();

     }

 

     public void onUserInteraction() {

          super.onUserInteraction();

          RefreshFinish();

     }

 

     protected void onUserLeaveHint () {

          super.onUserLeaveHint();

          Toast.makeText(this, "Leave by user", Toast.LENGTH_LONG).show();

     }

}

 

mFinishHandler는 메시지를 받자 마자 액티비티를 즉시 종료하도록 되어 있다. 지연된 시간을 지정하여 이 핸들러로 메시지를 보내 놓으면 잠시 후 종료될 것이다. registerFinish 메서드는 5초 후에 메시지를 보내 종료를 예약하며 unRegisterFinish는 큐에 쌓인 메시지를 제거하여 예약을 해제한다. RefreshFinish는 두 메서드를 순서대로 호출하여 취소 후 재예약함으로써 종료 시점을 리셋하는 역할을 한다.

onResume에서 종료를 예약하고 onPause에서 예약을 취소하여 별다른 조치가 없으면 실행 직후 5초가 지나면 종료될 것이다. 이를 방지하기 위해 사용자의 입력을 있을 때 종료 예약을 리셋해야 하는데 이 작업을 할만한 적당한 위치가 바로 onUserInteraction 메서드이다. 터치, 키, 트랙볼 중 어떠한 입력이라도 들어오면 호출된다. 이때마다 예약을 리셋하면 종료 시점을 지속적으로 연장할 수 있다.

예제를 실행해 놓고 5초간 가만히 있으면 종료되지만 화면을 계속 두드리거나 키를 누르면 종료가 연기된다. 그러나 터치한 상태로 이동하거나 터치를 뗄 때는 이 메서드가 호출되지 않는다. 만약 다른 터치 이벤트에 대해서도 종료되지 않도록 하려면 onTouchEvent에서도 리셋 처리를 해야 한다. 예제에서는 테스트의 편의상 5초로 설정했는데 카메라의 경우 1분 정도로 설정해 놓고 사용자가 1분 이상 촬영을 하지 않으면 자동 종료하는 식으로 활용 가능하다.

Home키를 눌러 액티비티를 빠져 나가면 onUserLeaveHint 메서드가 호출되어 토스트가 출력될 것이다. Back키를 누르거나 액티비티 스스로 finish를 호출했을 때는 토스트가 나타나지 않는다. 즉 onUserLeaveHint 메서드가 호출되었다는 것은 아직 액티비티가 살아는 있지만 잠시 백그라운드로 전환되었다는 뜻이다.