2011-05-30 51 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