카톡 스타일의, 화면 꺼진 상태에서도 푸시가 오면 알림창을 띄우는 기능을 구현해야 했다.
처리 절차는 다음과 같다.
1. 푸시를 받았는데 화면이 꺼져있다면
2. 락 스크린 위로(!) 특정 액티비티를 실행한다.
3. 이 액티비티에서 원하는 액션을 수행한다. (대게 '보러가기' / '닫기' 수준이겠지)
1번에선 화면이 꺼져있는지 여부를 확인해야 하고, 이는 다음과 같이 확인할 수 있다.
public static boolean isScreenOn(Context context) {
return ((PowerManager)context.getSystemService(Context.POWER_SERVICE)).isScreenOn();
}
2. 락 스크린 위로 액티비티를 보여주기 위해선 보여줄 액티비티가 full screen 이어야 하며, 다음과 같은 window 세팅을 해 줘야 한다. onCreate() 메서드에 넣어두면 된다.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
맨 위의 dismiss keyguard 는 락 까지 해제하겠다는 것인데, 몇 번 테스트 해 보니 일반적인 상황에선 락 화면을 없애지 못했다. 굳이 제거 안되는 락 스크린까지 걷어낼 필요가 없어 그냥 넘어가고.
3번은 case by case 이니 딱히 언급할 필요가 없고.
그런데 내 경우에 화면 표시까진 잘 되었는데, 몇 가지 요상한 문제가 발생했다.
1. recent app 목록에서 앱을 선택하면 원래 앱 화면이 아닌, 저 팝업 화면이 튀어나왔다.
2. 그래서 저 팝업 화면에다 android:excludeFromRecents="true" 를 설정했더니 아얘 recent app 목록에서 사라졌다.
앱을 만들면서 task를 새로 만들어본 적이 한번도 없었는데, push를 받아 activity를 생성할 때 newTask 를 붙여놨다지만 이 pushPopup 과 원래 앱의 taskAffinity 가 동일하다면 (별도로 설정을 하지 않는 이상 동일하다) 실제론 task가 새로 생기지 않으며, 아마도 처음 task를 실행한 pushPopup에서 android:excludeFromRecents 가 true 로 되어 있어 recent 목록에서도 날아간 듯 하다.
해결은
1. pushPopup 액티비티에 별도의 taskAffinity 를 주고,
2. pushPopup 액티비티는 android:excludeFromRecents="true" 를 명시했으며
3. pushPopup 을 띄울 때나, 이 액티비티가 원래의 앱을 호출할 때 모두 Intent.FLAG_ACTIVITY_NEW_TASK 플래그를 달아줬다.
이렇게 하니
1. recent 목록에서 원래 앱이 날아가는 문제도 없고
2. recent 목록의 항목을 선택하면 원래 앱의 원래 화면으로 잘 찾아들어갔다.
* activity 정의
<activity
android:name=".activity.PushPopup_"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:excludeFromRecents="true"
android:taskAffinity="{my_pkg_name}.popup"/>* 화면 꺼졌을 때 activity 호출
if (!Util.isScreenOn(context)) {
context.startActivity( new Intent(context, PushPopup_.class).putExtra( blah blah).setFlags( Intent.FLAG_ACTIVITY_NEW_TASK));
}
* popup activity 의 oncreate에서 flag 설정
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);