2011-05-30 50 views
0

我的目標是在主屏幕上顯示「飛行模式」小部件,以便用戶可以打開/關閉飛行模式;該小部件顯示飛行模式的當前狀態(打開,關閉或轉換)。爲了做到這一點,我註冊,聽取他們對我的appwidget提供商「的onUpdate」回調手機狀態變化:在appWidget中監聽手機狀態變化

mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE); 

,我通過重寫「mPhoneStateListener.onServiceStateChanged」回調更新小部件UI。

@Override 
    public void onServiceStateChanged(ServiceState serviceState) { 
     super.onServiceStateChanged(serviceState); 

     switch (serviceState.getState()) { 
     case ServiceState.STATE_POWER_OFF: 
      currentAirplaneModeState = AIRPLANE_MODE_ON; 
      Log.d(APP_ID, "serviceState: "+serviceState.getState()+": STATE_POWER_OFF"); 
      break; 
     case ServiceState.STATE_IN_SERVICE: 
      currentAirplaneModeState = AIRPLANE_MODE_OFF; 
      Log.d(APP_ID, "serviceState: "+serviceState.getState()+": STATE_IN_SERVICE"); 
      break; 
     case ServiceState.STATE_OUT_OF_SERVICE: 
      currentAirplaneModeState = AIRPLANE_MODE_IN_UNDETERMINED; 
      Log.d(APP_ID, "serviceState: "+serviceState.getState()+": STATE_OUT_OF_SERVICE"); 
      break; 
     case ServiceState.STATE_EMERGENCY_ONLY: 
      currentAirplaneModeState = AIRPLANE_MODE_ON; 
      Log.d(APP_ID, "serviceState: "+serviceState.getState()+": STATE_EMERGENCY_ONLY"); 
      break; 
     default: 
      Log.d(APP_ID, "serviceState: default: "+serviceState.getState()); 
      break; 
     } 
     updateWidget(mContext); 
    } 

該方法確實更新小部件,但並非全部。它需要幾個狀態轉換才能切換飛行模式,但我的小部件常常停留在「轉換」模式,因爲一旦上述代碼返回,Android似乎認爲監聽器的工作已完成並將終止偵聽器。在整個轉換週期完成之前,保持電話聽衆的最佳方法是什麼?或者有更好的方法嗎?

回答

1

我註冊聽我appwidget提供商

,將永遠是可靠的「的onUpdate」回撥電話的狀態變化,並在發生故障之前將導致內存泄漏。與任何清單註冊的BroadcastReceiver一樣,AppWidgetProvider應該生存幾個毫秒,足夠長的時間來處理onReceive()。之後的某個時候,Android會終止你的進程,如果沒有其他任何東西保持這個過程,並且Android需要內存。

還是有更好的方法嗎?

使用ACTION_PHONE_STATE_CHANGED廣播。或者,使用AlarmManager在短時間內檢查狀態。

+0

請您詳細說明我如何設置它?我創建了一個測試項目,其中只有一個接收器: <使用權限android:name =「android.permission.READ_PHONE_STATE」>但是當我從手機改變飛行模式時,接收者的onReceive處理程序似乎不會被調用設置。我錯過了什麼? – mobileTofu 2011-05-30 19:30:48

+0

@mobileTofu:有可能'ACTION_PHONE_STATE_CHANGED'只廣播振鈴/摘機事件。嘗試從DDMS接收模擬器中的電話,然後查看是否調用了您的接收器。如果是這樣,那麼'ACTION_PHONE_STATE_CHANGED'將不適用於你的場景,在這種情況下'AlarmManager'輪詢是下一個選項。 – CommonsWare 2011-05-30 19:48:07

+0

撥打電話確實會觸發接收器(意圖操作「android.intent.action.PHONE_STATE」)。 – mobileTofu 2011-05-30 22:00:46