我將創建需要每分鐘更新其內容的小部件(它顯示與時間相關的數據)。Android - 如何更新小部件,但只有當它是可見的?
然而,沒有必要對插件更新如果它當前不可見的,這意味着:
- 屏幕關閉
- 另一個應用程序正在運行
- 插件被放置在另一(不可見)主屏幕選項卡
什麼是每分鐘更新僅顯示小部件的最佳方式 - 無需喚醒設備或執行不必要的計算?小部件變得可見之後,更新之前的小滯後是可接受的。
我將創建需要每分鐘更新其內容的小部件(它顯示與時間相關的數據)。Android - 如何更新小部件,但只有當它是可見的?
然而,沒有必要對插件更新如果它當前不可見的,這意味着:
什麼是每分鐘更新僅顯示小部件的最佳方式 - 無需喚醒設備或執行不必要的計算?小部件變得可見之後,更新之前的小滯後是可接受的。
爲了防止在屏幕關閉時進行更新,請使用AlarmManager來安排不喚醒手機的週期性警報。
你在你的問題中的其他兩個要點是不可能的。無法檢測您的小部件是否在當前不可見的主屏幕上,並且無法確定某個應用程序是否正在運行而隱藏主屏幕。我已經在http://b.android.com上提交了一張要求將此功能添加到Android的門票。如果你覺得主演它,它會幫助它獲得優先權:http://code.google.com/p/android/issues/detail?id=5529&q=reporter:mark.r.baird&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars
我在一個名爲24clock in goole code的項目下找到了它。它試圖在用戶不在家時更新小部件:
ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> runningTasks = am.getRunningTasks(2);
for (RunningTaskInfo t : runningTasks) {
if (t != null && t.numRunning > 0) {
ComponentName cn = t.baseActivity;
if (cn == null) continue;
String clz = cn.getClassName();
String pkg = cn.getPackageName();
// TODO make this configurable
if (pkg != null && pkg.startsWith("com.android.launcher")) {
return true;
}
return false;
}
}
它可能是您的需求#2的答案。雖然它可能不適用於其他第三方發射器。
== ==更新
幾個月後,我突然在我的腦海有關如何檢測主屏幕是否顯示的想法。我把它放在我的blog中,然後我對我的慾望進行了測試,效果很好。該方法是向Android查詢所有安裝的軟件包,其中哪一個包含「啓動器」功能,然後檢查它是否位於正在運行的堆棧的頂部。如果有人測試過,請讓我知道結果,因爲我無法訪問其他Android設備。
雖然以上關於AlarmManager的回答是正確的,但它可能並不足夠,因爲我觀察到許多手機即使不是* _WAKEUP類型也會發出警報。如果安裝了其他正在喚醒設備的應用程序,則可能會發生這種情況。如果它一旦醒來,它會提供所有待處理的警報。
這是非常重要的一點。即使屏幕處於睡眠狀態,警報也可能會觸發,如[本主題](https://groups.google.com/forum/?fromgroups=#!topic/android-developers/Airlo3g5luw)中所述。 – lseidman 2013-02-22 00:22:00
我還注意到,在開發者模式下(並將內容記錄到logcat),設備保持清醒。爲了測試在沒有開發模式的情況下它會做什麼,我添加了一個計數器以顯示所有更新,並注意到在開發者模式關閉的情況下,它將進入休眠狀態,並且不會使用AlarmManager.RTC事件更新小部件。我找不到任何文檔來查看開發者模式是否保持清醒,但它確實對我有意義。 – 2014-10-27 12:03:46
從mbaird接受的答案擊中頭部的指甲。建議的onVisivilityChange()
方法(如果實施)應涵蓋上述所有情況。
同時,對於某些類型的小部件,這仍然是一個真正的問題。 jom介紹了註冊接收ACTION_SCREEN_OFF/ACTION_SCREEN_ON意圖的可能性。這很有用,因爲依賴於非喚醒循環警報是不夠的,因爲其他服務引起喚醒。這很困難,因爲這些操作無法通過AndroidManifest.xml進行訂閱,並且AppWidgetProvider不允許調用context.registerReceiver()
。這些問題在幾個其他StackOverflow問題中進行了討論,包括Listening for ACTION_SCREEN_OFF,android.intent.action.SCREEN_ON doesn't work as a receiver intent filter和Android - how to receive broadcast intents ACTION_SCREEN_ON/OFF?。
我已成功通過創建子公司不幸的是,當然,如果應用程序被殺,這將會失敗。BroascastReceiver
實例並使用context.getApplicationContext().registerReceiver()
進行註冊來訂閱窗口小部件中的ACTION_SCREEN_OFF/ACTION_SCREEN_ON意圖。這很可能是作弊行爲,至少在後來的某些Android版本中,可能會在註冊階段失敗,或者事件可能無法傳遞。我編碼處理這些案件,但現在它的工作。
另一種可能性是使用isHomeScreenShowing()
種類的方法,如xandy的回答所引用的here所述。通過緩存生成的已安裝應用程序列表並監聽ACTION_PACKAGE_ADDED/CHANGED/REMOVED廣播來更新它,可能會優化這些想法。
我的策略是:
IntentService
來處理相對昂貴的工作,其中包括一個持久的網絡連接。這對於近實時地監視遠程服務的狀態是必需的。
我出演過,至少我能做到,你回答了我的很多問題,並且可能會在將來這樣做。謝謝。 – Pentium10 2010-03-10 14:12:32
已加星標,太糟糕了,它將無法用於當前正在使用的數百萬首... – tomash 2010-03-10 14:18:10
可以確定哪個應用當前正在運行: ActivityManager mAM =(ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE ); List tasks = mAM.getRunningTasks(1); –
Niels
2012-06-16 14:42:16