10

BroadcastReceiver を使用して、電話が WiFi アクセス ポイントから切断されたことを検出しようとしています。これを行うために、BroadcastReceiver をマニフェストに登録しました。

<receiver android:name="com.eshayne.android.WiFiBroadcastReceiver">
    <intent-filter>
        <action android:name="android.net.wifi.STATE_CHANGE" />
    </intent-filter>
</receiver>

私の WiFiBroadcastReceiver クラスでは、NETWORK_STATE_CHANGED_ACTION アクションをチェックし、NetworkInfo の詳細な状態を調べています。

if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
    NetworkInfo info = (NetworkInfo)intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
    android.util.Log.d("com.eshayne.android.WiFiBroadcastReceiver", "network state change - detailedState=" + info.getDetailedState() + ": " + info.toString());
    if (info.getDetailedState() == DetailedState.DISCONNECTED) {
        ...
    }
    else if (info.getDetailedState() == DetailedState.CONNECTED) {
        ...
    }

私が見ている問題は、電話がWiFiアクセスポイントの範囲を離れると、「切断された」コールバックが停止する前に6回(かなり定期的に15秒ごとに約1回)呼び出されることです。これまでのところ、各コールバックの NetworkInfo の間で際立った特徴を見つけることができませんでした。ログに書き込まれる各 NetworkInfo オブジェクトは次のようになります。

02-18 10:16:51.918 D/com.eshayne.android.WiFiBroadcastReceiver( 1511): network state change - detailedState=DISCONNECTED: NetworkInfo: type: WIFI[], state: DISCONNECTED/DISCONNECTED, reason: (unspecified), extra: (none), roaming: false, failover: false, isAvailable: true

また、「接続された」コールバックは「切断された」コールバックの間に呼び出されないため、電話が WiFi の範囲内外をさまよっているという問題でもありません。また、その間に他の状態がトリガーされることもありません。それぞれが DISCONNECTED の detailedState を持つ 6 つのコールバックの急速なシリーズです。

電話が WiFi 接続を失ったことを検出して、コールバックが切断ごとに 1 回だけ呼び出されるようにするためのより良い方法はありますか? または、私が見ている6つのコールバックのどれが「最終」のものであるかを検出する方法はありますか?

4

2 に答える 2

2

あなたはそれが「6つの切断されたコールバックの迅速なシリーズ」だと言いますが、if/else-ifはDISCONNECTEDとCONNECTEDのみをチェックし、他のすべてのケースを処理するためのデフォルトブロックのようには見えません. NetworkInfo.DetailedState API ページから、「接続中」、「スキャン中」、「切断中」など、NetworkInfo.getDetailedState() によって返される可能性のある 10 の状態があります。これらはすべて、切断されたばかりの電話のもっともらしい動作です。ネットワークから。

「接続済み」と「切断済み」だけでなく、wifi 状態の変化警告するデフォルトのケースをスローします。電話がいくつかの異なる状態の間で回転していることに気付くかもしれません。同じ状態を 6 回撃っただけではありません。そこから、コードの進め方が少し明確になることを願っています。

于 2011-02-18T21:08:41.630 に答える
0

使用できる回避策の1つは、最後のコールバックアクション(グローバル状態、共有設定など)を維持し、アクションが変更された場合にのみコールバックを実行することです。

enum NetworkCallbackAction { None, Disconnected, Connected };
NetworkCallbackAction lastHandledAction = NetworkCallbackAction.None;

// ...

if (info.getDetailedState() == DetailedState.DISCONNECTED) {
  if (lastHandledAction != NetworkCallbackAction.Disconnected) {
    lastHandledAction = NetworkCallbackAction.Disconnected;
    // ...
  }
}
else if (info.getDetailedState() == DetailedState.CONNECTED) {
  if (lastHandledAction != NetworkCallbackAction.Connected) {
    lastHandledAction = NetworkCallbackAction.Connected;
    // ...
  }
}

このロジックのより良い抽象化は、ネットワーク状態の変化を一貫したイベントに正規化し、現実世界の癖を滑らかにしてから、独自のアクションを再ブロードキャストすることだけが仕事であるブロードキャストレシーバーを作成することです。これにより、生の更新をアプリケーションにとって意味のあるものに単純化できます。たとえば、最後のブロードキャストであり、変更のみをブロードキャストすることを覚えておくことができます(上記のコードと同様)。ネットワーク変更インテントのバーストの場合、受信した最後の状態をブロードキャストする前に数秒待つことができます。

于 2012-02-20T21:56:32.077 に答える