English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Android Service에서 Toast가 정상적으로 표시되지 않는 문제 해결 방법

이 글은 Android Service에서 Toast를 표시하지 못하는 문제를 해결하는 방법을 설명합니다. 여러분에게 공유하고 참고하기 위해 다음과 같이 작성했습니다:

Service의 OnCreate, OnStart, OnDestroy 세 가지 메서드에서 Activity의 동일한 메서드와 같이 Toast.makeText를 호출했으며, Activity에서는 두 개의 버튼을 통해 해당 서비스의 onStart와 onDestroy 메서드를 호출했습니다:

DemoService 코드는 다음과 같습니다:

@Override
public void onCreate()
{
    super.onCreate();
    Toast.makeText(getApplicationContext(), "서비스가 생성되었습니다!", Toast.LENGTH_LONG).show();
}
@Override
public void onStart(Intent intent, int startId)
{
    super.onStart(intent, startId);
    Toast.makeText(getApplicationContext(), "서비스가 활성화되었습니다!", Toast.LENGTH_LONG).show();
}
@Override
public void onDestroy(){
    super.onDestroy();
    Toast.makeText(getApplicationContext(), "서비스가 꺼져 있습니다!", Toast.LENGTH_LONG).show();
}

실행 후, DemoService에서의 정보가 모두 표시되지 않았습니다.

처음에는 받은 Context가 정확하지 않다고 생각했지만, Service에서 getApplicationContext()를 직접 호출하면 Service의 Context를 받아오는데, 보다細かに 살펴보면 Toast는 메인 UI의 Context를 받아야 표시될 수 있으므로 찾아보니, Google의 Toast 설명에 한마디가 있었습니다:

“Activitiy나 Service에서 토스트를 생성하고 표시할 수 있습니다. Service에서 토스트 알림을 생성하면 현재 초점에 있는 Activity 앞에 표시됩니다.”
(http://developer.Android.com/guide/topics/ui/notifiers/toasts.html)

이 문장에 따르면, 서비스에서 생성된 토스트는 현재 초점에 있는 Activity의 UI 앞에 집중적으로 표시될 것입니다. 그러나 왜 효과가 없는지 확인해 보겠습니다. makeText 메서드를 다시 확인해 보겠습니다.

물론 Context 문제로 인해 토스트가 정상적으로 작동하려면 Activity의 메인 스레드에서 실행되어야 합니다. 그렇다면 메인 스레드 UI의 Context를 얻는 방법은 무엇인가요? Handler를 사용하여 사용자 정의 스레드를 메인 스레드 위에서 실행할 수 있습니다.

Toast.show 메서드의 src를 다시 확인해 보겠습니다:

public void show() {
    ...
    service.enqueueToast(pkg, tn, mDuration);  //이 토스트를 메시지 큐에 삽입합니다
    ...
}

원리적으로 볼 때, Android는 메시지 큐와 메시지 루프로 구성되어 있으며, 메인 스레드는 메시지 큐에서 메시지를 꺼내 처리합니다. Handler는 메시지 큐에 메시지를 삽입하는 도구 클래스로 사용됩니다. 따라서 원래 코드를 다시 구조화하면:

@Override
public void onCreate()
{
    super.onCreate();
    handler=new Handler(Looper.getMainLooper());
    handler.post(new Runnable(){
      public void run(){
        Toast.makeText(getApplicationContext(), "서비스가 생성되었습니다!", Toast.LENGTH_LONG).show();
      }
    });
}
@Override
public void onStart(Intent intent, int startId)
{
    super.onStart(intent, startId);
    handler=new Handler(Looper.getMainLooper());
    handler.post(new Runnable(){
      public void run(){
        Toast.makeText(getApplicationContext(), "서비스가 활성화되었습니다!", Toast.LENGTH_LONG).show();
      }
    });
}
@Override
public void onDestroy(){
    super.onDestroy();
    handler=new Handler(Looper.getMainLooper());
    handler.post(new Runnable(){
      public void run(){
        Toast.makeText(getApplicationContext(), "서비스가 꺼져 있습니다!", Toast.LENGTH_LONG).show();
      }
    });
}

실행된 후의 효과는 다음과 같습니다:

요약:Android의 Framework에서 Toast를 사용하려면, Toast를 메인 스레드에 추가하여 정상적으로 작동해야 합니다.

Android와 관련된 더 많은 내용에 관심이 있는 독자는 이 사이트의 특辑을 확인할 수 있습니다: 《Android 개발 입문 및 고급 교본》、《Android 뷰 View 기술 요약》、《Android 프로그래밍에서 activity 작업 기술 요약》、《Android SQLite 데이터베이스 작업 기술 요약》、《Android json 형식 데이터 작업 기술 요약》、《Android 데이터베이스 작업 기술 요약》、《Android 파일 작업 기술 요약》、《Android 프로그래밍 개발에서 SD 카드 작업 방법 요약》、《Android 자원 작업 기술 요약》 및 《Android 컨트롤러 사용 요약》

이 문서에서 설명한 내용이 모두 여러분의 Android 프로그램 설계에 도움이 되길 바랍니다.

선언: 이 문서의 내용은 인터넷에서 가져왔으며, 저작권자는 모두입니다. 내용은 인터넷 사용자가 자발적으로 기여하고 업로드한 것이며, 이 사이트는 소유권을 가지지 않으며, 인공 편집 처리를 하지 않았으며, 관련 법적 책임도 부담하지 않습니다. 저작권 문제가 있는 내용을 발견하면 이메일을 보내 주세요: notice#oldtoolbag.com(이메일을 보내는 경우, #을 @으로 변경하십시오. 신고하시고 관련 증거를 제공하시면, 사실이 확인되면 이 사이트는 즉시 의심스러운 저작권 내용을 삭제합니다.

추천 합니다