I have been struggling with automatically turning on Wi-Fi as soon as the device is within range of an access point without turning on the screen. It has been very frustrati
My scenario is slightly different - I do not hold a wifi lock to begin with (and I am on regular android so I had to translate your method).
Screen off, CPU off, radio dies. Alarm wakes my (wakeful) service up - I hold a (partial) wake lock.
What I want is - if wifi is enabled to connect to the access point it was connected before the radio died - I acquire a wifi lock and I call your function - wakeWifiUp(). When the radio has died (!wifiInfo.IsConnectedOrConnecting is true) I get a network unreachable when I try to connect. I workaround it as in :
public final class NetworkService extends WakefulIntentService {
// this is an intent service - runs on its own thread - otherwise it would
// deadlock as I am using it. Moreover it holds a wakelock and woken up by
// an AlarmManager's Receiver - works reliably
private BroadcastReceiver mConnectionReceiver;
private volatile static CountDownLatch latch;
@Override
protected void doWakefulWork(Intent intent) {
WifiLock _wifiLock = null;
WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE);
boolean failedToConnect = true;
if (wm != null && wm.isWifiEnabled()) {// Don't want to enable it myself
_wifiLock = wm.createWifiLock(
/* WifiManager.WIFI_MODE_FULL_HIGH_PERF */0x3, this.getClass()
.getName() + ".WIFI_LOCK");
_wifiLock.acquire();
failedToConnect = !wakeWifiUp();
}
if (failedToConnect) {
if (_wifiLock != null) _wifiLock.release();
w("No connection !");
return;
}
HttpURLConnection connection = null;
try {
connection = connection();
} catch (IOException e) {/* won't throw - it doesn't do much*/}
OutputStream serverOutputStream = null;
try {
serverOutputStream = connection.getOutputStream(); // now
// this is really where the connection might seriously throw
// .... Work ....
} catch (IOException e) {
w("IOException sending data " + e.getMessage());
// I get here : Network unreachable when radio dies
} finally {
if (_wifiLock != null) _wifiLock.release();
if (connection != null) connection.disconnect();
}
}
private HttpURLConnection connection() throws MalformedURLException,
IOException {
HttpURLConnection connection = (HttpURLConnection) new URL("localhost")
.openConnection();
connection.setDoOutput(true); // triggers POST
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("User-Agent",
"Android Multipart HTTP Client 1.1");
return connection;
}
private boolean wakeWifiUp() {
ConnectivityManager _androidConnectivityMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo wifiInfo = _androidConnectivityMgr
.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
WifiManager _wifiManager = (WifiManager)
getSystemService(Context.WIFI_SERVICE);
final int wifiState = _wifiManager.getWifiState();
if (!_wifiManager.isWifiEnabled()
|| wifiState == WifiManager.WIFI_STATE_DISABLED
|| wifiState == WifiManager.WIFI_STATE_DISABLING) {
// Make sure the Wi-Fi is enabled, required for some devices when
// enable WiFi does not occur immediately
d("!_wifiManager.isWifiEnabled()");
_wifiManager.setWifiEnabled(true);
// do not enable if not enabled ! FIXME
return false;
}
if (!wifiInfo.isConnectedOrConnecting()) {
d("Wifi is NOT Connected Or Connecting - "
+ "wake it up and wait till is up");
// Do not wait for the OS to initiate a reconnect to a Wi-Fi router
_wifiManager.pingSupplicant();
if (wifiState == WifiManager.WIFI_STATE_ENABLED) {
try {
// Brute force methods required for some devices
_wifiManager.setWifiEnabled(false);
_wifiManager.setWifiEnabled(true);
} catch (SecurityException e) {
// Catching exception which should not occur on most
// devices. OS bug details at :
// https://code.google.com/p/android/issues/detail?id=22036
}
}
_wifiManager.disconnect();
_wifiManager.startScan();
_wifiManager.reassociate();
_wifiManager.reconnect();
// THIS IS WHAT I DO TO WAIT FOR A CONNECTION
try {
mConnectionReceiver = new WifiConnectionMonitor();
startMonitoringConnection();
latch = new CountDownLatch(1);
w("I wait");
latch.await();
w("Woke up");
return true; // made it
} catch (InterruptedException e) {
w("Interrupted while waiting for connection", e);
return false;
} finally {
stopMonitoringConnection();
}
}
return true;
}
static void downTheLatch() {
latch.countDown();
}
private synchronized void startMonitoringConnection() {
IntentFilter aFilter = new IntentFilter(
ConnectivityManager.CONNECTIVITY_ACTION);
aFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
registerReceiver(mConnectionReceiver, aFilter);
}
private synchronized void stopMonitoringConnection() {
unregisterReceiver(mConnectionReceiver);
}
private final class WifiConnectionMonitor extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent in) {
String action = in.getAction();
if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
NetworkInfo networkInfo = in
.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
d(networkInfo + "");
if (networkInfo.isConnected()) {
d("Wifi is connected!");
NetworkService.downTheLatch(); // HERE THE SERVICE IS WOKEN!
}
}
}
}
}
Btw not all the tricks in wakeWifiUp() are needed (in my case) and all the !_wifiManager.isWifiEnabled() may be ommited - as I only use the net if enabled by the user. I leave it for completeness.
Recap : in my scenario your method was not enough (if I translated correctly to java and didn't make some silly mistake, which always applies - see also my connection()). I needed to wait for connection to be established - but then all was fine. Not sure still how exactly you were using it - if as I do then the difference might be that you were holding a wifi lock all along
HTC Nexus 1, 2.3.7, Cyanogen mod (don't shoot I've been given it to test).
Will keep you posted