Android - Home 버튼이 눌려도 항상 상단에 떠 있는 View 만들기. (part 2)

오랜만에 글을 작성합니다...
늦어서 죄송합니다;;

지난 번에 작성한 Home 버튼이 눌려도 항상 상단에 떠 있는 View 만들기 part 2 입니다.
지난 번에 작성하지 못했던 부분이,

1. Service 와 Activity 연결하기.
- Activity 에서 Service 에 있는 함수 호출하기.
- Service 에서 Activity 에 있는 함수 호출하기.
2. Service 에서 터치 처리하기.
3. 마지막으로, Service 종료하기.

입니다. 하나씩 살펴보기로 하지요.
시작하기 전에 참고 링크를 하나 걸어두겠습니다.
android developer 페이지에 있는 Service Binding 관련 내용입니다. [ 참고 ]
사실 저 링크에 있는 글을 보시면, 제 글은 보실 필요가 없긴 합니다; 하하;

우선 activity 와 service 코드를 먼저 보실게요.
지난 번에 올린 것과는 조금 달라져 있습니다.

간단한 설명은 코드에 주석으로 작성해두었습니다만,
주의 깊게 보셔야 하는 내용은 ServiceConnection 입니다.
Android Developer에서는,
'Service 와의 연결을 모니터링 하기 위한 클래스' 라고 설명합니다.
override 할 수 있는 메소드도 서비스 연결이 될 때 호출하는 것과
서비스 연결이 끊어질 때 호출하는 것 두 가지 밖에 없는 걸 보면,
딱 모니터링 하기 위한 클래스로 보이기도 합니다.

저는 ServiceConnection 을 구현할 때,
- Service 객체를 저장하고,
- activity 에 구현한 interface 를 service 에 넣었고,
- isBound 라는 boolean 변수에 값을 true 로 넣어주었습니다.

service 객체를 activity 에 별도로 저장한 이유는,
activity 에서 service 에 있는 함수를 호출하기 위함입니다.
굳이 그럴 필요가 있는가... 싶지만...
외부 입력이 들어온다거나(예를 들면 nfc 카드 입력 같은...)
기기의 Back 버튼이 눌린다거나 하는 이벤트가 발생할 때
service 에서 뭔가를 처리할 수 있는 통로를 만들어 둔다고 보시면 될 것 같습니다.

interface 를 service 에 넣어준 이유는,
Context 객체 그리고 intent 객체 같은 것들을
static 으로 만들어서 접근을 허용하고 싶지 않아서 그렇습니다.
어디선가 그 작업의 위험성을 들었던 적이 있어서 일부러 피하고 있습니다;

마지막으로 isBound 라는 boolean 변수를 별도로 운용하는 이유는,
만에 하나를 대비하기 위해서입니다.
그 만에 하나를 대비한 부분은 onDestroy() 를 보시면 됩니다.

그럼 이제 service 에도 activity 와 연결할 준비를 해주겠습니다.
service 클래스 코드를 보시겠습니다.


코드를 자세히 보기 전에...
우선 사과의 말씀 드립니다.
FLAG_NOT_FOCUSABLE 은 말 그대로 포커스를 받지 않기 위한 FLAG 인데,
제가 지난 번에 터치 이벤트를 처리하기 위한 FLAG 라고 설명을 했더라구요.
오해를 드려서 다시 한번 죄송합니다;

음... 계속 설명을 하겠습니다.
service 클래스에서 이제 주의 깊게 봐주셔야 하는 부분은,
LocalBinder 클래스와, onClick(), callTest()
입니다.

LocalBinder 클래스의 역할은 굉장히 간단합니다.
service 클래스 자신을 전달하는 거지요.
이렇게 전달한 service 를 activity 에서 잡아서 사용한다... 고 보시면 될 것 같습니다.

다음은 onClick 입니다.
터치 처리와 종료 처리를 하기 위한 함수입니다.
이 함수를 사용하시기 전에 xml layout 을 먼저 수정해주셔야 합니다.
터치하고자 하는 영역에 id 값을 부여주시고, onClick 이라는 항목도 작성해주셔야 합니다.
이후에 xml 코드를 올리면, 보고 바로 이해하실 수 있을겁니다.
onClickListener 를 작성하는 방법도 있지만
onClick 을 사용하는 것이 가장 간단한 터치 처리 방식인 것 같습니다.
제 생각이지만요.

이 onClick 중에서 가장 중요한 부분은 exit 버튼이 눌렸을 때 입니다.
service 를 종료하기 위한 부분이지요.
WindowManager 에 addView 한 것을 제거하고, service 를 멈추고,
마지막으로 app 을 종료하는 순서로 진행됩니다.

callTest 는 activity 에서 service 에 있는 함수를 호출하기 위해 만든 테스트 함수입니다.
activity 코드를 보시면, back 버튼이 눌렸을 때 호출되게 만들어놨습니다.

여기까지 하면...
Activity 와 Service 의 연결, 그리고 터치 처리가 끝납니다.

이번엔 interface 를 살펴보겠습니다.
어떻게보면 정말 별 것 없습니다.
함수 이름만 봐도 뭐하는 녀석들인지 아시겠지요?
이 녀석들은 Activity 에서 override 되어 있습니다.
다시 한번 Activity 코드를 봐주시면 됩니다.

마지막으로 xml layout 을 보여드리고 마무리지을게요.
xml 에서 중요한 부분은 id 와 onClick 이 되겠습니다.
onClick 뒤에는 위젯이 눌렸을 때 호출할 함수의 이름을 넣어주시면 됩니다.
저는 더 좋은 함수 이름이 생각이 안 나서 그냥 onClick 을 했었지만요.

이렇게 해서...
Home 버튼이 눌려도 항상 떠 있는 View 만들기가 끝났습니다.
사실 끝내고 싶었습니다;

근데 제가 일에 치이고 있는 중에 android 6.0 marshmellow 가 나왔잖아요?
6.0 단말기 쓰시는 분들은 이거 안 돌아갈거에요.
permission 제어라는 부분이 생겼기 때문이에요.

제가 포스팅한 것을 6.0 에서 똑같이 보려면,
'다른 app 위에 그리기.' 라는 권한이 필요하게 되었습니다.
그래서 이 부분도 조만간 포스팅 하겠습니다.
... 올 해 안에는 작성할게요.

긴 글 읽느라 고생하셨습니다.
봐주셔서 감사합니다.
자주 놀러 오실 수 있게끔, 좋은 글 많이 작성하도록 노력할게요.

다시 한번 감사합니다.

CloudD

예술하는 프로그래머, 코딩하는 예술가

11 댓글

  1. 작성자가 댓글을 삭제했습니다.

    답글삭제
    답글
    1. 어떤 부분에서 앱이 종료되는지 확인해보실 수 있을까요?
      에러가 발생한다면 어느 부분에서 발생하는지 알려주세요.
      확인해보겠습니다.

      삭제
    2. case R.id.bt_exit :
      Log.d(TAG, "Exit - Button Click");
      // View 제거.
      winMgr.removeView(view);
      // 서비스 종료.
      stopService( ai.getServiceIntent() );
      // 프로세스 종료.
      android.os.Process.killProcess(android.os.Process.myPid());

      break;

      이부분에서 view제거만 했을때는 view 가 지워지기는 하지만 하얀 화면이 뜨고 나머지 도 같이 돌리면 팅겨버리는 현상이 일어납니다...

      삭제
    3. logcat 을 한번 같이 봐주시겠어요?
      logcat 에 에러 로그가 같이 생기면 튕기는 것이 맞겠지만, 저 코드 자체가 앱을 종료하는 코드라서 튕기는 것 처럼 느껴지실 수도 있습니다.
      그 부분 한번 더 확인해주세요.

      삭제
    4. 작성자가 댓글을 삭제했습니다.

      삭제
    5. 저는 뷰만 지우고 서비스는 유지 시키고 싶은데 뷰만지우면 흰 화면이 항상 남더라구요... 왜그런지 모르겟어요

      삭제
    6. 뷰만 삭제하신 경우면 서비스는 유지되는 상태가 맞습니다.
      서비스 뷰가 아니라 다른 뷰를 하나 더 만들어두시면, 서비스에서 출력한 뷰를 삭제해도 다른 뷰가 나타나게 됩니다.
      비슷한 방법으로 진행했던 프로젝트가 하나 있는데, 급한 불만 끄고 같이 포스팅하도록 하겠습니다.

      삭제
  2. 오랫만에 들렀습니다.
    건강하시죠?
    슬라이딩 페이지 구현하면서 필요해서 구글링하다가 ...
    역시 선생님 글이 간결하고 시원하고 쉽습니다.
    참, 관련글 찾으려다가 보니
    제 블로그 링크를 해두셨군요.
    한참 배우는 초보자인데 ...
    어쨌든 감사합니다.
    여유 있고 건강하게 사세요.

    답글삭제
    답글
    1. 오랜만에 뵙습니다.
      일 때문에 계속 바쁘게만 지내다 보니, 블로그 업데이트가 계속 밀리고 있습니다;
      그럼에도 좋게 평가해주시니 감사합니다 ㅠ;

      간절기 감기 조심하시고, 건강하세요~

      삭제
  3. 오랫만에 들렀습니다.
    건강하시죠?
    슬라이딩 페이지 구현하면서 필요해서 구글링하다가 ...
    역시 선생님 글이 간결하고 시원하고 쉽습니다.
    참, 관련글 찾으려다가 보니
    제 블로그 링크를 해두셨군요.
    한참 배우는 초보자인데 ...
    어쨌든 감사합니다.
    여유 있고 건강하게 사세요.

    답글삭제
  4. 선생의 설명 중에

    android 6.0 marshmellow ... 6.0 단말기 쓰시는 분들은 이거 안 돌아갈거에요.

    라는 말씀이 보여서 덧붙입니다.

    - 참 전에도 그랬는데 글 한 번 올리면 두 번씩 기록되는 현상이 또 있네요. 이번에는 안 지웁니다.

    안 돌아가는 분들은 아래 페이지 다운해서 돌려보세요.

    http://itmir.tistory.com/548

    참고할 분들이 있을까 해서 ...

    답글삭제
다음 이전