我正在尝试在Xamarin中创建一个闹钟类型的应用程序,我现在正在努力让应用程序在特定时间打开备份,无论如何(不包括重启我知道)那就是onbootcompleted)但是当我现在关闭应用程序时,AlarmManager广播永远不会被解雇,应用程序永远不会重新打开。
现在我试图通过设置闹钟管理器在我点击按钮后1分钟弹出广播进行测试。
广播接收器
using Android.Content;
namespace (removed)
{
[BroadcastReceiver]
public class ServiceEventHandler : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
Intent temp = new Intent();
temp.SetClass(context, typeof(MainActivity));
temp.SetFlags(ActivityFlags.NewTask);
context.StartActivity(temp);
}
}
}
清单
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="(removed)" android:versionCode="1" android:versionName="1.0" android:installLocation="auto">
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="24" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.PERSISTENT_ACTIVITY" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application android:icon="@drawable/Icon" android:label="(removed)">
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
<meta-data android:name="com.google.android.geo.API_KEY" android:value="(removed)" />
</application>
</manifest>
启动闹钟的方法
private void Test_Click(object sender, EventArgs e)
{
//StartService(new Intent(this, typeof(TestService)));
Intent wake = new Intent(this, typeof(ServiceEventHandler));
PendingIntent pending = PendingIntent.GetBroadcast(this, 0, wake, 0);
var alarmMgr = (AlarmManager)GetSystemService(AlarmService);
Calendar cal = Calendar.GetInstance(Java.Util.TimeZone.Default);
cal.Set(CalendarField.HourOfDay, DateTime.Now.Hour);
cal.Set(CalendarField.Minute, DateTime.Now.Minute + 1);
cal.Set(CalendarField.Minute, cal.Get(CalendarField.Minute) + 1);//One minute for test
alarmMgr.Set(AlarmType.RtcWakeup, cal.TimeInMillis, pending);
}
答案 0 :(得分:1)
1)您可能遇到日历问题。加上这个:
cal.Set(CalendarField.Year, DateTime.Now.Year);
cal.Set(CalendarField.Month, DateTime.Now.Month - 1);
cal.Set(CalendarField.DayOfMonth, DateTime.Now.Day);
删除它:
cal.Set(CalendarField.Minute, cal.Get(CalendarField.Minute) + 1);
2)对于不同的API级别使用正确的方法可能会遇到问题。使用此:
if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
{
var launchIntent = new Intent(Application.Context, typeof(SplashActivity)); //use your starting activity
var launchPendingIntent = PendingIntent.GetActivity(Application.Context, requestCode, launchIntent,
PendingIntentFlags.CancelCurrent); //use the same request code as for 'pending'
var alarmInfo = new AlarmManager.AlarmClockInfo(cal.TimeInMillis, launchPendingIntent);
alarmMgr.SetAlarmClock(alarmInfo, pending);
}
else if (Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat)
alarmMgr.SetExact(AlarmType.RtcWakeup, cal.TimeInMillis, pending);
else
alarmMgr.Set(AlarmType.RtcWakeup, cal.TimeInMillis, pending);
答案 1 :(得分:0)
最终,在玩了几周之后,我终于发现了一种可靠的方式来发出警报,无论如何。总的来说,有很多关于这个过程的文档,但我发现其中很多都不是在一个地方。
所以这就是我所做的:
AlarmManager
中设置的警报只有在设置它的应用程序始终运行时才会持久。
因此,解决方案是拥有一个运行和管理所有警报的后台服务。
守则:
我发现使用Cal会留下很大的错误空间,特别是在使用xamarin时,所以我使用了当前的系统时间,并在现在和我希望闹钟关闭时添加了跨度
TimeSpan span = time - DateTime.Now;
long schedule = (long)(Java.Lang.JavaSystem.CurrentTimeMillis() + span.TotalMilliseconds);
这是完整的警报代码:
private void SetAlarm(DateTime time, string alarmID, int eventID, bool final)
{
if (!final)
{
Intent wake = new Intent(this, typeof(Check//Removed//Event));
wake.PutExtra("alarmID", alarmID);
PendingIntent temp = PendingIntent.GetBroadcast(this, eventID, wake, PendingIntentFlags.NoCreate);
if (temp != null)
{
temp.Cancel();
}
PendingIntent pending = PendingIntent.GetBroadcast(this, eventID, wake, PendingIntentFlags.UpdateCurrent);
var alarmMgr = (AlarmManager)GetSystemService(AlarmService);
TimeSpan span = time - DateTime.Now;
long schedule = (long)(Java.Lang.JavaSystem.CurrentTimeMillis() + span.TotalMilliseconds);
alarmMgr.SetExactAndAllowWhileIdle(AlarmType.RtcWakeup, schedule, pending);
}
else
{//Set Alarm
Intent wake = new Intent(this, typeof(//Removed//Event));
wake.PutExtra("alarmID", alarmID);
PendingIntent temp = PendingIntent.GetBroadcast(this, eventID, wake, PendingIntentFlags.NoCreate);
if (temp != null)
{
temp.Cancel();
}
PendingIntent pending = PendingIntent.GetBroadcast(this, eventID, wake, PendingIntentFlags.UpdateCurrent);
var alarmMgr = (AlarmManager)GetSystemService(AlarmService);
TimeSpan span = time - DateTime.Now;
long schedule = (long)(Java.Lang.JavaSystem.CurrentTimeMillis() + span.TotalMilliseconds);
alarmMgr.SetExactAndAllowWhileIdle(AlarmType.RtcWakeup, schedule, pending);
}
}
}
准确设置闹钟。至于使所有内容持久化,我使服务变得粘滞,并将其设置为每次重置时重置所有警报。这是通过检查广播是否已经存在,然后将其删除并重新安排(如果广播)来实现的。
PendingIntent temp = PendingIntent.GetBroadcast(this, eventID, wake, PendingIntentFlags.NoCreate);
if (temp != null)
{
temp.Cancel();
}
这个和获得启动通知的广播接收器的组合使警报尽可能持久。