summaryrefslogtreecommitdiffstats
path: root/src/com/android/settings/wifi/WifiSetupActivity.java
blob: 38fc32d3dd15f8c3f8ea0416f1de8568b53ac173 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.settings.wifi;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.preference.PreferenceFragment;
import android.util.Log;

import com.android.settings.ButtonBarHandler;
import com.android.settings.R;
import com.android.settings.SetupWizardUtils;
import com.android.setupwizardlib.view.NavigationBar;

public class WifiSetupActivity extends WifiPickerActivity
        implements ButtonBarHandler, NavigationBar.NavigationBarListener {
    private static final String TAG = "WifiSetupActivity";

    // this boolean extra specifies whether to auto finish when connection is established
    private static final String EXTRA_AUTO_FINISH_ON_CONNECT = "wifi_auto_finish_on_connect";

    // This boolean extra specifies whether network is required
    private static final String EXTRA_IS_NETWORK_REQUIRED = "is_network_required";

    // This boolean extra specifies whether wifi is required
    private static final String EXTRA_IS_WIFI_REQUIRED = "is_wifi_required";

    // Whether auto finish is suspended until user connects to an access point
    private static final String EXTRA_REQUIRE_USER_NETWORK_SELECTION =
            "wifi_require_user_network_selection";

    // Key for whether the user selected network in saved instance state bundle
    private static final String PARAM_USER_SELECTED_NETWORK = "userSelectedNetwork";

    // Activity result when pressing the Skip button
    private static final int RESULT_SKIP = Activity.RESULT_FIRST_USER;

    // Whether to auto finish when the user selected a network and successfully connected
    private boolean mAutoFinishOnConnection;
    // Whether network is required to proceed. This is decided in SUW and passed in as an extra.
    private boolean mIsNetworkRequired;
    // Whether wifi is required to proceed. This is decided in SUW and passed in as an extra.
    private boolean mIsWifiRequired;
    // Whether the user connected to a network. This excludes the auto-connecting by the system.
    private boolean mUserSelectedNetwork;
    // Whether the device is connected to WiFi
    private boolean mWifiConnected;

    private NavigationBar mNavigationBar;

    private IntentFilter mFilter = new IntentFilter();
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // Refresh the connection state with the latest connection info. Use the connection info
            // from ConnectivityManager instead of the one attached in the intent to make sure
            // we have the most up-to-date connection state. b/17511772
            refreshConnectionState();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        final Intent intent = getIntent();
        mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
        mFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);

        mAutoFinishOnConnection = intent.getBooleanExtra(EXTRA_AUTO_FINISH_ON_CONNECT, false);
        mIsNetworkRequired = intent.getBooleanExtra(EXTRA_IS_NETWORK_REQUIRED, false);
        mIsWifiRequired = intent.getBooleanExtra(EXTRA_IS_WIFI_REQUIRED, false);
        // Behave like the user already selected a network if we do not require selection
        mUserSelectedNetwork = !intent.getBooleanExtra(EXTRA_REQUIRE_USER_NETWORK_SELECTION, false);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean(PARAM_USER_SELECTED_NETWORK, mUserSelectedNetwork);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        mUserSelectedNetwork = savedInstanceState.getBoolean(PARAM_USER_SELECTED_NETWORK, true);
    }

    private boolean isWifiConnected() {
        final ConnectivityManager connectivity = (ConnectivityManager)
                getSystemService(Context.CONNECTIVITY_SERVICE);
        boolean wifiConnected = connectivity != null &&
                connectivity.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected();
        mWifiConnected = wifiConnected;
        return wifiConnected;
    }

    private void refreshConnectionState() {
        if (isWifiConnected()) {
            if (mAutoFinishOnConnection && mUserSelectedNetwork) {
                Log.d(TAG, "Auto-finishing with connection");
                finish(Activity.RESULT_OK);
                // Require a user selection before auto-finishing next time we are here. The user
                // can either connect to a different network or press "next" to proceed.
                mUserSelectedNetwork = false;
            }
            setNextButtonText(R.string.setup_wizard_next_button_label);
            setNextButtonEnabled(true);
        } else if (mIsWifiRequired || (mIsNetworkRequired && !isNetworkConnected())) {
            // We do not want the user to skip wifi setting if
            // - wifi is required, but wifi connection hasn't been established yet;
            // - or network is required, but no valid connection has been established.
            setNextButtonText(R.string.skip_label);
            setNextButtonEnabled(false);
        } else {
            // In other cases, user can choose to skip. Specifically these cases are
            // - wifi is not required;
            // - and network is not required;
            // -     or network is required and a valid connection has been established.
            setNextButtonText(R.string.skip_label);
            setNextButtonEnabled(true);
        }
    }

    private void setNextButtonEnabled(boolean enabled) {
        if (mNavigationBar != null) {
            mNavigationBar.getNextButton().setEnabled(enabled);
        }
    }

    private void setNextButtonText(int resId) {
        if (mNavigationBar != null) {
            mNavigationBar.getNextButton().setText(resId);
        }
    }

    /* package */ void networkSelected() {
        Log.d(TAG, "Network selected by user");
        mUserSelectedNetwork = true;
    }

    @Override
    public void onResume() {
        super.onResume();
        registerReceiver(mReceiver, mFilter);
        refreshConnectionState();
    }

    @Override
    public void onPause() {
        unregisterReceiver(mReceiver);
        super.onPause();
    }

    @Override
    protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
        resid = SetupWizardUtils.getTheme(getIntent());
        super.onApplyThemeResource(theme, resid, first);
    }

    @Override
    protected boolean isValidFragment(String fragmentName) {
        return WifiSettingsForSetupWizard.class.getName().equals(fragmentName);
    }

    @Override
    /* package */ Class<? extends PreferenceFragment> getWifiSettingsClass() {
        return WifiSettingsForSetupWizard.class;
    }

    /**
     * Complete this activity and return the results to the caller.
     */
    public void finish(int resultCode) {
        Log.d(TAG, "finishing, resultCode=" + resultCode);
        setResult(resultCode);
        finish();
    }

    public void onNavigationBarCreated(final NavigationBar bar) {
        mNavigationBar = bar;
        bar.setNavigationBarListener(this);
        SetupWizardUtils.setImmersiveMode(this);
    }

    @Override
    public void onNavigateBack() {
        onBackPressed();
    }

    @Override
    public void onNavigateNext() {
        if (mWifiConnected) {
            finish(RESULT_OK);
        } else {
            // Warn of possible data charges if there is a network connection, or lack of updates
            // if there is none.
            final int message = isNetworkConnected() ? R.string.wifi_skipped_message :
                    R.string.wifi_and_mobile_skipped_message;
            WifiSkipDialog.newInstance(message).show(getFragmentManager(), "dialog");
        }
    }

    /**
     * @return True if there is a valid network connection, whether it is via WiFi, mobile data or
     *         other means.
     */
    private boolean isNetworkConnected() {
        final ConnectivityManager connectivity = (ConnectivityManager)
                getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivity == null) {
            return false;
        }
        final NetworkInfo info = connectivity.getActiveNetworkInfo();
        return info != null && info.isConnected();
    }

    public static class WifiSkipDialog extends DialogFragment {
        public static WifiSkipDialog newInstance(int messageRes) {
            final Bundle args = new Bundle();
            args.putInt("messageRes", messageRes);
            final WifiSkipDialog dialog = new WifiSkipDialog();
            dialog.setArguments(args);
            return dialog;
        }

        public WifiSkipDialog() {
            // no-arg constructor for fragment
        }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            int messageRes = getArguments().getInt("messageRes");
            final AlertDialog dialog = new AlertDialog.Builder(getActivity())
                    .setMessage(messageRes)
                    .setCancelable(false)
                    .setPositiveButton(R.string.wifi_skip_anyway,
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int id) {
                                    WifiSetupActivity activity = (WifiSetupActivity) getActivity();
                                    activity.finish(RESULT_SKIP);
                                }
                            })
                    .setNegativeButton(R.string.wifi_dont_skip,
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int id) {
                                }
                            })
                    .create();
            SetupWizardUtils.applyImmersiveFlags(dialog);
            return dialog;
        }
    }
}