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