2017-08-11 68 views
0

在後臺服務中,我使用System.Timers創建一個倒數計時器。爲什麼在我的後臺Service(使用System.Timer)中不會出現Toast通知?

這似乎工作。在控制檯中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(); 
      } 
     } 

回答

1

在Android的後臺服務沒有一個用戶界面,因此它不能產生舉杯,因爲這是一個UI組件。

@ jason.kaisersmith,嗨,大家好,有一點不同的意見,我想是因爲線程,而不是Service本身的顯示敬酒着。

服務可以顯示Toast作爲文檔說:

可以創建一個烤麪包和從活動或服務顯示。如果您通過服務創建了Toast通知,它會出現在當前焦點活動的前面。

爲什麼它不能在這個問題中顯示?請注意,Toast.MakeText方法:

enter image description here

這意味着,如果你想顯示敬酒,你必須把吐司主線程,我想這就是原因。您的問題是OnTimedEvent方法將運行在不同的線程所以您正在顯示Toast在一個不允許在android線程。

正如你所說,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(); 
    } 
} 

效果:

enter image description here

+0

謝謝你這麼多的這個答案約克。其中最全面的我有。 – Jim

相關問題