AlarmManager 在睡眠模式下不触发
AlarmManager not firing when in sleep mode
正如标题所说,我的 AlarmManager 经常不触发,或者更确切地说,似乎会触发 on-pause,因此警报会延迟触发(我正在使用 SetExactAndAllowWhileIdle),有时会非常高延迟破坏了我的应用程序的目的。
我的应用程序有一个前台进程,我已经将该应用程序添加到 IgnoreBatteryOptimizations 并禁用了 OEM 电池优化。
我的 Samsung S7 Edges 上有这些问题,但在模拟器上(也测试了打瞌睡)一切正常,所以我知道这是由 OEM 引起的问题,但有人知道吗如何解决?
下面是一些相关代码:
报警广播接收器:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Android.Content;
using Android.Util;
namespace CGSJDSportsNotification.Droid {
public partial class JDMonitoring {
[BroadcastReceiver]
public partial class BackgroundWorker : BroadcastReceiver {
Helper H { get; } = new Helper(60 * SharedSettings.Entries.Get.Int32("searchRefresh"));
public override void OnReceive(Context context, Intent intent) {
FetchTickets();
}
async void FetchTickets() {
Log.Debug("jd_foo", "STARTED");
// Reinitialize the Browser class
if (H.browser == null) {
Log.Debug("jd_foo", "BROWSER == NULL");
H.wc = new Browser.CustomWebViewClient();
H.wc.OnPageStart += BrowserOnPageStarted;
H.wc.OnPageLoaded += BrowserOnPageLoaded;
await H.BrowserInit();
Log.Debug("jd_foo", "BROWSER_INIT_SUCCESS");
}
if (await H.Net_Or_FgServiceAreNotActive())
goto CleanUpWebView;
Log.Debug("jd_foo", "NET_OR_FGSERVICE_OK");
UserNotification.Remove(12029); // Removes the 'No Internet' notification when the connection is back
UserNotification.Remove(503); // Removes the 'Server took too long to respond' notification when is back
UserNotification.Remove(0); // Notification warning group id
// Resets the process cycle
H.ProcessPhase = 0;
H.InDepthProcess = false;
H.browser.LoadUrl(H.UrlQueuePage);
Log.Debug("jd_foo", "PREPARING_WHILE_PHASE_0");
// Waits for the log-in page to fully load
while (H.ProcessPhase == 0) {
if (await H.Net_Or_FgServiceAreNotActive())
goto CleanUpWebView;
await Task.Delay(100);
}
Log.Debug("jd_foo", "WHILE_PHASE_O_PASSED");
bool? loginPage = await H.IsOnLoginPage();
Log.Debug("jd_foo", $"ON_LOGIN_PAGE = {loginPage}");
if (loginPage == true) {
bool? loginResponse = await H.Login();
Log.Debug("jd_foo", $"LOGIN_RESPONSE = {loginResponse}");
if (loginResponse == false) {
if (await H.Net_Or_FgServiceAreNotActive())
goto CleanUpWebView;
H.BackgroundWorkerReset();
goto CleanUpWebView;
} else if (loginResponse == null)
// If Login function returns null means that there's no internet connection or the server is down
goto CleanUpWebView;
} else if (loginPage == false) {
if (await H.Net_Or_FgServiceAreNotActive())
goto CleanUpWebView;
// If at this point ProcessPhase is 1 this means that the browser session was cleaned and the we loggedin again
if (H.ProcessPhase == 1)
H.browser.LoadUrl(H.UrlQueuePage);
} else
// If null is returned, this means that there's no internet connection or the server is down
goto CleanUpWebView;
Log.Debug("jd_foo", "PREPARING_WHILE_PROCESS_PHASE_1");
// Waits for the queue page to fully load
while (H.ProcessPhase == 1) {
if (await H.Net_Or_FgServiceAreNotActive())
goto CleanUpWebView;
await Task.Delay(100);
}
Log.Debug("jd_foo", "WHILE_PHASE_1_PASSED");
if (await H.JDServerIsOk() == false)
goto CleanUpWebView;
Log.Debug("jd_foo", "JD_SERVER_OK");
// Checks if the queue HTML table element is present
if (await H.browser.ElementExists("document.getElementsByClassName('ticket-list collection-as-table')[0]")) {
Log.Debug("jd_foo", "QUEUE_TABLE_OK");
List<Ticket> tkts = await H.GetTickets();
Log.Debug("jd_foo", "GOT_TKTS_OK");
string country = SharedSettings.Entries.Get.String("searchCountrySelected").ToLower();
// Fetch all the tickets inside the time frame chosen by the user
// Starts from the end of the list in order to show the recent tkts on top
for (int i = tkts.Count - 1; i >= 0; i--) {
Ticket t = tkts[i];
// Checks only the tkts with the 'open' or 'new' status
//if (t.Status.ToLower() == "open" || t.Status.ToLower() == "new") {
if (t.Status.Length > 0) { //-- Used for testing
// The first and fastest step is to check the tkt title
if (t.Title.ToLower().Contains(country)) {
H.DisplayNotification(t.ID, t.LastUpdated, t.Title, t.Status, t.Owner, country, t.Link);
} else if (H.TktIsWithoutCountry(t.Title)) {
if (await H.JDServerIsOk() == false)
goto CleanUpWebView;
// Country not found in the title, we must dig deeper by opening the tkt link
H.InDepthProcess = true;
H.browser.LoadUrl(t.Link);
// Waits for the tkt url to load
while (H.ProcessPhase == 2) {
if (await H.Net_Or_FgServiceAreNotActive())
goto CleanUpWebView;
await Task.Delay(100);
}
// Gets the page's body
string pBody = await H.browser.EvalJS("document.body.textContent");
// If the selected country by the user is present somewhere into the tkt page body
if (pBody.IndexOf(country, StringComparison.OrdinalIgnoreCase) > -1) {
H.DisplayNotification(t.ID, t.LastUpdated, t.Title, t.Status, t.Owner, country, t.Link);
} else if (H.TktIsWithoutCountry(pBody)) {
// If the country string isn't present and the user has chosen to check also for tkts with unknown countries
if (SharedSettings.Entries.Get.Bool("searchUnknownCountry"))
H.DisplayNotification(t.ID, t.LastUpdated, t.Title, t.Status, t.Owner, "unknown", t.Link);
}
// Ready for the next ticket
H.ProcessPhase = 2;
}
}
}
}
Log.Debug("jd_foo", "STARTING_CLEAN_UP");
CleanUpWebView:
// Tries to free the memory asap
H.FreeMemory();
// Reschedules the alarm
H.BackgroundWorkerReset();
Log.Debug("jd_foo", "CLEAN_UP_OK");
}
public async void BrowserOnPageStarted(object sender, string url) {
if (await H.Net_Or_FgServiceAreNotActive())
return;
}
async void BrowserOnPageLoaded(object sender, string url) {
if (await H.Net_Or_FgServiceAreNotActive())
return;
// When the login page has loaded
if (url.StartsWith(H.UrlLoginPage)) {
// Login again in order to access the tkt page
if (H.InDepthProcess)
await H.Login();
else
// First login
H.ProcessPhase = 1;
// Saves the login session
Android.Webkit.CookieManager.Instance.Flush();
}
// When the queue page has loaded
if (url.Equals(H.UrlQueuePage))
H.ProcessPhase = 2;
// When the tkt page has loaded
if (url.StartsWith("https://support.jdplc.com/rt4/Ticket/Display.html?id=") && H.InDepthProcess) {
while (await H.browser.EvalJS("document.getElementById('TitleBox--_Helpers_TicketHistory------SGlzdG9yeQ__---0')") == null) {
if (await H.Net_Or_FgServiceAreNotActive() || await H.JDServerIsOk() == false)
return;
await Task.Delay(1000);
}
H.ProcessPhase = 3;
}
}
}
}
}
报警辅助方法:
public static void BackgroundWorkerFire(int alarmMilliseconds) {
((AlarmManager)(new ContextWrapper(AndroidContext)).GetSystemService(Context.AlarmService))
.SetExactAndAllowWhileIdle(
AlarmType.ElapsedRealtimeWakeup,
SystemClock.ElapsedRealtime() + alarmMilliseconds,
PendingIntent.GetBroadcast(
AndroidContext,
98,
new Intent(
AndroidContext,
typeof(JDMonitoring.BackgroundWorker)),
PendingIntentFlags.UpdateCurrent));
}
public void BackgroundWorkerReset(int seconds = -1) {
BackgroundWorkerStop();
BackgroundWorkerFire(seconds == -1 ? RefreshRate : 1000 * seconds);
}
未及时触发示例:
06-27 21:19:54.962 25634 25634 D jd_foo : STARTED
06-27 21:19:54.962 25634 25634 D jd_foo : BROWSER == NULL
06-27 21:19:55.766 25634 25634 D jd_foo : BROWSER_INIT_SUCCESS
06-27 21:19:55.842 25634 25634 D jd_foo : NET_OR_FGSERVICE_OK
06-27 21:19:55.851 25634 25634 D jd_foo : PREPARING_WHILE_PHASE_0
06-27 21:19:59.699 25634 25634 D jd_foo : WHILE_PHASE_O_PASSED
06-27 21:19:59.791 25634 25634 D jd_foo : ON_LOGIN_PAGE = True
06-27 21:20:05.093 25634 25634 D jd_foo : LOGIN_RESPONSE = True
06-27 21:20:05.093 25634 25634 D jd_foo : PREPARING_WHILE_PROCESS_PHASE_1
06-27 21:20:05.795 25634 25634 D jd_foo : WHILE_PHASE_1_PASSED
06-27 21:20:05.803 25634 25634 D jd_foo : JD_SERVER_OK
06-27 21:20:05.814 25634 25634 D jd_foo : QUEUE_TABLE_OK
06-27 21:20:06.411 25634 25634 D jd_foo : GOT_TKTS_OK
06-27 21:20:08.666 25634 25634 D jd_foo : STARTING_CLEAN_UP
06-27 21:20:08.714 25634 25634 D jd_foo : CLEAN_UP_OK
06-27 21:33:37.282 25634 25634 D jd_foo : STARTED
06-27 21:33:37.284 25634 25634 D jd_foo : BROWSER == NULL
06-27 21:33:37.415 25634 25634 D jd_foo : BROWSER_INIT_SUCCESS
06-27 21:33:37.429 25634 25634 D jd_foo : NET_OR_FGSERVICE_OK
06-27 21:33:37.437 25634 25634 D jd_foo : PREPARING_WHILE_PHASE_0
06-27 21:33:39.572 25634 25634 D jd_foo : WHILE_PHASE_O_PASSED
06-27 21:33:39.599 25634 25634 D jd_foo : ON_LOGIN_PAGE = True
06-27 21:33:44.871 25634 25634 D jd_foo : LOGIN_RESPONSE = True
06-27 21:33:44.871 25634 25634 D jd_foo : PREPARING_WHILE_PROCESS_PHASE_1
06-27 21:33:44.872 25634 25634 D jd_foo : WHILE_PHASE_1_PASSED
06-27 21:33:44.890 25634 25634 D jd_foo : JD_SERVER_OK
06-27 21:33:44.909 25634 25634 D jd_foo : QUEUE_TABLE_OK
06-27 21:33:45.732 25634 25634 D jd_foo : GOT_TKTS_OK
06-27 21:33:47.383 25634 25634 D jd_foo : STARTING_CLEAN_UP
06-27 21:33:47.452 25634 25634 D jd_foo : CLEAN_UP_OK
06-27 21:48:37.318 25634 25634 D jd_foo : STARTED
06-27 21:48:37.318 25634 25634 D jd_foo : BROWSER == NULL
06-27 21:48:37.442 25634 25634 D jd_foo : BROWSER_INIT_SUCCESS
06-27 21:48:37.463 25634 25634 D jd_foo : NET_OR_FGSERVICE_OK
06-27 21:48:37.470 25634 25634 D jd_foo : PREPARING_WHILE_PHASE_0
06-27 21:48:39.523 25634 25634 D jd_foo : WHILE_PHASE_O_PASSED
06-27 21:48:39.578 25634 25634 D jd_foo : ON_LOGIN_PAGE = True
06-27 21:48:44.943 25634 25634 D jd_foo : LOGIN_RESPONSE = True
06-27 21:48:44.944 25634 25634 D jd_foo : PREPARING_WHILE_PROCESS_PHASE_1
06-27 21:48:44.944 25634 25634 D jd_foo : WHILE_PHASE_1_PASSED
06-27 21:48:44.962 25634 25634 D jd_foo : JD_SERVER_OK
06-27 21:48:44.980 25634 25634 D jd_foo : QUEUE_TABLE_OK
06-27 21:48:46.221 25634 25634 D jd_foo : GOT_TKTS_OK
06-27 21:48:47.869 25634 25634 D jd_foo : STARTING_CLEAN_UP
06-27 21:48:47.931 25634 25634 D jd_foo : CLEAN_UP_OK
06-27 22:03:37.396 25634 25634 D jd_foo : STARTED
06-27 22:03:37.398 25634 25634 D jd_foo : BROWSER == NULL
06-27 22:03:37.565 25634 25634 D jd_foo : BROWSER_INIT_SUCCESS
06-27 22:03:37.581 25634 25634 D jd_foo : NET_OR_FGSERVICE_OK
06-27 22:03:37.586 25634 25634 D jd_foo : PREPARING_WHILE_PHASE_0
06-27 22:03:39.581 25634 25634 D jd_foo : WHILE_PHASE_O_PASSED
06-27 22:03:39.620 25634 25634 D jd_foo : ON_LOGIN_PAGE = True
06-27 22:03:44.860 25634 25634 D jd_foo : LOGIN_RESPONSE = True
06-27 22:03:44.861 25634 25634 D jd_foo : PREPARING_WHILE_PROCESS_PHASE_1
06-27 22:03:44.861 25634 25634 D jd_foo : WHILE_PHASE_1_PASSED
06-27 22:03:44.879 25634 25634 D jd_foo : JD_SERVER_OK
06-27 22:03:44.893 25634 25634 D jd_foo : QUEUE_TABLE_OK
06-27 22:03:45.754 25634 25634 D jd_foo : GOT_TKTS_OK
06-27 22:03:47.549 25634 25634 D jd_foo : STARTING_CLEAN_UP
06-27 22:03:47.625 25634 25634 D jd_foo : CLEAN_UP_OK
06-27 22:18:37.288 25634 25634 D jd_foo : STARTED
06-27 22:18:37.289 25634 25634 D jd_foo : BROWSER == NULL
06-27 22:18:37.422 25634 25634 D jd_foo : BROWSER_INIT_SUCCESS
06-27 22:18:37.438 25634 25634 D jd_foo : NET_OR_FGSERVICE_OK
06-27 22:18:37.443 25634 25634 D jd_foo : PREPARING_WHILE_PHASE_0
06-27 22:18:39.343 25634 25634 D jd_foo : WHILE_PHASE_O_PASSED
06-27 22:18:39.400 25634 25634 D jd_foo : ON_LOGIN_PAGE = True
06-27 22:18:44.643 25634 25634 D jd_foo : LOGIN_RESPONSE = True
06-27 22:18:44.644 25634 25634 D jd_foo : PREPARING_WHILE_PROCESS_PHASE_1
06-27 22:18:44.644 25634 25634 D jd_foo : WHILE_PHASE_1_PASSED
06-27 22:18:44.651 25634 25634 D jd_foo : JD_SERVER_OK
06-27 22:18:44.658 25634 25634 D jd_foo : QUEUE_TABLE_OK
06-27 22:18:45.483 25634 25634 D jd_foo : GOT_TKTS_OK
06-27 22:18:47.087 25634 25634 D jd_foo : STARTING_CLEAN_UP
06-27 22:18:47.167 25634 25634 D jd_foo : CLEAN_UP_OK
如您所见,第一次发射是在 21:19,然后是 21:33,然后是 21:48。
但是应该每 10 分钟被解雇一次
我真的不明白为什么:/
P.S: 我刚才也注意到,即使我使用 AlarmType.ElapsedRealtimeWakeup)
屏幕也不会唤醒
[编辑]
现在我已经测试了更长的时间,看起来第一次触发后的警报每 15 分钟触发一次,这对我的应用程序来说不是大问题,但为什么呢?
为了减少滥用,对特定应用程序发出这些警报的频率有限制。在正常的系统操作下,它发送这些警报的时间不会超过大约每分钟一次(此时将发送每个此类未决警报);在低功耗空闲模式下,此持续时间可能会明显更长,例如 15 分钟。
所以,这很正常,“精确”并不那么精确,它的名称具有误导性。
正如标题所说,我的 AlarmManager 经常不触发,或者更确切地说,似乎会触发 on-pause,因此警报会延迟触发(我正在使用 SetExactAndAllowWhileIdle),有时会非常高延迟破坏了我的应用程序的目的。
我的应用程序有一个前台进程,我已经将该应用程序添加到 IgnoreBatteryOptimizations 并禁用了 OEM 电池优化。
我的 Samsung S7 Edges 上有这些问题,但在模拟器上(也测试了打瞌睡)一切正常,所以我知道这是由 OEM 引起的问题,但有人知道吗如何解决?
下面是一些相关代码:
报警广播接收器:
using System; using System.Collections.Generic; using System.Threading.Tasks; using Android.Content; using Android.Util; namespace CGSJDSportsNotification.Droid { public partial class JDMonitoring { [BroadcastReceiver] public partial class BackgroundWorker : BroadcastReceiver { Helper H { get; } = new Helper(60 * SharedSettings.Entries.Get.Int32("searchRefresh")); public override void OnReceive(Context context, Intent intent) { FetchTickets(); } async void FetchTickets() { Log.Debug("jd_foo", "STARTED"); // Reinitialize the Browser class if (H.browser == null) { Log.Debug("jd_foo", "BROWSER == NULL"); H.wc = new Browser.CustomWebViewClient(); H.wc.OnPageStart += BrowserOnPageStarted; H.wc.OnPageLoaded += BrowserOnPageLoaded; await H.BrowserInit(); Log.Debug("jd_foo", "BROWSER_INIT_SUCCESS"); } if (await H.Net_Or_FgServiceAreNotActive()) goto CleanUpWebView; Log.Debug("jd_foo", "NET_OR_FGSERVICE_OK"); UserNotification.Remove(12029); // Removes the 'No Internet' notification when the connection is back UserNotification.Remove(503); // Removes the 'Server took too long to respond' notification when is back UserNotification.Remove(0); // Notification warning group id // Resets the process cycle H.ProcessPhase = 0; H.InDepthProcess = false; H.browser.LoadUrl(H.UrlQueuePage); Log.Debug("jd_foo", "PREPARING_WHILE_PHASE_0"); // Waits for the log-in page to fully load while (H.ProcessPhase == 0) { if (await H.Net_Or_FgServiceAreNotActive()) goto CleanUpWebView; await Task.Delay(100); } Log.Debug("jd_foo", "WHILE_PHASE_O_PASSED"); bool? loginPage = await H.IsOnLoginPage(); Log.Debug("jd_foo", $"ON_LOGIN_PAGE = {loginPage}"); if (loginPage == true) { bool? loginResponse = await H.Login(); Log.Debug("jd_foo", $"LOGIN_RESPONSE = {loginResponse}"); if (loginResponse == false) { if (await H.Net_Or_FgServiceAreNotActive()) goto CleanUpWebView; H.BackgroundWorkerReset(); goto CleanUpWebView; } else if (loginResponse == null) // If Login function returns null means that there's no internet connection or the server is down goto CleanUpWebView; } else if (loginPage == false) { if (await H.Net_Or_FgServiceAreNotActive()) goto CleanUpWebView; // If at this point ProcessPhase is 1 this means that the browser session was cleaned and the we loggedin again if (H.ProcessPhase == 1) H.browser.LoadUrl(H.UrlQueuePage); } else // If null is returned, this means that there's no internet connection or the server is down goto CleanUpWebView; Log.Debug("jd_foo", "PREPARING_WHILE_PROCESS_PHASE_1"); // Waits for the queue page to fully load while (H.ProcessPhase == 1) { if (await H.Net_Or_FgServiceAreNotActive()) goto CleanUpWebView; await Task.Delay(100); } Log.Debug("jd_foo", "WHILE_PHASE_1_PASSED"); if (await H.JDServerIsOk() == false) goto CleanUpWebView; Log.Debug("jd_foo", "JD_SERVER_OK"); // Checks if the queue HTML table element is present if (await H.browser.ElementExists("document.getElementsByClassName('ticket-list collection-as-table')[0]")) { Log.Debug("jd_foo", "QUEUE_TABLE_OK"); List<Ticket> tkts = await H.GetTickets(); Log.Debug("jd_foo", "GOT_TKTS_OK"); string country = SharedSettings.Entries.Get.String("searchCountrySelected").ToLower(); // Fetch all the tickets inside the time frame chosen by the user // Starts from the end of the list in order to show the recent tkts on top for (int i = tkts.Count - 1; i >= 0; i--) { Ticket t = tkts[i]; // Checks only the tkts with the 'open' or 'new' status //if (t.Status.ToLower() == "open" || t.Status.ToLower() == "new") { if (t.Status.Length > 0) { //-- Used for testing // The first and fastest step is to check the tkt title if (t.Title.ToLower().Contains(country)) { H.DisplayNotification(t.ID, t.LastUpdated, t.Title, t.Status, t.Owner, country, t.Link); } else if (H.TktIsWithoutCountry(t.Title)) { if (await H.JDServerIsOk() == false) goto CleanUpWebView; // Country not found in the title, we must dig deeper by opening the tkt link H.InDepthProcess = true; H.browser.LoadUrl(t.Link); // Waits for the tkt url to load while (H.ProcessPhase == 2) { if (await H.Net_Or_FgServiceAreNotActive()) goto CleanUpWebView; await Task.Delay(100); } // Gets the page's body string pBody = await H.browser.EvalJS("document.body.textContent"); // If the selected country by the user is present somewhere into the tkt page body if (pBody.IndexOf(country, StringComparison.OrdinalIgnoreCase) > -1) { H.DisplayNotification(t.ID, t.LastUpdated, t.Title, t.Status, t.Owner, country, t.Link); } else if (H.TktIsWithoutCountry(pBody)) { // If the country string isn't present and the user has chosen to check also for tkts with unknown countries if (SharedSettings.Entries.Get.Bool("searchUnknownCountry")) H.DisplayNotification(t.ID, t.LastUpdated, t.Title, t.Status, t.Owner, "unknown", t.Link); } // Ready for the next ticket H.ProcessPhase = 2; } } } } Log.Debug("jd_foo", "STARTING_CLEAN_UP"); CleanUpWebView: // Tries to free the memory asap H.FreeMemory(); // Reschedules the alarm H.BackgroundWorkerReset(); Log.Debug("jd_foo", "CLEAN_UP_OK"); } public async void BrowserOnPageStarted(object sender, string url) { if (await H.Net_Or_FgServiceAreNotActive()) return; } async void BrowserOnPageLoaded(object sender, string url) { if (await H.Net_Or_FgServiceAreNotActive()) return; // When the login page has loaded if (url.StartsWith(H.UrlLoginPage)) { // Login again in order to access the tkt page if (H.InDepthProcess) await H.Login(); else // First login H.ProcessPhase = 1; // Saves the login session Android.Webkit.CookieManager.Instance.Flush(); } // When the queue page has loaded if (url.Equals(H.UrlQueuePage)) H.ProcessPhase = 2; // When the tkt page has loaded if (url.StartsWith("https://support.jdplc.com/rt4/Ticket/Display.html?id=") && H.InDepthProcess) { while (await H.browser.EvalJS("document.getElementById('TitleBox--_Helpers_TicketHistory------SGlzdG9yeQ__---0')") == null) { if (await H.Net_Or_FgServiceAreNotActive() || await H.JDServerIsOk() == false) return; await Task.Delay(1000); } H.ProcessPhase = 3; } } } } }
报警辅助方法:
public static void BackgroundWorkerFire(int alarmMilliseconds) { ((AlarmManager)(new ContextWrapper(AndroidContext)).GetSystemService(Context.AlarmService)) .SetExactAndAllowWhileIdle( AlarmType.ElapsedRealtimeWakeup, SystemClock.ElapsedRealtime() + alarmMilliseconds, PendingIntent.GetBroadcast( AndroidContext, 98, new Intent( AndroidContext, typeof(JDMonitoring.BackgroundWorker)), PendingIntentFlags.UpdateCurrent)); } public void BackgroundWorkerReset(int seconds = -1) { BackgroundWorkerStop(); BackgroundWorkerFire(seconds == -1 ? RefreshRate : 1000 * seconds); }
未及时触发示例:
06-27 21:19:54.962 25634 25634 D jd_foo : STARTED 06-27 21:19:54.962 25634 25634 D jd_foo : BROWSER == NULL 06-27 21:19:55.766 25634 25634 D jd_foo : BROWSER_INIT_SUCCESS 06-27 21:19:55.842 25634 25634 D jd_foo : NET_OR_FGSERVICE_OK 06-27 21:19:55.851 25634 25634 D jd_foo : PREPARING_WHILE_PHASE_0 06-27 21:19:59.699 25634 25634 D jd_foo : WHILE_PHASE_O_PASSED 06-27 21:19:59.791 25634 25634 D jd_foo : ON_LOGIN_PAGE = True 06-27 21:20:05.093 25634 25634 D jd_foo : LOGIN_RESPONSE = True 06-27 21:20:05.093 25634 25634 D jd_foo : PREPARING_WHILE_PROCESS_PHASE_1 06-27 21:20:05.795 25634 25634 D jd_foo : WHILE_PHASE_1_PASSED 06-27 21:20:05.803 25634 25634 D jd_foo : JD_SERVER_OK 06-27 21:20:05.814 25634 25634 D jd_foo : QUEUE_TABLE_OK 06-27 21:20:06.411 25634 25634 D jd_foo : GOT_TKTS_OK 06-27 21:20:08.666 25634 25634 D jd_foo : STARTING_CLEAN_UP 06-27 21:20:08.714 25634 25634 D jd_foo : CLEAN_UP_OK 06-27 21:33:37.282 25634 25634 D jd_foo : STARTED 06-27 21:33:37.284 25634 25634 D jd_foo : BROWSER == NULL 06-27 21:33:37.415 25634 25634 D jd_foo : BROWSER_INIT_SUCCESS 06-27 21:33:37.429 25634 25634 D jd_foo : NET_OR_FGSERVICE_OK 06-27 21:33:37.437 25634 25634 D jd_foo : PREPARING_WHILE_PHASE_0 06-27 21:33:39.572 25634 25634 D jd_foo : WHILE_PHASE_O_PASSED 06-27 21:33:39.599 25634 25634 D jd_foo : ON_LOGIN_PAGE = True 06-27 21:33:44.871 25634 25634 D jd_foo : LOGIN_RESPONSE = True 06-27 21:33:44.871 25634 25634 D jd_foo : PREPARING_WHILE_PROCESS_PHASE_1 06-27 21:33:44.872 25634 25634 D jd_foo : WHILE_PHASE_1_PASSED 06-27 21:33:44.890 25634 25634 D jd_foo : JD_SERVER_OK 06-27 21:33:44.909 25634 25634 D jd_foo : QUEUE_TABLE_OK 06-27 21:33:45.732 25634 25634 D jd_foo : GOT_TKTS_OK 06-27 21:33:47.383 25634 25634 D jd_foo : STARTING_CLEAN_UP 06-27 21:33:47.452 25634 25634 D jd_foo : CLEAN_UP_OK 06-27 21:48:37.318 25634 25634 D jd_foo : STARTED 06-27 21:48:37.318 25634 25634 D jd_foo : BROWSER == NULL 06-27 21:48:37.442 25634 25634 D jd_foo : BROWSER_INIT_SUCCESS 06-27 21:48:37.463 25634 25634 D jd_foo : NET_OR_FGSERVICE_OK 06-27 21:48:37.470 25634 25634 D jd_foo : PREPARING_WHILE_PHASE_0 06-27 21:48:39.523 25634 25634 D jd_foo : WHILE_PHASE_O_PASSED 06-27 21:48:39.578 25634 25634 D jd_foo : ON_LOGIN_PAGE = True 06-27 21:48:44.943 25634 25634 D jd_foo : LOGIN_RESPONSE = True 06-27 21:48:44.944 25634 25634 D jd_foo : PREPARING_WHILE_PROCESS_PHASE_1 06-27 21:48:44.944 25634 25634 D jd_foo : WHILE_PHASE_1_PASSED 06-27 21:48:44.962 25634 25634 D jd_foo : JD_SERVER_OK 06-27 21:48:44.980 25634 25634 D jd_foo : QUEUE_TABLE_OK 06-27 21:48:46.221 25634 25634 D jd_foo : GOT_TKTS_OK 06-27 21:48:47.869 25634 25634 D jd_foo : STARTING_CLEAN_UP 06-27 21:48:47.931 25634 25634 D jd_foo : CLEAN_UP_OK 06-27 22:03:37.396 25634 25634 D jd_foo : STARTED 06-27 22:03:37.398 25634 25634 D jd_foo : BROWSER == NULL 06-27 22:03:37.565 25634 25634 D jd_foo : BROWSER_INIT_SUCCESS 06-27 22:03:37.581 25634 25634 D jd_foo : NET_OR_FGSERVICE_OK 06-27 22:03:37.586 25634 25634 D jd_foo : PREPARING_WHILE_PHASE_0 06-27 22:03:39.581 25634 25634 D jd_foo : WHILE_PHASE_O_PASSED 06-27 22:03:39.620 25634 25634 D jd_foo : ON_LOGIN_PAGE = True 06-27 22:03:44.860 25634 25634 D jd_foo : LOGIN_RESPONSE = True 06-27 22:03:44.861 25634 25634 D jd_foo : PREPARING_WHILE_PROCESS_PHASE_1 06-27 22:03:44.861 25634 25634 D jd_foo : WHILE_PHASE_1_PASSED 06-27 22:03:44.879 25634 25634 D jd_foo : JD_SERVER_OK 06-27 22:03:44.893 25634 25634 D jd_foo : QUEUE_TABLE_OK 06-27 22:03:45.754 25634 25634 D jd_foo : GOT_TKTS_OK 06-27 22:03:47.549 25634 25634 D jd_foo : STARTING_CLEAN_UP 06-27 22:03:47.625 25634 25634 D jd_foo : CLEAN_UP_OK 06-27 22:18:37.288 25634 25634 D jd_foo : STARTED 06-27 22:18:37.289 25634 25634 D jd_foo : BROWSER == NULL 06-27 22:18:37.422 25634 25634 D jd_foo : BROWSER_INIT_SUCCESS 06-27 22:18:37.438 25634 25634 D jd_foo : NET_OR_FGSERVICE_OK 06-27 22:18:37.443 25634 25634 D jd_foo : PREPARING_WHILE_PHASE_0 06-27 22:18:39.343 25634 25634 D jd_foo : WHILE_PHASE_O_PASSED 06-27 22:18:39.400 25634 25634 D jd_foo : ON_LOGIN_PAGE = True 06-27 22:18:44.643 25634 25634 D jd_foo : LOGIN_RESPONSE = True 06-27 22:18:44.644 25634 25634 D jd_foo : PREPARING_WHILE_PROCESS_PHASE_1 06-27 22:18:44.644 25634 25634 D jd_foo : WHILE_PHASE_1_PASSED 06-27 22:18:44.651 25634 25634 D jd_foo : JD_SERVER_OK 06-27 22:18:44.658 25634 25634 D jd_foo : QUEUE_TABLE_OK 06-27 22:18:45.483 25634 25634 D jd_foo : GOT_TKTS_OK 06-27 22:18:47.087 25634 25634 D jd_foo : STARTING_CLEAN_UP 06-27 22:18:47.167 25634 25634 D jd_foo : CLEAN_UP_OK
如您所见,第一次发射是在 21:19,然后是 21:33,然后是 21:48。
但是应该每 10 分钟被解雇一次
我真的不明白为什么:/
P.S: 我刚才也注意到,即使我使用 AlarmType.ElapsedRealtimeWakeup)
屏幕也不会唤醒[编辑]
现在我已经测试了更长的时间,看起来第一次触发后的警报每 15 分钟触发一次,这对我的应用程序来说不是大问题,但为什么呢?
为了减少滥用,对特定应用程序发出这些警报的频率有限制。在正常的系统操作下,它发送这些警报的时间不会超过大约每分钟一次(此时将发送每个此类未决警报);在低功耗空闲模式下,此持续时间可能会明显更长,例如 15 分钟。
所以,这很正常,“精确”并不那么精确,它的名称具有误导性。