안드로이드 스마트폰에서 화면이 켜지는 경우는 크게 두가지로 나뉜다.


1. HW Key에 의해 화면이 켜짐

2. Software에 의해 화면이 켜짐


여기서 1. 하드웨어 키에 의해 화면이 켜지는 경우는 홈 버튼(Home button) / 파워 버튼(Power Button)으로 화면을 켜는 경우이며, 

2. Software에 의해 켜지는 경우는 알람, 푸쉬메세지, 전화 등 여러 'Notification'이 들어 왔을 경우에 해당한다.


나는 이 중에 1번의 경우를 캐치하고 싶었다. 2번은 철저하게 배제하고.

사용한 방법은 아래와 같다.


1) NotificationListenerService를 생성 후, Notifacation을 받을 경우 현재 시간을 SharedPreference에 저장한다.

2) BroadcastReceiver에서 Intent.ACTION_SCREEN_ON 일 경우를 Receiver해서 현재 시간을 구한 후, 1)에서 구한 시간과 비교한다.

3) 간격이 2초 이내일 경우 Software에 의해 화면이 켜진 것이고, 그 외의 경우는 유저가 하드웨어 키 입력을 통해 화면을 킨 경우이다.


갤럭시 노트4에서 테스트 해 본 결과 화면이 꺼진 상태에서 Push 메세지가 올 경우 BroadcastReceiver보다 NotificationListenerService의 onNotificationPosted() 가 더 우선 수행되었다. (다른 폰에서는 장담 못한다.)


따라서 위의 로직이 성공적으로 수행될 수 있었다.


구현은 다 했지만.. 아직 허들이 남아있다.


1. NotificationListenerService의 라이프 사이클 문제이다.

검색해도 잘 나오질 않아서 내가 직접 실험해 보기로 했다. 만약 NotificationListenerService가 LMK 등에 의해 지워지게 될 경우 위의 로직은 말짱 꽝이다. 그래서 onNotificationPosted() 일 경우에 Vibrator를 진동 시켜, 해당 Service가 언제까지 살아있는지 테스트 해보기로 했다.

하루 정도 테스트 해보면 충분할 것이라 생각한다. 결과는 내일이나 모래쯤 올리겠다.


부디 성공하길.

저작자 표시 비영리 변경 금지
신고
블로그 이미지

roter

JHB / Peripheral Programmer

댓글을 달아 주세요

http://www.learn2crack.com/2014/11/reading-notification-using-notificationlistenerservice.html


완벽하다 정말


NotificationListnerService 외에도 LocalBroadcastManager 사용법 까지 알게 되어 좋다.


참고로 Notification Access는 폰마다 위치가 다르다.

아래와 같이 열어주면 편하다.


Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
	startActivity(intent);

추가적으로 NotificationListenerService를 통해 핸드폰 화면이 꺼져있을 때 메세지가 와서 해당 서비스가 캐치 하는 경우

BroadcastReceiver의 Screen On 보다 먼저 캐치 한다. (갤럭시 노트4의 경우)

매우 굳굳

저작자 표시 비영리 변경 금지
신고
블로그 이미지

roter

JHB / Peripheral Programmer

댓글을 달아 주세요

안드로이드 서비스 동작 중인지 파악하기


아래의 코드를 사용하면 된다.


나는 보통 static으로 선언하여 service 안에 넣는다.


예를 들어 service 이름이 'JHService' 라면

JHService.isServiceRunning(); 하면 여부가 나온다.


public static boolean isServiceRunning(Context context) {
		ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
		
		for (RunningServiceInfo rsi : am.getRunningServices(Integer.MAX_VALUE)) {
			if ([서비스이름].class.getName().equals(rsi.service.getClassName())) //[서비스이름]에 본인 것을 넣는다.
				return true;
		}
		
		return false;
	}



이거 구현하면서 햇깔렸던게, String 비교 부분에서 .equals() 말고 == 을 해줬더니 계속 실패했다는 점...

문자열이 일치하는지 아닌지 비교하려면 .equals() 쓰는 것 잊지 말자. == 는 객체의 instance가 같은지 다른지 보는 연산자이다.


class.getName() 하는 것이나 service.getClassName() 하는 것이나 

kr.jhb.testapp.ServieName

위와 같이 package name + class name 으로 나온다.

저작자 표시 비영리 변경 금지
신고
블로그 이미지

roter

JHB / Peripheral Programmer

댓글을 달아 주세요