问题描述
在后台服务中,我使用 System.Timers 创建了一个倒数计时器.
它似乎有效.在控制台中 2 秒后,我可以看到 Console.WriteLine() 打印文本.
然而,Toast 通知没有出现,我想知道为什么
使用系统;使用 System.Collections.Generic;使用 System.Linq;使用 System.Text;使用 Android.App;使用 Android.Content;使用Android.OS;使用 Android.Runtime;使用 Android.Views;使用 Android.Widget;使用 Android.Media;使用 Android.Content.Res;使用 System.Timers;命名空间 AudioTour{[Service(Exported = false, Name = "com.AudioTour.AudioService")]公共类 AudioService :服务{//调用这个方法来启动Timer私有无效 StartCountdown(){运行定时器(2);}私人定时器 myTimer;私人 int countDownSeconds;//这是我的计时器私有无效运行计时器(int _timerLength){myTimer = new Timer();myTimer.Interval = 1000;myTimer.Elapsed += OnTimedEvent;倒计时秒数 = 5;myTimer.Enabled = true;}//当定时器超时时调用此事件私有无效 OnTimedEvent(对象发送者,System.Timers.ElapsedEventArgs elapsedEventArgs){倒计时秒数--;//这是我期望在计时器达到 0 时发生的情况if (countDownSeconds == 0){Console.WriteLine("定时器完成");Toast.MakeText(this, "Timer Finished", ToastLength.Short).Show();myTimer.Stop();}}
@jason.kaisersmith,大家好,有点不同的意见,我认为无法显示吐司是因为线程而不是 Service
本身.
服务可以像文档所说的那样显示 Toast
:
可以从活动或服务中创建和显示 Toast.如果您从服务创建 Toast 通知,它会出现在当前焦点活动的前面.
为什么不能在这个问题中显示?注意 Toast.MakeText
方法:
意思是如果你想显示toast,你必须把Toast放在主线程中,我想这就是原因.您的问题是OnTimedEvent
方法将在不同的线程 中运行,因此您在android 中不允许的线程中显示Toast
强>.
正如您所说,您只需对其进行初始化,然后将其传递到系统服务队列
.在 Toast
源代码中,我们可以证明您的意见:
//将toast插入消息队列service.enqueueToast(pkg, tn, mDuration);
现在的问题变成了如何将此消息发送到主线程.
我们只需要将toast放入主线程的消息队列中,Android给我们一个API
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();
}
}
@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 :
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 :
这篇关于为什么我的后台服务中不会出现 toast 通知(使用 System.Timer)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!