- ACTION_SCREEN_ON and ACTION_SCREEN_OFF not working?
- Android : Reconnect to Wi-Fi after entering coverage area while screen turned off
- 3 Answers 3
- Android: WiFi-Direct communication when screen is off
- 1 Answer 1
- Detect screen off/on and change wifi state in Android
- How To Disable WiFi Automatically When Screen is Off
ACTION_SCREEN_ON and ACTION_SCREEN_OFF not working?
I’m trying to turn WiFi off when the screen is OFF (locked), and turn it on again when screen is ON (unlocked). I made a BroadcastReceiver ; put in manifest this code:
package org.androidpeople.boot; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; public class MyIntentReceiver extends BroadcastReceiver < // Called when boot completes public static boolean startup; @Override public void onReceive(Context context, Intent intent) < // Set what activity should launch after boot completes System.out.println("Intent Action: " + intent.getAction()); if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) < System.out.println("locked : ACTION_SCREEN_OFF"); >else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) < System.out.println("not locked : ACTION_SCREEN_ON "); >else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) < System.out.println("User Unlocking it "); >else if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) < // this to indicate that program is running // automaticlly not manually by user startup = true; System.out.println("Automatic BOOT at StartUp"); Intent startupBootIntent = new Intent(context, LaunchActivity.class); startupBootIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(startupBootIntent); >> >
And the result is — both ACTION_SCREEN_ON and ACTION_SCREEN_OFF never fired! USER_PRESENT and BOOT_COMPLETED worked fine but the other did not. I’m using an emulator, not a real device — can this cause the problem? Any help? I need to catch the screen on and off in order to enable/disable WiFi to save battery. Thanks in advance
Android : Reconnect to Wi-Fi after entering coverage area while screen turned off
Result : The Wifi is not reconnected immediately and thus app does not reconnect to server. Depending on the device and settings, sometimes it would not reconnect at all until the screen was turned on.
Forcing the Wi-Fi to reconnect
Ok, this time my application calls WifiManager.Reconnect() at an interval if Wifi is disconnected.
Repeated the test. Results : Worked for the S3, failed for other devices.
Tried adding some other calls
Tried different combinations of WifiManager.Scan(), WifiManager.Reassociate(), . etc. Eventually it was working for most devices(HTC, S3) except the S4.
Code that seems to work for all devices
NetworkInfo wifiInfo = _androidConnectivityMgr.GetNetworkInfo(ConnectivityType.Wifi); if (!_wifiManager.IsWifiEnabled || _wifiManager.WifiState == WifiState.Disabled || _wifiManager.WifiState == WifiState.Disabling) < // Make sure the Wi-Fi is enabled, required for some devices when enable WiFi does not occur immediately _wifiManager.SetWifiEnabled(true); >if (!wifiInfo.IsConnectedOrConnecting) < // Do not wait for the OS to initiate a reconnect to a Wi-Fi router _wifiManager.PingSupplicant(); if (_wifiManager.WifiState == WifiState.Enabled) < try < // Brute force methods required for some devices _wifiManager.SetWifiEnabled(false); _wifiManager.SetWifiEnabled(true); >catch (Java.Lang.SecurityException) < // 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(); >
I am not even sure all this code is necessary as I was unable to find much information online. WifiFixer did help some. But this does seem to work for the devices I have tested on.
The Question
- Is there a better way of doing this?
- Do the manufacturers really modify the base Android where I can be seeing this much of a difference?
- Is this completely the wrong way to approach this?
Thanks for reading through all this 🙂
Additional Notes
- Code runs during 10+ second interval initiated from the AlarmManager. WakeLock is held only for the duration of this call.
- Before this final scary looking solution/hack the «Wifi Sleep Policy» affected the results. This confused me since I am holding a WifiLock the entire time, which I thought was equivalent of «Never».
- Changing the «Wifi Sleep Policy» programmatically does not work for the S4, can anyone else confirm?
- Yes, we have a specific need to do this and are aware of battery implication.
3 Answers 3
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).
Android: WiFi-Direct communication when screen is off
I’m experimenting with P2P communication on Android using WiFi-Direct. I’ve got a service that searchs for other phones and automatically connects to them if they’ve been paired before. I like to have this working regardless of whether the screen is on or off. Android offers an option to keep WiFi alive when the device screen is off. But it looks like it doesn’t affect WiFi-Direct. After turning the device’s screen off and waiting a minute the WifiP2pManager seems to stop discovering new peers. Has anyone an idea how to fix this behaviour?
1 Answer 1
So what is happening here is that you are calling startDiscoveryProcess() 50 seconds after screen is turned off and startDiscoveryProcess() is calling itself every 50 seconds. How to stop that process? You listen for Intent.ACTION_SCREEN_ON and if screen is on, we don’t send the broadcast to start discovery again.
boolean screenOn = true; BroadcastReceiver screenReceiver = new BroadcastReceiver() < @Override public void onReceive(Context context, Intent intent) < if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF) || intent.getAction().equals("MY_ACTION_WHEN_SCREEN_IS_OFF")) < screenOn = false; new Handler().postDelayed(new Runnable() < @Override public void run() < // start discovery process again startDiscoveryProcess(); >>, 50000); > else if(intent.getAction().equals(Intent.ACTION_SCREEN_ON)) < screenOn = true; >> >;
In onCreate() of your service, register the receiver:
IntentFilter filters = new IntentFilter(); filters.addAction(Intent.ACTION_SCREEN_OFF); filters.addAction(Intent.ACTION_SCREEN_ON); filters.addAction("MY_ACTION_WHEN_SCREEN_IS_OFF"); registerReceiver(screenReceiver, filters);
Then just make sure to have the method we called above:
void startDiscoveryProcess() < //start discovery process // do something. // then send the broadcast yourself to do this every 50 seconds because discovery stops at 60 seconds if(!screenOn) < Intent intent = new Intent("MY_ACTION_WHEN_SCREEN_IS_OFF"); sendBroadcast(intent); >>
Detect screen off/on and change wifi state in Android
I’m trying to setup a service that detect when screen goes off and disable the wifi. Here is my code: Service:
public static boolean isScreen; private int mInterval = 5000; private Handler mHandler; @Override public void onCreate() < mHandler = new Handler(); startRepeatingTask(); IntentFilter mFilter = new IntentFilter("com.my.package.myAction"); BroadcastReceiver mReceiver = new screenReceiver(); registerReceiver(mReceiver, mFilter); >Runnable mStatusChecker = new Runnable() < @Override public void run() < Intent intent = new Intent(); intent.setAction("com.my.package.myAction"); sendBroadcast(intent); PowerManager pm = (PowerManager) androidTweaker.this.getSystemService(Context.POWER_SERVICE); isScreen = pm.isScreenOn(); mHandler.postDelayed(mStatusChecker, mInterval); >>; void startRepeatingTask() < mStatusChecker.run(); >void stopRepeatingTask()
And here is my first question: I set up an handler to check every 5 seconds the state of the screen. Have you got any better solution? My receiver:
public class screenReceiver extends BroadcastReceiver < @Override public void onReceive(Context context, Intent intent) < ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(context.CONNECTIVITY_SERVICE); NetworkInfo mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); if (!myService.isScreen && !mWifi.isConnected()) < WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); wifiManager.setWifiEnabled(false); >>
> And here my service crash. The logcat report the error in this line: wifiManager.setWifiEnabled(false); (Receiver) My manifest:
My service of course got a notification with foreground, so it’s always on. Any help? Edit: I got the main problem (changing wifi state) solved by replace
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction("com.my.package.myAction"); BroadcastReceiver mReceiver = new screenReceiver(); registerReceiver(mReceiver, filter);
@Override public void onReceive(Context context, Intent intent) < if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) < WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); wifiManager.setWifiEnabled(false); >else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) < WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); wifiManager.setWifiEnabled(true); >Intent i = new Intent(context, androidTweaker.class); context.startService(i); >
How To Disable WiFi Automatically When Screen is Off
It’s probably of no use when you are not using your android smartphone, WiFi sys background apps and uses data. So ultimately you can improve smartphone’s battery life will be increased. Here is how you can set up Disable WiFi Automatically during your screen is off and you are not using your device.
Here are few steps to be followed to setup automatic turn off your smartphone’s WiFi.
1. Go to setting menu from your smartphone and then tap on WiFi option.
2.Now you will be in WiFi menu, there tap on options button to show advanced menus. Tap on Advanced menu.
3. You are now on advanced WiFi setting menu. There you will see keep WiFi on during sleep. Tap on the option for setup.
4.There will be now three options, say always, when plugged in and never( increases data usage). Select Never (increase data usage) from that three option.
When you select always, it will keep your WiFi on during your device’s screen is off. If you choose when plugged in, it will keep WiFi on when your device screen is on or device is in charging. Otherwise, WiFi will be kept off automatically. If you select Never( increase data usage) option, whenever your screen off, it will automatically switch off your device’s WiFi.