我正试图通过AlarmManager定期调用一个线程。问题是,在给定的时间段后,OnReceive()被调用两次(为什么?)然后再也没有。我在这做错了什么?
我在API级别23上使用Xamarin(C#)for Android。
MainActivity的代码:
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);
}
}
答案 0 :(得分: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
哇!我们有2个实例......那是怎么发生的?
属性[IntentFilter(new string[] {"com.company.BROADCAST"})]
会为您的Alarm : BroadcastReceiver
生成一个清单条目,使其自动收听com.company.BROADCAST
的广播。 Xamarin文档有一个很好的解释here。
当您在活动中致电RegisterReceiver
时,会发生第二次注册。这会注册一个新的Alarm
唯一实例来监听com.company.BROADCAST
的广播。
你可以修复被叫两次的警报"通过从[IntentFilter(new string[] {"com.company.BROADCAST"})]
移除Alarm
属性或移除活动中的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);