Why won't a toast notification appear in my background Service (using System.Timer)?

假装没事ソ 提交于 2019-12-12 04:03:12

问题


In a background service I create a count down timer using System.Timers.

It appears to work. After 2 seconds in the console I can see that Console.WriteLine() prints the text.

However, the Toast notification does not appear and I would like to know why

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;   
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Media;
using Android.Content.Res;
using System.Timers;


namespace AudioTour
{
    [Service(Exported = false, Name = "com.AudioTour.AudioService")]
    public class AudioService : Service
    {
        // This method is called to start the Timer
        private void StartCountdown()
        {
            RunTimer(2);
        }

        private Timer myTimer;
        private int countDownSeconds;

        // This is my timer
        private void RunTimer(int _timerLength)
        {
            myTimer = new Timer();
            myTimer.Interval = 1000;
            myTimer.Elapsed += OnTimedEvent;
            countDownSeconds = 5;
            myTimer.Enabled = true;
        }

        // When the timer has elapsed this event is called
        private void OnTimedEvent(object sender, System.Timers.ElapsedEventArgs elapsedEventArgs)
        {
            countDownSeconds--;
            // This is what I expect to happen when the timer reaches 0
            if (countDownSeconds == 0)
            {
                Console.WriteLine("Timer Finished");
                Toast.MakeText(this, "Timer Finished", ToastLength.Short).Show();
                myTimer.Stop();
            }
        }

回答1:


A background service in Android does not have an UI, so it can't produce a toast as this is a UI component.

@jason.kaisersmith, hi guys, a little different opinion, I think the toast cant shown because of the thread instead of the Service itself.

A service could show Toast as the document said :

A toast can be created and displayed from an Activity or Service. If you create a toast notification from a Service,it appears in front of the Activity currently in focus.

Why it cant be shown in this question? Notice that the Toast.MakeText method :

It means if you want to show the toast, you have to put the Toast on the main thread, I think this is the reason. Your problem is OnTimedEvent method will run in a different thread so you are showing Toast in a thread which is not allowed in android.

As you said, You simply initialize it, then it gets passed off to a system service queue. In Toast source code we can prove your opinion:

//insert toast to a messagequeue
service.enqueueToast(pkg, tn, mDuration);  

Now the problem becomes how to send this message to Main thread.

We just need to put the toast into main thread's messagequeue, and Android give us a API Looper.getMainLooper() to implement this function, modify your code like this :

private void OnTimedEvent(object sender, System.Timers.ElapsedEventArgs elapsedEventArgs)
{
     countDownSeconds--;
     // This is what I expect to happen when the timer reaches 0
     if (countDownSeconds == 0)
     {
          Console.WriteLine("Timer Finished==========================");
          Handler handler = new Handler(Looper.MainLooper);
          //Returns the application's main looper, which lives in the main thread of the application.
          Action myAction = () =>
          {
              Toast.MakeText(this, "Timer Finished", ToastLength.Short).Show();

           };
           handler.Post(myAction);
           myTimer.Stop();
     }
}

Effect :



来源:https://stackoverflow.com/questions/45638838/why-wont-a-toast-notification-appear-in-my-background-service-using-system-tim

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!