Как вывести тост из сервиса после завершения основной деятельности?
UPDATE: я не согласен с тем, что это дубликат, потому что я ищу способ выйти из основного приложения и все еще показывать тост из службы.
В очень простом тестовом приложении у меня есть 2 кнопки:
При нажатии на любую из кнопок будет запущен сервис с соответствующей строкой действий ("открыть" или "flash") -
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, я задаюсь вопросом Как правильно отобразить тост из службы?
Я думаю, что уже видел тосты в Android Home (то есть на экране устройства не было никакой активности, и все еще были тосты).
Мой фон: я хотел бы следить за устройством маяка из моего сервиса и показывать некоторые текстовые тосты-даже когда мое приложение было закрыто.
5 ответов:
OnHandleIntent
побежит в differantThread
таким образом, вы показываетеToast
в потоке, который не разрешен в androidПоэтому измените свой код следующим образом
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 имеет несколько ограничений:
Он не может напрямую взаимодействовать с вашим пользовательским интерфейсом. Поставить свою результаты в пользовательском интерфейсе, вы должны отправить их в действие.Все происходит в фоновом потоке, а не в потоке пользовательского интерфейса, поэтому вам нужен другой способ, как показано ниже:
@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, никогда не исчезает
OnHandleIntent
вызывается в фоновом потоке, и любая попытка коснуться пользовательского интерфейса приведет к сбою. Используйте обработчик для публикации 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, и чтобы преодолеть это, при создании действия сохраните его контекст из Метода
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(); } });