행복한 수지아빠
2015. 2. 4. 20:35
2015. 2. 4. 20:35
카톡 스타일의, 화면 꺼진 상태에서도 푸시가 오면 알림창을 띄우는 기능을 구현해야 했다.
처리 절차는 다음과 같다.
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);
안녕하세요. 안드로이드 공부하는 학생입니다. 중복으로 푸쉬를 보내면 맨처음 푸쉬창을 사용자가 없애지 않으면 다음 푸쉬가 안보내지는데, 중복푸쉬를 가능하게 하는 방법이 있나요?
+김윤중 안녕하세요. 제가 이 글을 쓴 지 너무 오래되어 저도 기억이 잘 안나는데, 푸시창이라고 하신게 화면 꺼짐상태의 창을 말씀하신거지요? 이 경우 제일 좋은 방법은 이미 열려있는 화면 꺼짐 창의 내용을 갱신하는 것입니다. 메서드가 잘 기억이 나진 않는데 현재 알림 창이 떠 있는지 확인하고, 떠 있다면 액티비티의 내용을 갱신하기 위해 broadcast 를 날리던지 intent를 날리던지 하는 방식으로 처리할 수 있을거에요. 저도 그렇게 했던 것 같구요.
빠른 답변 감사합니다!! 네 맞습니다. 화면이 꺼진상태에서 푸시가 날라오면 알림창을 보여주는 것이죠. 하지만 연속으로 푸시를 보내면 첫번째 푸시만 알림창으로 나오고 다음 푸시는 나오지 않는 문제가 있는데 그 문제를 해결 못하고 있습니다ㅠ
+김윤중 제 경우엔 푸시팝업 화면을 singleTop인가 singleInstance로 띄우고, 여기에 intent를 다시 보냈던 것 같아요. 이 때 푸시팝업 activity는 onNewIntent() 로 새 인텐트를 받게 되고, 이 메서드안에서 내용을 갱신하도록 구현했습니다.
우와!! 감사합니다!
+Sewon Ann 님 말씀대로 하니까 푸쉬팝업이 연속적으로 꺼진상태에서 작동하긴 하나 아쉽게도 출력되는 데이터 값이 이전 데이터가 찍히는 상황이 벌어지네요. 아무래도 onNewIntent()에서 값을 제대로 받아 오지 못하는 것 같습니다.ㅠㅠ;;
@김윤중아마도 getIntent() 로 데이터를 가져오신 것 같은데 onNewIntent() 의 parameter로 넘어온 intent 값을 사용하셔야 해요. getIntent() 를 쓰시고 싶다면 onNewIntent() 안에서 새로 넘어온 intent 객체를 setIntent() 로 설정해서 사용하시면 되지 싶습니다. 도움이 되시길 :-)
+Sewon Ann 감사합니다. 도움되었습니다! 정말정말 감사합니다!!! 와 감동의 눈물이 ㅠㅠㅠㅠㅠ 삼일 해매던걸 여기와서 한퀴에 해결했네요 ㅠㅠ 너무 감사합니다.
으아!! 너무 감사드립니다 ^_^ 앞으로 종종 찾아뵐께요 !!
안녕하세요~ 저는 폰이 sleep mode로 넘어간뒤 일정 지나면 푸쉬를 보내도 onReceive() 에 들어오지 않는데요... 혹시 방법 아시나요?ㅜㅜ , 폰이 활성->슬립모드로 들어가자마자 푸쉬를 보내면 onReceive()에 들어와서 화면을 깨우고 팝업을 보여줍니다.
+이주영 아마도 서버에서 푸시를 보낼 때 delay_while_idle 속성을 true로 해 두셨을거에요. 이걸 true로 해 두면 첫번째 푸시는 receive로 들어오지만, 이 때 바로 폰은 "아, 나는 이제 자는 상태니 푸시 보내지마" 상태로 접어들기 때문에 이후 푸시가 화면 켜야 들어옵니다. 그래서 일단 delay_while_idle 를 확인해보시는 게 좋을겁니다. false 여야 자고 있는 상태에서도 깨우는 처리가 될 거에요.
http://developer.android.com/google/gcm/server.html
우와!! 감사합니다 ㅜㅜ 몇일째 헤매던건데 바로 해결해주셨어요!!댓글도 바로 달아주시구!!!! 두번 감사해요ㅎㅎㅎ
+이졍 네, 저도 이것때문에 한참 고생을 했어서 마침 기억을 하고 있었네요.
gcm 서버로부터 메시지를 받기는 합니다. 화면이 꺼져있을때 깨우면서 최상위로 activity를 띄우게 하고 싶은데요. 2번대로는 해봤는데 1번이 없어서그런지 안되더라구요.
+김미혜 깨우는 게 문제라면 wake lock 쪽을 살펴보시면 될 것 같네요