2016-03-06 191 views
1

我想通過AlarmManager定期調用線程。問題是,在給定的時間段之後,OnReceive()會被調用兩次(爲什麼?),然後再也不會再次調用。我在這裏做錯了什麼?
我與Xamarin(C#)Android版API級別從MainActivity工作23AlarmManager.SetRepeating not working properly

代碼:

Alarm alarm = new Alarm(); 
RegisterReceiver (alarm, new IntentFilter ("com.company.BROADCAST")); 
alarm.SetAlarm(this); 

報警類別:

[BroadcastReceiver] 
[IntentFilter(new string[] {"com.company.BROADCAST"})] 
public class Alarm : BroadcastReceiver 
{ 
    public override void OnReceive(Context c, Intent i) 
    { 
     Toast.MakeText (c, "hi", ToastLength.Short).Show(); 
    } 

    public void SetAlarm(Context context) 
    { 
     AlarmManager am = (AlarmManager)context.GetSystemService(Context.AlarmService); 
     Intent i = new Intent("com.company.BROADCAST"); 
     PendingIntent pi = PendingIntent.GetBroadcast(context, 0, i, 0); 
     am.SetRepeating(AlarmType.ElapsedRealtimeWakeup, SystemClock.ElapsedRealtime() + 1000, 1000 * 2, pi); 
    } 
} 

回答

1

OnReceive被稱爲兩次,因爲你不小心註冊了兩次警報。讓我們添加下面的代碼片段到你的Alarm類:

[BroadcastReceiver] 
[IntentFilter(new string[] {"com.company.BROADCAST"})] 
public class Alarm : BroadcastReceiver 
{ 

    public Alarm() 
     : base() 
    { 
     Console.WriteLine ("Alarm made: " + this.GetHashCode()); 
    } 

    public Alarm(System.IntPtr handle, Android.Runtime.JniHandleOwnership transfer) 
     : base(handle, transfer) 
    { 
     Console.WriteLine ("Alarm made: " + this.GetHashCode()); 
    } 

    // ... 
} 

如果我們運行應用程序時,將Alarm註銷一個獨特的哈希碼爲創建的每個實例。因此,啓動應用程序並觀察應用程序輸出中發生的情況:

Alarm made: 123719217 
... 
Alarm made: 119997678 

哇!我們有兩個實例......這是怎麼發生的?

屬性[IntentFilter(new string[] {"com.company.BROADCAST"})]爲您的Alarm : BroadcastReceiver生成清單條目,這會導致它自動偵聽com.company.BROADCAST的廣播。 Xamarin文檔有一個很好的解釋here

當您在您的活動中致電RegisterReceiver時,會發生第二次註冊。這注冊了Alarm的新的唯一實例來監聽com.company.BROADCAST的廣播。

您可以通過從Alarm中刪除[IntentFilter(new string[] {"com.company.BROADCAST"})]屬性或在活動中刪除RegisterReceiver調用來修復「正在調用兩次警報」問題。


其次,2000毫秒對於AlarmManager來說頻率太小。它會自動擴展到60秒,以延長電池壽命。

如果你運行你的樣品和使用的logcat捕捉系統輸出你會發現證實了這一消息:

W/AlarmManager( 579): Suspiciously short interval 2000 millis; expanding to 60 seconds 

如果你想重複操作太頻繁,請考慮使用定時器或交延遲處理程序:

// Frequent operation using .NET Timer. 
System.Timers.Timer t = new System.Timers.Timer (1000); 
t.AutoReset = true; 
t.Elapsed += (object sender, System.Timers.ElapsedEventArgs e) => { 
    t.Interval = 2000; 
    RunOnUiThread (() => Toast.MakeText (this, "Hi", ToastLength.Short).Show()); 
}; 
t.Start(); 

// Frequent operation using Android.OS.Handler 
handler = new Handler(); 
Action callback = null; 
callback =() => { 
    //Do something after 100ms 
    Toast.MakeText(this, "Hi", ToastLength.Short).Show(); 
    handler.PostDelayed(callback, 2000); 
}; 
handler.PostDelayed(callback, 1000); 
+0

感謝您的幫助,我不知道這一點。你有什麼想法爲什麼警報不重複? – AllRight

+0

我想說2000ms的重複間隔太小。 Android通常會將小於1分鐘的間隔擴展到一分鐘。讓我確認,雖然 – matthewrdev

+0

@AllRight查看更新的答案。 – matthewrdev