Turn on the Internet on Android when in sleep
android, sleep-mode
Solution
First, you need to get that `HttpPost` code out of the `BroadcastReceiver` and into an `IntentService`. Never do network I/O on the main application thread, and `onReceive()` is called on the main application thread. For example, if you take too long, Android will terminate your code partway through your Internet operation.
Second, given the `IntentService`, you need to use a `WakeLock`. That may steer you to use my `WakefulIntentService`, which handles both problems. Or, use `WakefulBroadcastReceiver`, which has the same purpose.
Third, delete `turnOnInet()` and `getMobileDataEnabled()`. You do not need them, they are unreliable, and in particular `turnOnInet()` is user-hostile -- if the user wanted mobile data on, they would have turned it on.
Now, given all of that, in your `onHandleIntent()` of your `IntentService()` (or your `doWakefulWork()` of your `WakefulIntentService`), if you do not have an Internet connection right away, as a temporary workaround, `SystemClock.sleep()` for a second and try again, repeating a few times in a loop. If you find that you are getting Internet access after a bit, then you can consider getting more sophisticated (e.g., listening for connectivity change broadcasts rather than polling, though this would drive you away from `WakefulIntentService` and into a regular `Service` with your own background thread and a state machine for `WakeLock` management). Or, just stick with the `sleep()` -- it's unlikely to be the end of the world if you tie up this background thread for a few seconds. If you do not get connectivity after a modest amount of time, though, please do not keep trying indefinitely, as there are any number of reasons why you might not get a connection, including user-driven bandwidth management on Android 4.0+.
Problem
I have an Android app that needs to sync to the internet, but as soon as the phone goes to sleep I can't access the internet. It only happens when the user uses the "battery mode", when it turns off the data after 15 minutes. I wrote a test app and its turning the data on, but it still does connect to the server. What I tried: - When I turn the data manually off, then the app is turning it on and it works - I also tried WakeLock, but it did not help. - The alarm works as expected, even when the phone goes to sleep for hours Tested on Motorola Atrix Android 2.3.3. I can't rely on Wifi. In real life it will sync every week. How can we make it possible? AlarmManager: ``` alarm_manager = (AlarmManager)getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(this, AlarmReceiver.class); PendingIntent pending = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); alarm_manager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 15000, pending); ``` AlarmReceiver: ``` public class AlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Log.d("MYTAG", "RECEIVED getMobileDataEnabled: " + getMobileDataEnabled(context)); if (!isOnline(context)) { Log.d("MYTAG", "NO INET"); if (turnOnInet(context)) { Log.d("MYTAG", "INET IS ON"); } } HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost("http://xxx.xxx.xxx.xxx/ping/pong/moto/"); try { List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1); nameValuePairs.add(new BasicNameValuePair("short_code", "ROFL")); httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); httpclient.execute(httppost); Log.d("MYTAG", "POST FINISHED"); } catch (Exception e) { Log.e("MYTAG", "MYTAG", e); } } public boolean isOnline(Context context) { ConnectivityManager cm = (ConnectivityManager)context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo netInfo = cm.getActiveNetworkInfo(); if (netInfo != null){ Log.d("MYTAG", "isAvailable: "+netInfo.isAvailable()); } if (netInfo != null && netInfo.isConnectedOrConnecting()) { return true; } return false; } public boolean turnOnInet(Context context) { ConnectivityManager mgr = (ConnectivityManager)context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE); if (mgr == null) { Log.d("MYTAG", "ConnectivityManager == NULL"); return false; } try { Method setMobileDataEnabledMethod = mgr.getClass().getDeclaredMethod("setMobileDataEnabled", boolean.class); if (null == setMobileDataEnabledMethod) { Log.d("MYTAG", "setMobileDataEnabledMethod == null"); return false; } setMobileDataEnabledMethod.invoke(mgr, true); } catch(Exception e) { Log.e("MYTAG", "MYTAG", e); return false; } return true; } private boolean getMobileDataEnabled(Context context) { ConnectivityManager mgr = (ConnectivityManager)context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE); if (mgr == null) { Log.d("MYTAG", "getMobileDataEnabled ConnectivityManager == null"); return false; } try { Method method = mgr.getClass().getMethod("getMobileDataEnabled"); return (Boolean) method.invoke(mgr); } catch (Exception e) { Log.e("MYTAG", "MYTAG", e); return false; } } } ``` AndroidManifest.xml ``` <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> ```