기획자가 원하는 대로 액티비티를 띄우고, 이동하고, 점프하는 방법에 대해 알아본다.


[관련글 링크]
1. Activity Jump #1 "홈 액티비티로 이동하기"
2. Activity Jump #2 "액티비티 스택에 없었던 메인액티비티로 이동하기"


[목표]
1번 글에서는 어느 액티비티에서든 홈 액티비티로 이동하는 방법에 대해 정리해봤다.

이번 글에서는 시작 액티비티가 기획자가 요구하는 UI흐름의 중간인 경우. 그래서 시작 액티비티에서 [이전] 키를 눌렀을 때, 안드로이드 홈스크린이 아닌 UI흐름 상의 액티비티를 보여줘야 하는 경우에 대해 알아본다.

그림으로 표현하면 다음과 같다.


안드로이드 홈스크린에서 "위젯" 또는 "실행 아이콘"을 눌렀을 때, 액티비티 B를 보여주는 것. 또한, [이전]의 의미가안드로이드 홈스크린이 아닌, 한 번도 띄운적 없는(액티비티 스택에 존재하지 않는) Activity A인 경우 어떻게 구현해야 할까?


[구현하기]

다음과 같이 액티비티 4개를 준비한다.



우선, AndroidManifest.xml을 수정하여, Activity B를 시작액티비티로 지정해 준다.
이렇게 하면 안드로이드홈에서 아이콘을 클릭하면 제일 먼서 Activity B가 보여진다.
당연히 액티비티 스택에는 Activity B 만 쌓여있는 상태가 된다.


<activity
          android:name=".ActivityJumpDemoActivity"
          android:label="@string/app_name">
</activity>
<activity android:name="ActivityA" 
	android:configChanges="orientation" 
	android:screenOrientation="sensor">
</activity>
<activity android:name="ActivityB" 
	android:configChanges="orientation" 
	android:screenOrientation="sensor">
	<intent-filter>
		<action android:name="android.intent.action.MAIN" />
		<category android:name="android.intent.category.LAUNCHER" />
	</intent-filter>
</activity>
<activity android:name="ActivityC" 
	android:configChanges="orientation" 
	android:screenOrientation="sensor">
</activity>
*맨 아래 링크되어 있는  전체 코드는 이전 글을 기준으로 구현되어 있어서 이 부분이 적용이 되어 있지 않다. 테스트 해보려면 위의 내용을 수정해서 테스트해야 한다.


이제 Activity B에서 [이전]키를 눌렀을 때,
Activity A를 보여주려면 Activity B에 onKeyUp(...)을 구현해준다. 
나머지 액티비티들도 띄워줄 액티비티를 변경/적용해준다.
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
	if (keyCode == KeyEvent.KEYCODE_BACK) {
		Intent intent = new Intent(getBaseContext(), ActivityA.class);
		startActivity(intent);
		finish();
		return true;
	}
	return super.onKeyDown(keyCode, event);
}
Line 3
"KeyEvent.KEYCODE_BACK" [이전]키가 눌렸을 때를 처리한다.
Line 4 : [이전]키가 눌렸을 때 보여줄 ActivityA.class를 지정한다.
Line 6 : 현재 창은 종료시켜 액티비티 스택에서 깔끔히 없앤다.

이렇게 구현된 상태에서 "안드로이드홈->B액티비티->[이전]키->A액티비티"의 흐름은 정상적으로 동작한다.


* 안드로이드홈->B액티비티->[이전]키->A액티비티 후 스택 확인

  Running activities (most recent first):

    TaskRecord{300bdd60 #5 A com.juno.activityjump.demo}

      Run #1: HistoryRecord{3012fe80 com.juno.activityjump.demo/.ActivityJumpDemoActivity}

    TaskRecord{2fe0c3e8 #2 A com.lge.launcher}

      Run #0: HistoryRecord{300d62c0 com.lge.launcher/.Launcher}



그런데, 문제가 있다.
위와 같이 액티비티 마다 onKeyUp(...) 별도로 구현해 놓으면, [이전]키가 눌렸을 때 항상 새롭게 액티비티를 띄우게 된다.
만약 "메인->A->메인"를 반복하면, A액티비티는 finish()로 종료되지만, 스택에 있었던 녀석을 놔두고 새롭게 메인액티비티를 띄우게 된다. 즉, 메인액티비티가 여러 벌이 생기고 메모리에 계속 남게 된다.


* "메인->A->[이전]키->메인"를 두 번 반복했을 때의 스택 확인

  Running activities (most recent first):

    TaskRecord{301628a0 #6 A com.juno.activityjump.demo}

      Run #3: HistoryRecord{30311070 com.juno.activityjump.demo/.ActivityJumpDemoActivity}

      Run #2: HistoryRecord{301e5650 com.juno.activityjump.demo/.ActivityJumpDemoActivity}

      Run #1: HistoryRecord{301c5ea8 com.juno.activityjump.demo/.ActivityJumpDemoActivity}

    TaskRecord{2fe0c3e8 #2 A com.lge.launcher}

      Run #0: HistoryRecord{300d62c0 com.lge.launcher/.Launcher}


이를 해결하는 방법은
"1. Activity Jump #1 "홈 액티비티로 이동하기" 글에서 소개한 인텐트 플래그를 동일하게 사용하면 해결된다.

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
	if (keyCode == KeyEvent.KEYCODE_BACK) {
		Intent intent = new Intent(getBaseContext(), ActivityJumpDemoActivity.class);
		intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
		intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
		startActivity(intent);
		finish();
		return true;
	}
	return super.onKeyDown(keyCode, event);
}

Line 5 : FLAG_ACTIVITY_CLEAR_TOP 플래그. 혹시 모를 중간의 액티비티를 스택에서 없앤다.
Line 6 : FLAG_ACTIVITY_SINGLE_TOP 플래그. 최상위 스택에 보여줄 액티비티가 존재하는 경우, 이를 재사용한다.

위와 같이 적용한 후에는 액티비티 사이를 이리저리 왔다 갔다 한 후, 메인액티비티로 돌아온다고 해도 스택은 아래와 같이 깔끔해진다.

  Running activities (most recent first):

    TaskRecord{3027dff8 #7 A com.juno.activityjump.demo}

      Run #1: HistoryRecord{301e89e8 com.juno.activityjump.demo/.ActivityJumpDemoActivity}

    TaskRecord{2fe0c3e8 #2 A com.lge.launcher}

      Run #0: HistoryRecord{300d62c0 com.lge.launcher/.Launcher}



[다운로드]
    전체소스


Posted by 데브로망스

댓글을 달아 주세요