1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.settings.wifi; 17 18 import android.app.Activity; 19 import android.app.AlertDialog; 20 import android.app.Dialog; 21 import android.app.DialogFragment; 22 import android.content.BroadcastReceiver; 23 import android.content.Context; 24 import android.content.DialogInterface; 25 import android.content.Intent; 26 import android.content.IntentFilter; 27 import android.content.res.Resources; 28 import android.net.ConnectivityManager; 29 import android.net.NetworkInfo; 30 import android.net.wifi.WifiManager; 31 import android.os.Bundle; 32 import android.preference.PreferenceFragment; 33 import android.util.Log; 34 35 import com.android.settings.ButtonBarHandler; 36 import com.android.settings.R; 37 import com.android.settings.SetupWizardUtils; 38 import com.android.setupwizard.navigationbar.SetupWizardNavBar; 39 import com.android.setupwizard.navigationbar.SetupWizardNavBar.NavigationBarListener; 40 41 public class WifiSetupActivity extends WifiPickerActivity 42 implements ButtonBarHandler, NavigationBarListener { 43 private static final String TAG = "WifiSetupActivity"; 44 45 // this boolean extra specifies whether to auto finish when connection is established 46 private static final String EXTRA_AUTO_FINISH_ON_CONNECT = "wifi_auto_finish_on_connect"; 47 48 // This boolean extra specifies whether network is required 49 private static final String EXTRA_IS_NETWORK_REQUIRED = "is_network_required"; 50 51 // This boolean extra specifies whether wifi is required 52 private static final String EXTRA_IS_WIFI_REQUIRED = "is_wifi_required"; 53 54 // Whether auto finish is suspended until user connects to an access point 55 private static final String EXTRA_REQUIRE_USER_NETWORK_SELECTION = 56 "wifi_require_user_network_selection"; 57 58 // Key for whether the user selected network in saved instance state bundle 59 private static final String PARAM_USER_SELECTED_NETWORK = "userSelectedNetwork"; 60 61 // Activity result when pressing the Skip button 62 private static final int RESULT_SKIP = Activity.RESULT_FIRST_USER; 63 64 // Whether to auto finish when the user selected a network and successfully connected 65 private boolean mAutoFinishOnConnection; 66 // Whether network is required to proceed. This is decided in SUW and passed in as an extra. 67 private boolean mIsNetworkRequired; 68 // Whether wifi is required to proceed. This is decided in SUW and passed in as an extra. 69 private boolean mIsWifiRequired; 70 // Whether the user connected to a network. This excludes the auto-connecting by the system. 71 private boolean mUserSelectedNetwork; 72 // Whether the device is connected to WiFi 73 private boolean mWifiConnected; 74 75 private SetupWizardNavBar mNavigationBar; 76 77 private IntentFilter mFilter = new IntentFilter(); 78 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 79 @Override 80 public void onReceive(Context context, Intent intent) { 81 // Refresh the connection state with the latest connection info. Use the connection info 82 // from ConnectivityManager instead of the one attached in the intent to make sure 83 // we have the most up-to-date connection state. b/17511772 84 refreshConnectionState(); 85 } 86 }; 87 88 @Override onCreate(Bundle savedInstanceState)89 protected void onCreate(Bundle savedInstanceState) { 90 super.onCreate(savedInstanceState); 91 92 final Intent intent = getIntent(); 93 mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 94 mFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 95 96 mAutoFinishOnConnection = intent.getBooleanExtra(EXTRA_AUTO_FINISH_ON_CONNECT, false); 97 mIsNetworkRequired = intent.getBooleanExtra(EXTRA_IS_NETWORK_REQUIRED, false); 98 mIsWifiRequired = intent.getBooleanExtra(EXTRA_IS_WIFI_REQUIRED, false); 99 // Behave like the user already selected a network if we do not require selection 100 mUserSelectedNetwork = !intent.getBooleanExtra(EXTRA_REQUIRE_USER_NETWORK_SELECTION, false); 101 } 102 103 @Override onSaveInstanceState(Bundle outState)104 protected void onSaveInstanceState(Bundle outState) { 105 super.onSaveInstanceState(outState); 106 outState.putBoolean(PARAM_USER_SELECTED_NETWORK, mUserSelectedNetwork); 107 } 108 109 @Override onRestoreInstanceState(Bundle savedInstanceState)110 protected void onRestoreInstanceState(Bundle savedInstanceState) { 111 super.onRestoreInstanceState(savedInstanceState); 112 mUserSelectedNetwork = savedInstanceState.getBoolean(PARAM_USER_SELECTED_NETWORK, true); 113 } 114 isWifiConnected()115 private boolean isWifiConnected() { 116 final ConnectivityManager connectivity = (ConnectivityManager) 117 getSystemService(Context.CONNECTIVITY_SERVICE); 118 boolean wifiConnected = connectivity != null && 119 connectivity.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected(); 120 mWifiConnected = wifiConnected; 121 return wifiConnected; 122 } 123 refreshConnectionState()124 private void refreshConnectionState() { 125 if (isWifiConnected()) { 126 if (mAutoFinishOnConnection && mUserSelectedNetwork) { 127 Log.d(TAG, "Auto-finishing with connection"); 128 finishOrNext(Activity.RESULT_OK); 129 // Require a user selection before auto-finishing next time we are here. The user 130 // can either connect to a different network or press "next" to proceed. 131 mUserSelectedNetwork = false; 132 } 133 setNextButtonText(R.string.setup_wizard_next_button_label); 134 setNextButtonEnabled(true); 135 } else if (mIsWifiRequired || (mIsNetworkRequired && !isNetworkConnected())) { 136 // We do not want the user to skip wifi setting if 137 // - wifi is required, but wifi connection hasn't been established yet; 138 // - or network is required, but no valid connection has been established. 139 setNextButtonText(R.string.skip_label); 140 setNextButtonEnabled(false); 141 } else { 142 // In other cases, user can choose to skip. Specifically these cases are 143 // - wifi is not required; 144 // - and network is not required; 145 // - or network is required and a valid connection has been established. 146 setNextButtonText(R.string.skip_label); 147 setNextButtonEnabled(true); 148 } 149 } 150 setNextButtonEnabled(boolean enabled)151 private void setNextButtonEnabled(boolean enabled) { 152 if (mNavigationBar != null) { 153 mNavigationBar.getNextButton().setEnabled(enabled); 154 } 155 } 156 setNextButtonText(int resId)157 private void setNextButtonText(int resId) { 158 if (mNavigationBar != null) { 159 mNavigationBar.getNextButton().setText(resId); 160 } 161 } 162 networkSelected()163 /* package */ void networkSelected() { 164 Log.d(TAG, "Network selected by user"); 165 mUserSelectedNetwork = true; 166 } 167 168 @Override onResume()169 public void onResume() { 170 super.onResume(); 171 registerReceiver(mReceiver, mFilter); 172 refreshConnectionState(); 173 } 174 175 @Override onPause()176 public void onPause() { 177 unregisterReceiver(mReceiver); 178 super.onPause(); 179 } 180 181 @Override onApplyThemeResource(Resources.Theme theme, int resid, boolean first)182 protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) { 183 resid = SetupWizardUtils.getTheme(getIntent(), resid); 184 super.onApplyThemeResource(theme, resid, first); 185 } 186 187 @Override isValidFragment(String fragmentName)188 protected boolean isValidFragment(String fragmentName) { 189 return WifiSettingsForSetupWizard.class.getName().equals(fragmentName); 190 } 191 192 @Override getWifiSettingsClass()193 /* package */ Class<? extends PreferenceFragment> getWifiSettingsClass() { 194 return WifiSettingsForSetupWizard.class; 195 } 196 197 /** 198 * Complete this activity and return the results to the caller. If using WizardManager, this 199 * will invoke the next scripted action; otherwise, we simply finish. 200 */ finishOrNext(int resultCode)201 public void finishOrNext(int resultCode) { 202 Log.d(TAG, "finishOrNext resultCode=" + resultCode 203 + " isUsingWizardManager=" + SetupWizardUtils.isUsingWizardManager(this)); 204 if (SetupWizardUtils.isUsingWizardManager(this)) { 205 SetupWizardUtils.sendResultsToSetupWizard(this, resultCode); 206 } else { 207 setResult(resultCode); 208 finish(); 209 } 210 } 211 212 @Override onNavigationBarCreated(final SetupWizardNavBar bar)213 public void onNavigationBarCreated(final SetupWizardNavBar bar) { 214 mNavigationBar = bar; 215 SetupWizardUtils.setImmersiveMode(this, bar); 216 } 217 218 @Override onNavigateBack()219 public void onNavigateBack() { 220 onBackPressed(); 221 } 222 223 @Override onNavigateNext()224 public void onNavigateNext() { 225 if (mWifiConnected) { 226 finishOrNext(RESULT_OK); 227 } else { 228 // Warn of possible data charges if there is a network connection, or lack of updates 229 // if there is none. 230 final int message = isNetworkConnected() ? R.string.wifi_skipped_message : 231 R.string.wifi_and_mobile_skipped_message; 232 WifiSkipDialog.newInstance(message).show(getFragmentManager(), "dialog"); 233 } 234 } 235 236 /** 237 * @return True if there is a valid network connection, whether it is via WiFi, mobile data or 238 * other means. 239 */ isNetworkConnected()240 private boolean isNetworkConnected() { 241 final ConnectivityManager connectivity = (ConnectivityManager) 242 getSystemService(Context.CONNECTIVITY_SERVICE); 243 if (connectivity == null) { 244 return false; 245 } 246 final NetworkInfo info = connectivity.getActiveNetworkInfo(); 247 return info != null && info.isConnected(); 248 } 249 250 public static class WifiSkipDialog extends DialogFragment { newInstance(int messageRes)251 public static WifiSkipDialog newInstance(int messageRes) { 252 final Bundle args = new Bundle(); 253 args.putInt("messageRes", messageRes); 254 final WifiSkipDialog dialog = new WifiSkipDialog(); 255 dialog.setArguments(args); 256 return dialog; 257 } 258 WifiSkipDialog()259 public WifiSkipDialog() { 260 // no-arg constructor for fragment 261 } 262 263 @Override onCreateDialog(Bundle savedInstanceState)264 public Dialog onCreateDialog(Bundle savedInstanceState) { 265 int messageRes = getArguments().getInt("messageRes"); 266 return new AlertDialog.Builder(getActivity()) 267 .setMessage(messageRes) 268 .setCancelable(false) 269 .setPositiveButton(R.string.wifi_skip_anyway, 270 new DialogInterface.OnClickListener() { 271 @Override 272 public void onClick(DialogInterface dialog, int id) { 273 WifiSetupActivity activity = (WifiSetupActivity) getActivity(); 274 activity.finishOrNext(RESULT_SKIP); 275 } 276 }) 277 .setNegativeButton(R.string.wifi_dont_skip, 278 new DialogInterface.OnClickListener() { 279 @Override 280 public void onClick(DialogInterface dialog, int id) { 281 } 282 }) 283 .create(); 284 } 285 } 286 } 287