1823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang/*
2823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * Copyright (C) 2006 The Android Open Source Project
3823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang *
4823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * Licensed under the Apache License, Version 2.0 (the "License");
5823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * you may not use this file except in compliance with the License.
6823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * You may obtain a copy of the License at
7823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang *
8823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang *      http://www.apache.org/licenses/LICENSE-2.0
9823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang *
10823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * Unless required by applicable law or agreed to in writing, software
11823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * distributed under the License is distributed on an "AS IS" BASIS,
12823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * See the License for the specific language governing permissions and
14823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * limitations under the License.
15823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang */
16823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
17823b6f3516076b92f78c3fc27037d24bb514e653Ying Wangpackage com.android.common;
18823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
19823b6f3516076b92f78c3fc27037d24bb514e653Ying Wangimport android.content.BroadcastReceiver;
20823b6f3516076b92f78c3fc27037d24bb514e653Ying Wangimport android.content.Context;
21823b6f3516076b92f78c3fc27037d24bb514e653Ying Wangimport android.content.Intent;
22823b6f3516076b92f78c3fc27037d24bb514e653Ying Wangimport android.content.IntentFilter;
23823b6f3516076b92f78c3fc27037d24bb514e653Ying Wangimport android.net.ConnectivityManager;
24823b6f3516076b92f78c3fc27037d24bb514e653Ying Wangimport android.net.NetworkInfo;
25823b6f3516076b92f78c3fc27037d24bb514e653Ying Wangimport android.os.Handler;
26823b6f3516076b92f78c3fc27037d24bb514e653Ying Wangimport android.os.Message;
27823b6f3516076b92f78c3fc27037d24bb514e653Ying Wangimport android.util.Log;
28823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
29823b6f3516076b92f78c3fc27037d24bb514e653Ying Wangimport java.util.HashMap;
30823b6f3516076b92f78c3fc27037d24bb514e653Ying Wangimport java.util.Iterator;
31823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
32823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang/**
33823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * A wrapper for a broadcast receiver that provides network connectivity
34823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * state information, independent of network type (mobile, Wi-Fi, etc.).
35823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * @deprecated Code tempted to use this class should simply listen for connectivity intents
36823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * (or poll ConnectivityManager) directly.
37823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * {@hide}
38823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang */
39194dda102240aeeaa30c28f4eda3e1d3ccdb6b03Scott Kennedy@Deprecated
40823b6f3516076b92f78c3fc27037d24bb514e653Ying Wangpublic class NetworkConnectivityListener {
41823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    private static final String TAG = "NetworkConnectivityListener";
42823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    private static final boolean DBG = false;
43823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
44823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    private Context mContext;
45823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    private HashMap<Handler, Integer> mHandlers = new HashMap<Handler, Integer>();
46823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    private State mState;
47823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    private boolean mListening;
48823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    private String mReason;
49823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    private boolean mIsFailover;
50823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
51823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    /** Network connectivity information */
52823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    private NetworkInfo mNetworkInfo;
53823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
54823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    /**
55823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * In case of a Disconnect, the connectivity manager may have
56823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * already established, or may be attempting to establish, connectivity
57823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * with another network. If so, {@code mOtherNetworkInfo} will be non-null.
58823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     */
59823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    private NetworkInfo mOtherNetworkInfo;
60823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
61823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    private ConnectivityBroadcastReceiver mReceiver;
62823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
63823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    private class ConnectivityBroadcastReceiver extends BroadcastReceiver {
64823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang        @Override
65823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang        public void onReceive(Context context, Intent intent) {
66823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            String action = intent.getAction();
67823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
68823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
69823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang                mListening == false) {
70823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang                Log.w(TAG, "onReceived() called with " + mState.toString() + " and " + intent);
71823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang                return;
72823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            }
73823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
74823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            boolean noConnectivity =
75823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang                intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
76823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
77823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            if (noConnectivity) {
78823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang                mState = State.NOT_CONNECTED;
79823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            } else {
80823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang                mState = State.CONNECTED;
81823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            }
82823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
83823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            mNetworkInfo = (NetworkInfo)
84823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang                intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
85823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            mOtherNetworkInfo = (NetworkInfo)
86823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang                intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
87823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
88823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            mReason = intent.getStringExtra(ConnectivityManager.EXTRA_REASON);
89823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            mIsFailover =
90823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang                intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false);
91823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
92823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            if (DBG) {
93823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang                Log.d(TAG, "onReceive(): mNetworkInfo=" + mNetworkInfo +  " mOtherNetworkInfo = "
94823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang                        + (mOtherNetworkInfo == null ? "[none]" : mOtherNetworkInfo +
95823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang                        " noConn=" + noConnectivity) + " mState=" + mState.toString());
96823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            }
97823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
98823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            // Notifiy any handlers.
99823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            Iterator<Handler> it = mHandlers.keySet().iterator();
100823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            while (it.hasNext()) {
101823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang                Handler target = it.next();
102823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang                Message message = Message.obtain(target, mHandlers.get(target));
103823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang                target.sendMessage(message);
104823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            }
105823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang        }
106194dda102240aeeaa30c28f4eda3e1d3ccdb6b03Scott Kennedy    }
107823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
108823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    public enum State {
109823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang        UNKNOWN,
110823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
111823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang        /** This state is returned if there is connectivity to any network **/
112823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang        CONNECTED,
113823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang        /**
114823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang         * This state is returned if there is no connectivity to any network. This is set
115823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang         * to true under two circumstances:
116823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang         * <ul>
117823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang         * <li>When connectivity is lost to one network, and there is no other available
118823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang         * network to attempt to switch to.</li>
119823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang         * <li>When connectivity is lost to one network, and the attempt to switch to
120823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang         * another network fails.</li>
121823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang         */
122823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang        NOT_CONNECTED
123823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    }
124823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
125823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    /**
126823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * Create a new NetworkConnectivityListener.
127823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     */
128823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    public NetworkConnectivityListener() {
129823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang        mState = State.UNKNOWN;
130823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang        mReceiver = new ConnectivityBroadcastReceiver();
131823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    }
132823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
133823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    /**
134823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * This method starts listening for network connectivity state changes.
135823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * @param context
136823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     */
137823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    public synchronized void startListening(Context context) {
138823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang        if (!mListening) {
139823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            mContext = context;
140823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
141823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            IntentFilter filter = new IntentFilter();
142823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
143823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            context.registerReceiver(mReceiver, filter);
144823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            mListening = true;
145823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang        }
146823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    }
147823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
148823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    /**
149823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * This method stops this class from listening for network changes.
150823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     */
151823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    public synchronized void stopListening() {
152823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang        if (mListening) {
153823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            mContext.unregisterReceiver(mReceiver);
154823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            mContext = null;
155823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            mNetworkInfo = null;
156823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            mOtherNetworkInfo = null;
157823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            mIsFailover = false;
158823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            mReason = null;
159823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang            mListening = false;
160823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang        }
161823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    }
162823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
163823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    /**
164823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * This methods registers a Handler to be called back onto with the specified what code when
165823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * the network connectivity state changes.
166823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     *
167823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * @param target The target handler.
168823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * @param what The what code to be used when posting a message to the handler.
169823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     */
170823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    public void registerHandler(Handler target, int what) {
171823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang        mHandlers.put(target, what);
172823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    }
173823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
174823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    /**
175823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * This methods unregisters the specified Handler.
176823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * @param target
177823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     */
178823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    public void unregisterHandler(Handler target) {
179823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang        mHandlers.remove(target);
180823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    }
181823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
182823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    public State getState() {
183823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang        return mState;
184823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    }
185823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
186823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    /**
187823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * Return the NetworkInfo associated with the most recent connectivity event.
188823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * @return {@code NetworkInfo} for the network that had the most recent connectivity event.
189823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     */
190823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    public NetworkInfo getNetworkInfo() {
191823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang        return mNetworkInfo;
192823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    }
193823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
194823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    /**
195823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * If the most recent connectivity event was a DISCONNECT, return
196823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * any information supplied in the broadcast about an alternate
197823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * network that might be available. If this returns a non-null
198823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * value, then another broadcast should follow shortly indicating
199823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * whether connection to the other network succeeded.
200823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     *
201823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * @return NetworkInfo
202823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     */
203823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    public NetworkInfo getOtherNetworkInfo() {
204823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang        return mOtherNetworkInfo;
205823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    }
206823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
207823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    /**
208823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * Returns true if the most recent event was for an attempt to switch over to
209823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * a new network following loss of connectivity on another network.
210823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * @return {@code true} if this was a failover attempt, {@code false} otherwise.
211823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     */
212823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    public boolean isFailover() {
213823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang        return mIsFailover;
214823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    }
215823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang
216823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    /**
217823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * An optional reason for the connectivity state change may have been supplied.
218823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * This returns it.
219823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * @return the reason for the state change, if available, or {@code null}
220823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     * otherwise.
221823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang     */
222823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    public String getReason() {
223823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang        return mReason;
224823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang    }
225823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang}
226