Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
326 views
in Technique[技术] by (71.8m points)

android - Wifi sleeps, even with Lock

Summary: even when wifi lock is acquired, when the phone is running on batteries, WiFi is disconnected after a while.

I've simplified the problem to a single activity with a button that launches a thread. It just sends 100.000 strings to an echo server running on a PC (one string every 100ms). See code below. I can see the traffic with WireShark, and also the echo server shows the strings. Notice how WiFi and power locks are acquired before starting to send (and released after, of course).

However, when the phone is running on battery and the user turns off the phone, it keeps sending strings for some time and then WiFi is disconnected and the phone does not even respond to ping. It takes from 600s to 6000s to be disconnected (the figures are that round, so I think they are important).

It perfectly works when A/C is connected, so I guess it is somehow related to power management.

To test it I just launch the activity, start the echo server, start WireShark, press the "Start" button (android:onClick="doStart"), blocks the phone and let it on the table. I go for lunch or whatever and after 600-6000s I can see the tx errors on WireShark, the echo server has stopped receiving traffic and the phone does not respond to ping.

The phone is 2.2, with WiFi policy set to "sleep after 15m".

package Odroid.test;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Date;

import android.app.Activity;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.PowerManager;
import android.view.View;
import android.widget.Button;

public class Test extends Activity {
  PowerManager _powerManagement = null;
  PowerManager.WakeLock _wakeLock = null;
  WifiManager.WifiLock _wifiLock = null;

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
  }

  public void doStart(View v) {
    DoerThreadFake t = new DoerThreadFake();
    t.start();
  }

  private class DoerThreadFake extends Thread {
    public void run() {
      runOnUiThread(new Runnable() {
        public void run() {
          ((Button) findViewById(R.id.start)).setText("Doing...");
        }
      });
      _keepOnStart();
      Socket s;
      byte[] buffer = new byte[1000];

      try {
        s = new Socket("192.168.0.16", 2000);
        PrintStream ps = new PrintStream(s.getOutputStream());
        InputStream is = s.getInputStream();
        for (int i = 0; i < 100000; i++) {
          ps.println(System.currentTimeMillis() +"("+(new Date()).toString() +") : " + i);
          try {
            Thread.sleep(100);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          while (is.available() > 0) {
            int a = is.available();
            if (a > 1000) a = 1000;
            is.read(buffer, 0, a); // Clean echo
          }
        }
      } catch (UnknownHostException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      }
      _keepOnStop();
      runOnUiThread(new Runnable() {
        public void run() {
          ((Button) findViewById(R.id.start)).setText("Done");
        }
      });
    }

    private void _keepOnStart() {
      if (_powerManagement == null) {
        _powerManagement = (PowerManager) getSystemService(Context.POWER_SERVICE);
      }
      if (_wakeLock == null) {
        _wakeLock = _powerManagement.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE,
            "0 Backup power lock");
      }
      _wakeLock.acquire();
      WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
      if (wifiManager != null) {
        _wifiLock = wifiManager.createWifiLock("0 Backup wifi lock");
        _wifiLock.acquire();
      }
    }

    private void _keepOnStop() {
      if ((_wifiLock != null) && (_wifiLock.isHeld())) {
        _wifiLock.release();
      }
      if ((_wakeLock != null) && (_wakeLock.isHeld())) {
        _wakeLock.release();
      }
    }
  }
}

The manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest
  xmlns:android="http://schemas.android.com/apk/res/android"
  package="Odroid.test"
  android:versionCode="1"
  android:versionName="1.0"
>
  <uses-sdk android:minSdkVersion="4" />

  <application
    android:icon="@drawable/icon"
    android:label="@string/app_name"
  >
    <activity
      android:name=".Test"
      android:label="@string/app_name"
    >
      <intent-filter>
        <action
          android:name="android.intent.action.MAIN" />
        <category
          android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>

  </application>
  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
  <uses-permission android:name="android.permission.WAKE_LOCK" />

</manifest>

Any idea?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There are numerous bugs on the Android bug tracker to do with wifi sleep/power saving mode and even apps available that attempt to rectify this. So it is quite likely that you are not doing anything wrong.

http://code.google.com/p/android/issues/detail?id=9781
http://code.google.com/p/android/issues/detail?id=1698

Also check out wififixer which is an open source project which may help you with code to keep the connection alive

http://wififixer.wordpress.com/


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...