English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
この記事では、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(メールを送信する際、#を@に置き換えてください。報告を行い、関連する証拠を提供してください。一旦確認が取れましたら、本サイトは即座に侵害疑いのコンテンツを削除します。)