i have a chat application.my code has a thread which manages internet connection.
but after some minutes my thread goes sleep.
I know i should use WakeLock to wake CPU and my thread.
but when i use below code , battery usage goes up.
if (mWakeLock == null) {
mWakeLock = pm.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK,
"NewOnlineSignalingPowerManagerTag");
}
if (mWifiLock == null) {
mWifiLock = wm.createWifiLock(
WifiManager.WIFI_MODE_FULL,
"NewOnlineSignalingWifiManagerTag");
}
if (!mWakeLock.isHeld()) {
logging.l("mWakeLock.acquire()");
mWakeLock.acquire();
}
if (!mWifiLock.isHeld()) {
logging.l("mWifiLock.acquire()");
mWifiLock.acquire();
}
can you prefer me a better way?
Why do you have to manage a internet connection? You don't have to. Use a Android service, and there won't be a thread issue, nor a sleep issue.
Related
The problem is purely on some models:
android4.4.4+
After the andorid system goes into hibernation, http can not connect to the server (in service [thread]), I have awakened the cpu (wifi state), but still does not work.
update:
After about 10 minutes from the lock screen, the network connection is broken while (true) {http ==> connect server [thread sleep]}
//set wifi in BroadcastReceiver
public static void setWifiDormancy(Context context){
int value = Settings.System.getInt(context.getContentResolver(), Settings.Global.WIFI_SLEEP_POLICY, Settings.Global.WIFI_SLEEP_POLICY_DEFAULT);
Log.d(TAG, "setWifiDormancy() returned: " + value);
final SharedPreferences prefs = context.getSharedPreferences("wifi_sleep_policy", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putInt(Settings.Global.WIFI_SLEEP_POLICY, value);
editor.commit();
if(Settings.Global.WIFI_SLEEP_POLICY_NEVER != value){
Settings.System.putInt(context.getContentResolver(), Settings.Global.WIFI_SLEEP_POLICY, Settings.Global.WIFI_SLEEP_POLICY_NEVER);
}
}
//wakeLock in service
public void wakeLockRequest(){
if(wakeLock == null) {
PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK , getClass().getCanonicalName());
}
if(null != wakeLock && !wakeLock.isHeld()){
wakeLock.acquire();
}
}
//and in Service
startForeground(NOTIFYCATION_ID,createNotification());
After touching the lock screen, the app running in the background, and still can not connect to the server
When the user automatically click on the app, the network connection is restored (app in the foreground)
The first question, I have no way, at present can endure
The second problem I used a very stupid way to accept the screen on the broadcast, restart the app
I also try to restart the Service when screen on and screen off ,but The http is not work too.
Who has a good solution?Thanks!!!
I building a Android based SMS Server.
It shall request server (each x seconds) for new SMSes to send (in an infinite loop).
The Android device will be always plugged-in via USB to the server.
The fetching of the new messages is running as a service and I need it to run 24/7.
Since battery draining is not an issue here, how should I use the WakeLock?
As I read some articles about the partial lock it seems to be sufficient.
But yet I did not find any clues when should I call the wakeLock.acquire(); and wakeLock.release();
I do not suppose that it could work like that:
while(true){
wakeLock.acquire();
//Do stuff
wakeLock.release();
Thread.sleep(10000);
}
Considering the idea... Any inputs would be greatly apperciated. For example does it make sense to scheduler a daily restart of the phone so it will not get stucked? etc...
As explained here, various type of lock can be used. If you want to be always on, then you can acquire it outside the loop :
boolean end = false;
wakeLock.acquire();
while(!end){
//Do stuff
Thread.sleep(10000);
}
wakeLock.release();
But you shouldn't really use a loop for that, try an handler instead to do repeating tasks :
http://developer.android.com/reference/android/os/Handler.html
Example :
private class MyRunnable implements Runnable {
#Override
public void run() {
// Do stuff
handler.postDelayed(new MyRunnable(), 100000);
}
}
Handler handler = new android.os.Handler();
handler.postDelayed(new MyRunnable(), 1000000);
The handler is useful if you need to do a repeating task often and with a short period. If there period is longer (like few hours), use the AlarmManager :
Alarm Manager Example
That is a good example of what you can do, and they also use a wakelock for their tasks.
use the bellow way to wake up the device
private void wakeUpTheDevice()
{
pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wL = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK|PowerManager.ACQUIRE_CAUSES_WAKEUP, "wakeupdevice");
if ((wL != null) && // we have a WakeLock
(wL.isHeld() == false) ){ // but we don't hold it
wL.acquire();
}
}
I have a service which polls a server at certain intervals. I use an AlarmManager and a BroadcastReceiver to start the service. My problem is that after a certain duration, even though the Wifi is still enabled, but for some reason, my application can't contact the server. I get an "Unreachable network" error.
Note that I've already acquired a partial wake lock as well as a wifilock.
Here's my code for the BroadcastReceiver.
public class ServiceAlarmBroadcastReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
WakeLock wakeLock = null;
WifiLock wifiLock = null;
try {
PowerManager pm = (PowerManager) context
.getSystemService(Context.POWER_SERVICE);
// acquire a WakeLock to keep the CPU running
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyWakeLock");
if(!wakeLock.isHeld()){
wakeLock.acquire();
}
Log.i("ServiceAlarmBroadcastReceiver", "WakeLock acquired!");
WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
wifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL , "MyWifiLock");
if(!wifiLock.isHeld()){
wifiLock.acquire();
}
Log.i("ServiceAlarmBroadcastReceiver", "WifiLock acquired!");
context.startService(new Intent(context, ThePollerService.class));
} finally {
// release the WakeLock to allow CPU to sleep
if (wakeLock != null) {
if (wakeLock.isHeld()) {
wakeLock.release();
Log.i("ServiceAlarmBroadcastReceiver", "WakeLock released!");
}
}
// release the WifiLock
if (wifiLock != null) {
if (wifiLock.isHeld()) {
wifiLock.release();
Log.i("ServiceAlarmBroadcastReceiver", "WiFi Lock released!");
}
}
}
}
}
The problem with the code posted here is that you acquire and release the WakeLock and WifiLock from right inside of your receiver. Unless you are completing your entire task inside of the onStart of your service (which if you are, why even bother having a service???), the locks will be released before your polling task completes.
I would suggest changing your implementation to something like the following:
Have broadcast receiver start service (and that is all)
Have service acquire wake locks and kick off the thread to do your polling operation. The most appropriate spot would be your service onCreate)
After your polled operation is complete, you should stop your polling service
In the onDestroy of your service, you should release the locks you acquired in onStart
Thanks to Tom, I was able to resolve this issue. Here's the code:
Settings.System.putInt(getContentResolver(),
Settings.System.WIFI_SLEEP_POLICY,
Settings.System.WIFI_SLEEP_POLICY_NEVER);
Under the WiFi Settings, Menu Key, Advanced Options theirs the WIFI_SLEEP_POLICY option list which when set to never will keep the WiFi connection open while the phone is asleep.
You can manipulate this under Settings.System Package.
http://developer.android.com/reference/android/provider/Settings.System.html#WIFI_SLEEP_POLICY
Hope this helps,
Tom
A little edit to javauser's answer:
private void setNeverSleepPolicy() {
try {
ContentResolver cr = getContentResolver();
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
int set = android.provider.Settings.System.WIFI_SLEEP_POLICY_NEVER;
android.provider.Settings.System.putInt(cr, android.provider.Settings.System.WIFI_SLEEP_POLICY, set);
} else {
int set = android.provider.Settings.Global.WIFI_SLEEP_POLICY_NEVER;
android.provider.Settings.System.putInt(cr, android.provider.Settings.Global.WIFI_SLEEP_POLICY, set);
}
} catch (Exception e) {
e.printStackTrace();
}
}
I am having trouble with wakelocks. Basically, I had the wakelock running in my timer thread, a doInBackground of an AsyncTask for the entire duration of my app (it is a background app for taking performance measurements). Then I decided I only want the screen to wakeup every 10 minutes or so for a second or so. So I created another class extending AsyncTask and put the code below into it's doInBackground, but now the screen doesn't turn back on. I should note that I start this thread and two other threads that are AsyncTask with doInBackground methods from onCreate.
Here is my new inner class doing the waking up: Essentially all it is supposed to do is wake the phone screen up every 10 minutes for a bit until my other two background threads set their booleans true.
private class WakeUp extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... arg0) {
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, getClass().getName());
do{
try {
Thread.sleep(WAKEUP_EVERY); //600000ms
} catch (InterruptedException e) {
e.printStackTrace();
}
wl.acquire();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
wl.release();
}while(!timeCompleted || !transferCompleted);
return null;
}
}
You've forgotten to tell the wake lock to turn on the screen using the ACQUIRE_CAUSES_WAKEUP flag. As per the documentation:
Normal wake locks don't actually turn on the illumination. Instead, they cause the illumination to remain on once it turns on (e.g. from user activity). This flag will force the screen and/or keyboard to turn on immediately, when the WakeLock is acquired. A typical use would be for notifications which are important for the user to see immediately.
See ACQUIRE_CAUSES_WAKEUP for more details :D
I have a service which polls a server at certain intervals. I use an AlarmManager and a BroadcastReceiver to start the service. My problem is that after a certain duration, even though the Wifi is still enabled, but for some reason, my application can't contact the server. I get an "Unreachable network" error.
Note that I've already acquired a partial wake lock as well as a wifilock.
Here's my code for the BroadcastReceiver.
public class ServiceAlarmBroadcastReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
WakeLock wakeLock = null;
WifiLock wifiLock = null;
try {
PowerManager pm = (PowerManager) context
.getSystemService(Context.POWER_SERVICE);
// acquire a WakeLock to keep the CPU running
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyWakeLock");
if(!wakeLock.isHeld()){
wakeLock.acquire();
}
Log.i("ServiceAlarmBroadcastReceiver", "WakeLock acquired!");
WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
wifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL , "MyWifiLock");
if(!wifiLock.isHeld()){
wifiLock.acquire();
}
Log.i("ServiceAlarmBroadcastReceiver", "WifiLock acquired!");
context.startService(new Intent(context, ThePollerService.class));
} finally {
// release the WakeLock to allow CPU to sleep
if (wakeLock != null) {
if (wakeLock.isHeld()) {
wakeLock.release();
Log.i("ServiceAlarmBroadcastReceiver", "WakeLock released!");
}
}
// release the WifiLock
if (wifiLock != null) {
if (wifiLock.isHeld()) {
wifiLock.release();
Log.i("ServiceAlarmBroadcastReceiver", "WiFi Lock released!");
}
}
}
}
}
The problem with the code posted here is that you acquire and release the WakeLock and WifiLock from right inside of your receiver. Unless you are completing your entire task inside of the onStart of your service (which if you are, why even bother having a service???), the locks will be released before your polling task completes.
I would suggest changing your implementation to something like the following:
Have broadcast receiver start service (and that is all)
Have service acquire wake locks and kick off the thread to do your polling operation. The most appropriate spot would be your service onCreate)
After your polled operation is complete, you should stop your polling service
In the onDestroy of your service, you should release the locks you acquired in onStart
Thanks to Tom, I was able to resolve this issue. Here's the code:
Settings.System.putInt(getContentResolver(),
Settings.System.WIFI_SLEEP_POLICY,
Settings.System.WIFI_SLEEP_POLICY_NEVER);
Under the WiFi Settings, Menu Key, Advanced Options theirs the WIFI_SLEEP_POLICY option list which when set to never will keep the WiFi connection open while the phone is asleep.
You can manipulate this under Settings.System Package.
http://developer.android.com/reference/android/provider/Settings.System.html#WIFI_SLEEP_POLICY
Hope this helps,
Tom
A little edit to javauser's answer:
private void setNeverSleepPolicy() {
try {
ContentResolver cr = getContentResolver();
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
int set = android.provider.Settings.System.WIFI_SLEEP_POLICY_NEVER;
android.provider.Settings.System.putInt(cr, android.provider.Settings.System.WIFI_SLEEP_POLICY, set);
} else {
int set = android.provider.Settings.Global.WIFI_SLEEP_POLICY_NEVER;
android.provider.Settings.System.putInt(cr, android.provider.Settings.Global.WIFI_SLEEP_POLICY, set);
}
} catch (Exception e) {
e.printStackTrace();
}
}