UPDATE:これが重複していることに同意しません-メインアプリを終了し、引き続きトーストを表示する方法を探しているのでサービス。
非常にシンプルなテストアプリ には2つのボタンがあります。
ボタンのいずれかをクリックすると、対応するアクション文字列(「開く」または「フラッシュ」)でサービスが実行されます-
public class OpenActivity extends Activity {
private Intent mServiceIntent;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_open);
mServiceIntent = new Intent(this, RegionService.class);
}
public void openCar(View v) {
mServiceIntent.setAction("open");
startService(mServiceIntent);
}
public class RegionService extends IntentService {
private static final String TAG = "RegionService";
@Override
protected void onHandleIntent(Intent intent) {
Log.d(TAG, "Received an intent: " + intent);
String action = intent.getAction();
Log.d(TAG, "Received an action: " + action);
if(action.equals("open")) {
Toast.makeText(this,
getString(R.string.car_opened),
Toast.LENGTH_SHORT).show();
}
残念ながら、私のアプリは次のようにクラッシュします:
D/RegionService(24506): Received an intent: Intent { act=open cmp=de.afarber.mynotification/.RegionService }
D/RegionService(24506): Received an action: open
W/MessageQueue(24506): Handler (Android.os.Handler) {422768a8} sending message to a Handler on a dead thread
W/MessageQueue(24506): Java.lang.RuntimeException: Handler (Android.os.Handler) {422768a8} sending message to a Handler on a dead thread
W/MessageQueue(24506): at Android.os.MessageQueue.enqueueMessage(MessageQueue.Java:320)
W/MessageQueue(24506): at Android.os.Handler.enqueueMessage(Handler.Java:626)
W/MessageQueue(24506): at Android.os.Handler.sendMessageAtTime(Handler.Java:595)
W/MessageQueue(24506): at Android.os.Handler.sendMessageDelayed(Handler.Java:566)
W/MessageQueue(24506): at Android.os.Handler.post(Handler.Java:326)
W/MessageQueue(24506): at Android.widget.Toast$TN.hide(Toast.Java:370)
W/MessageQueue(24506): at Android.app.ITransientNotification$Stub.onTransact(ITransientNotification.Java:54)
W/MessageQueue(24506): at Android.os.Binder.execTransact(Binder.Java:412)
W/MessageQueue(24506): at dalvik.system.NativeStart.run(Native Method)
Androidプログラミング初心者であるので、Serviceから Toast を正しく表示する方法は?
トーストはすでにAndroidホーム(つまり、デバイスの画面にアクティビティがなく、トーストが残っていました)で見たことがあると思います)。
私の背景:サービスからビーコンデバイスを監視し、アプリが閉じている場合でも、トーストのテキストを表示したいと思います。
OnHandleIntent
は別のThread
で実行されるため、Androidでは許可されていないスレッドでToast
を表示しています
このようにコードを変更してください
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),
getString(R.string.car_opened),
Toast.LENGTH_SHORT).show();
}
});
これから サービス中のデッドスレッド
IntentServiceは新しいインテントを処理するスレッドを作成し、タスクが完了するとすぐにそれを終了します。したがって、トーストはデッドスレッドによって制御されなくなります。
画面にトーストが表示されると、コンソールにいくつかの例外が表示されます。
IntentServiceにはいくつかの制限があります。
ユーザーインターフェイスと直接やり取りすることはできません。結果をUIに配置するには、アクティビティに送信する必要があります。
すべてがUIスレッドではなくバックグラウンドスレッドで発生しているため、以下に示すような別の方法が必要です。
@Override
public void onCreate() {
super.onCreate();
mHandler = new Handler();
}
@Override
protected void onHandleIntent(Intent intent) {
mHandler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(MyIntentService.this, "Hello Toast!", Toast.LENGTH_LONG).show();
}
});
}
OnHandleIntent
はバックグラウンドスレッドで呼び出され、UIに触れようとするとクラッシュします。ハンドラーを使用してUIスレッドにRunnableを投稿し、トーストを表示します。
private class MyRunnable implements Runnable {
final int mTextId = -1;
final Context mContext;
public MyRunnable(Context c, int textId) {
mTextId = textId;
mContext = c;
}
@Override
public void run() {
Toast.makeText(mContext,
getString(mTextId),
Toast.LENGTH_SHORT).show();
}
}
Handler handler = new Handler();
handler.post(new MyRunnable(this, R.string.car_opened));
次のコードを使用します。
runOnUiThread(new Runnable(){
public void run() {
// UI code goes here
}
});
この問題は、main_threadからToastを実行しないため、およびそれを克服するために、アクティビティを作成するときに、onCreate()
メソッドからコンテキストを保存します。
public static Context ctx;
// the method responsible for running the MainActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ctx = this;
}
次に、サービスにハンドラーを追加し、そこからスレッドを実行します(ハンドラーはメインスレッドを通じて実行されるため)。
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(OpenActivity.ctx, getString(R.string.car_opened),
Toast.LENGTH_SHORT).show();
}
});