2010-03-10 54 views
27

我將創建需要每分鐘更新其內容的小部件(它顯示與時間相關的數據)。Android - 如何更新小部件,但只有當它是可見的?

然而,沒有必要對插件更新如果它當前不可見的,這意味着:

  • 屏幕關閉
  • 另一個應用程序正在運行
  • 插件被放置在另一(不可見)主屏幕選項卡

什麼是每分鐘更新僅顯示小部件的最佳方式 - 無需喚醒設備或執行不必要的計算?小部件變得可見之後,更新之前的小滯後是可接受的。

回答

15

爲了防止在屏幕關閉時進行更新,請使用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

+0

我出演過,至少我能做到,你回答了我的很多問題,並且可能會在將來這樣做。謝謝。 – Pentium10 2010-03-10 14:12:32

+0

已加星標,太糟糕了,它將無法用於當前正在使用的數百萬首... – tomash 2010-03-10 14:18:10

+1

可以確定哪個應用當前正在運行: ActivityManager mAM =(ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE ); List tasks = mAM.getRunningTasks(1); – Niels 2012-06-16 14:42:16

6

我在一個名爲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設備。

+2

肯定會失敗當在非標準的主屏幕上運行時可怕嗎? – Adrian 2011-01-12 12:10:19

+2

請看我更新的答案,我有一個更好的方法,應該在第三方工作。 – xandy 2011-01-12 13:17:02

+0

注意:需要權限GET_TASKS – larham1 2013-11-21 19:16:33

8
  1. 您可以詢問isScreenOn()在電源管理器
  2. 可以爲意向ACTION_SCREEN_OFF/ACTION_SCREEN_ON註冊並把你定時開/關機相應。

雖然以上關於AlarmManager的回答是正確的,但它可能並不足夠,因爲我觀察到許多手機即使不是* _WAKEUP類型也會發出警報。如果安裝了其他正在喚醒設備的應用程序,則可能會發生這種情況。如果它一旦醒來,它會提供所有待處理的警報。

+0

這是非常重要的一點。即使屏幕處於睡眠狀態,警報也可能會觸發,如[本主題](https://groups.google.com/forum/?fromgroups=#!topic/android-developers/Airlo3g5luw)中所述。 – lseidman 2013-02-22 00:22:00

+0

我還注意到,在開發者模式下(並將內容記錄到logcat),設備保持清醒。爲了測試在沒有開發模式的情況下它會做什麼,我添加了一個計數器以顯示所有更新,並注意到在開發者模式關閉的情況下,它將進入休眠狀態,並且不會使用AlarmManager.RTC事件更新小部件。我找不到任何文檔來查看開發者模式是否保持清醒,但它確實對我有意義。 – 2014-10-27 12:03:46

0

從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 filterAndroid - 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來處理相對昂貴的工作,其中包括一個持久的網絡連接。這對於近實時地監視遠程服務的狀態是必需的。
相關問題