在后台服务中,我使用System.Timers创建倒计时器。
似乎有效。在控制台中2秒后,我可以看到Console.WriteLine()打印文本。
但是,Toast通知没有出现,我想知道为什么
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();
}
}
答案 0 :(得分:2)
Android中的后台服务没有UI,因此它无法生成吐司,因为这是一个UI组件。
@ jason.kaisersmith,大家好,有点不同意见,我认为吐司因为线索而不是Service
本身而无法显示。
如文档所述,服务可以显示Toast
:
可以从活动或服务创建和显示Toast。如果您从服务创建Toast通知,它将显示在当前处于焦点的活动的前面。
为什么它不能出现在这个问题中?请注意Toast.MakeText
方法:
这意味着如果你想要展示吐司,你必须把Toast放在主线程上,我想这就是原因。您的问题是OnTimedEvent
方法将在不同的主题中运行,因此您在Android 中不允许的主题中显示Toast
。
如你所说,You simply initialize it, then it gets passed off to a system service queue
。
在Toast
源代码中,我们可以证明您的意见:
//insert toast to a messagequeue
service.enqueueToast(pkg, tn, mDuration);
现在问题变成了如何将此消息发送到主线程。
我们只需将吐司放入主线程的消息队列中,Android就会给我们一个API Looper.getMainLooper()来实现这个功能,修改你的代码如下:
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();
}
}
效果: