web-dev-qa-db-ja.com

メインアクティビティが完了した後、サービスからトーストを表示する方法は?

UPDATE:これが重複していることに同意しません-メインアプリを終了し、引き続きトーストを表示する方法を探しているのでサービス。

非常にシンプルなテストアプリ には2つのボタンがあります。

screenshot

ボタンのいずれかをクリックすると、対応するアクション文字列(「開く」または「フラッシュ」)でサービスが実行されます-

OpenActivity.Java

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);
    }

RegionService.Java

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ホーム(つまり、デバイスの画面にアクティビティがなく、トーストが残っていました)で見たことがあると思います)。

私の背景:サービスからビーコンデバイスを監視し、アプリが閉じている場合でも、トーストのテキストを表示したいと思います。

13

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は新しいインテントを処理するスレッドを作成し、タスクが完了するとすぐにそれを終了します。したがって、トーストはデッドスレッドによって制御されなくなります。

画面にトーストが表示されると、コンソールにいくつかの例外が表示されます。

39
kalyan pvs

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();                
        } 
    }); 
} 

ソース: IntentServiceで作成されたトーストが消えることはありません

5
Little Child

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));
2
Blackbelt

次のコードを使用します。

  runOnUiThread(new Runnable(){
     public void run() {
          // UI code goes here
     }
    });
1
TechHelper

この問題は、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();
        }
    });
0
Muhammed Refaat