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

Android ServiceでToastが正常に表示されない問題の解決方法

この記事では、Android ServiceでToastが正常に表示されない問題の解決方法について説明します。皆さんに参考にしていただければ幸いです。以下の通りです:

Serviceの簡単な練習をしているとき、ServiceのOnCreate、OnStart、OnDestroyの3つのメソッドでは、Activity内の同じメソッドと同様にToast.makeTextを呼び出し、Activityでは2つのボタンを通じてそのサービスのonStartとonDestroyメソッドを呼び出しました:

DemoServiceのコードは以下の通りです:

@Override
public void onCreate()
{
    super.onCreate();
    Toast.makeText(getApplicationContext(), "Service is created!", Toast.LENGTH_LONG).show();
}
@Override
public void onStart(Intent intent, int startId)
{
    super.onStart(intent, startId);
    Toast.makeText(getApplicationContext(), "Service is on!", Toast.LENGTH_LONG).show();
}
@Override
public void onDestroy(){
    super.onDestroy();
    Toast.makeText(getApplicationContext(), "Service is off!", Toast.LENGTH_LONG).show();
}

実行した後、DemoService内の情報は全く表示されませんでした。

最初は受け取ったContextが正しくないと思っていたが、Serviceで直接getApplicationContext()を呼び出すとServiceのContextが取得される。しかし詳しく調べてみると、ToastはメインUIのContextを取得して表示する必要があるため、GoogleのToastの説明を調べてみたところ、以下の一文がありました:

「ActivityまたはServiceからtoastを作成して表示できます。Serviceからtoast通知を作成すると、現在焦点を当てたActivityの前に表示されます。」
(http://developer.Android.com/guide/topics/ui/notifiers/toasts.html)

その文句に従えば、serviceで作成されたtoastは、ActivityのUIの前に焦点を当てて表示されます。しかし、なぜ効果がないのかを確認します。

確かにContextの問題が原因ですので、toastが正常に動作するためには、Activityのメインスレッド上で実行する必要があります。それでは、メインスレッドのUIのContextをどうやって取得するのでしょうか?カスタムスレッドをHandlerを使ってメインスレッド上で実行することでできます。

それでは、Toast.showメソッドのsrcを見てみましょう:

public void show() {
    ...
    service.enqueueToast(pkg, tn, mDuration);  //このtoastをメッセージキューに挿入します
    ...
}

原理的見方では、Androidでは概ねメッセージキューとメッセージループがあり、メインスレッドがメッセージキューからメッセージを取得して処理します。Handlerはそのツールクラスであり、メッセージキューにメッセージを挿入するために使用されます。したがって、元のコードを再構築します:

@Override
public void onCreate()
{
    super.onCreate();
    handler=new Handler(Looper.getMainLooper());
    handler.post(new Runnable(){
      public void run(){
        Toast.makeText(getApplicationContext(), "Service is created!", 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(), "Service is on!", 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(), "Service is off!", 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(メールを送信する際、#を@に置き換えてください。報告を行い、関連する証拠を提供してください。一旦確認が取れましたら、本サイトは即座に侵害疑いのコンテンツを削除します。)

おすすめ