AlarmManager.SetRepeating 工作不正常
AlarmManager.SetRepeating not working properly
我试图通过 AlarmManager 定期调用一个线程。问题是,在给定的时间段之后,OnReceive() 被调用了两次(为什么?),然后再也没有调用过。我在这里做错了什么?
我正在 API 级别 23 上使用 Xamarin (C#) Android。
来自 MainActivity 的代码:
Alarm alarm = new Alarm ();
RegisterReceiver (alarm, new IntentFilter ("com.company.BROADCAST"));
alarm.SetAlarm(this);
闹钟class:
[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);
}
}
OnReceive
被调用两次,因为您不小心将闹钟注册了两次。让我们将以下代码片段添加到您的 Alarm
class:
[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.
当您在 activity 中调用 RegisterReceiver
时,会发生第二次注册。这会注册一个新的、唯一的 Alarm
实例来监听 com.company.BROADCAST
.
的广播
您可以通过从 Alarm
中删除 [IntentFilter(new string[] {"com.company.BROADCAST"})]
属性或删除 activity 中的 RegisterReceiver
调用来修复 "alarm being called twice" 问题。
其次,2000 毫秒对于 AlarmManager 来说太小了。它会自动将其延长至 60 秒以延长电池寿命。
如果您 运行 您的示例并使用 logcat 捕获系统输出,您将看到一条消息来确认这一点:
W/AlarmManager( 579): Suspiciously short interval 2000 millis; expanding to 60 seconds
如果你想如此频繁地重复操作,请考虑使用定时器或 post 延迟处理程序:
// 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);
我试图通过 AlarmManager 定期调用一个线程。问题是,在给定的时间段之后,OnReceive() 被调用了两次(为什么?),然后再也没有调用过。我在这里做错了什么?
我正在 API 级别 23 上使用 Xamarin (C#) Android。
来自 MainActivity 的代码:
Alarm alarm = new Alarm ();
RegisterReceiver (alarm, new IntentFilter ("com.company.BROADCAST"));
alarm.SetAlarm(this);
闹钟class:
[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);
}
}
OnReceive
被调用两次,因为您不小心将闹钟注册了两次。让我们将以下代码片段添加到您的 Alarm
class:
[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.
当您在 activity 中调用 RegisterReceiver
时,会发生第二次注册。这会注册一个新的、唯一的 Alarm
实例来监听 com.company.BROADCAST
.
您可以通过从 Alarm
中删除 [IntentFilter(new string[] {"com.company.BROADCAST"})]
属性或删除 activity 中的 RegisterReceiver
调用来修复 "alarm being called twice" 问题。
其次,2000 毫秒对于 AlarmManager 来说太小了。它会自动将其延长至 60 秒以延长电池寿命。
如果您 运行 您的示例并使用 logcat 捕获系统输出,您将看到一条消息来确认这一点:
W/AlarmManager( 579): Suspiciously short interval 2000 millis; expanding to 60 seconds
如果你想如此频繁地重复操作,请考虑使用定时器或 post 延迟处理程序:
// 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);