Android Wifi睡眠,即使有锁

Android Wifi睡眠,即使有锁,android,wifi,Android,Wifi,小结:即使获得wifi锁定,当手机使用电池运行时,wifi也会在一段时间后断开 我已经将问题简化为一个带有启动线程的按钮的单个活动。它只向运行在PC上的echo服务器发送100.000个字符串(每100ms发送一个字符串)。请参阅下面的代码。我可以看到WireShark的流量,echo服务器也显示了字符串。注意在开始发送之前是如何获取WiFi和电源锁的(当然,在发送之后释放) 但是,当手机使用电池运行且用户关闭手机时,手机会持续发送字符串一段时间,然后WiFi断开,手机甚至不会响应ping。断开

小结:即使获得wifi锁定,当手机使用电池运行时,wifi也会在一段时间后断开

我已经将问题简化为一个带有启动线程的按钮的单个活动。它只向运行在PC上的echo服务器发送100.000个字符串(每100ms发送一个字符串)。请参阅下面的代码。我可以看到WireShark的流量,echo服务器也显示了字符串。注意在开始发送之前是如何获取WiFi和电源锁的(当然,在发送之后释放)

但是,当手机使用电池运行且用户关闭手机时,手机会持续发送字符串一段时间,然后WiFi断开,手机甚至不会响应ping。断开连接需要从600秒到6000秒的时间(这些数字都是圆形的,所以我认为它们很重要)

它完美地工作时,A/C连接,所以我想它是某种程度上与电源管理

要测试它,我只需启动活动,启动echo服务器,启动WireShark,按下“开始”按钮(
android:onClick=“doStart”
),阻塞手机并将其放在桌上。我去吃午饭或其他什么,在600-6000秒之后,我可以看到WireShark上的发送错误,echo服务器已经停止接收流量,手机没有响应ping

手机为2.2,WiFi策略设置为“15分钟后睡眠”

package-Odroid.test;
导入java.io.IOException;
导入java.io.InputStream;
导入java.io.PrintStream;
导入java.net.Socket;
导入java.net.UnknownHostException;
导入java.util.Date;
导入android.app.Activity;
导入android.content.Context;
导入android.net.wifi.WifiManager;
导入android.os.Bundle;
导入android.os.PowerManager;
导入android.view.view;
导入android.widget.Button;
公共类测试扩展了活动{
PowerManager\u powerManagement=null;
PowerManager.WakeLock _WakeLock=null;
WifiManager.WifiLock _WifiLock=null;
/**在首次创建活动时调用*/
@凌驾
创建时的公共void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
公共void doStart(视图五){
DoerThreadFake t=新的DoerThreadFake();
t、 start();
}
私有类DoerThreadFake扩展线程{
公开募捐{
runOnUiThread(新的Runnable(){
公开募捐{
((按钮)findviewbyd(R.id.start)).setText(“正在…”);
}
});
_keepOnStart();
插座;
字节[]缓冲区=新字节[1000];
试一试{
s=新插座(“192.168.0.16”,2000年);
PrintStream ps=新的PrintStream(s.getOutputStream());
InputStream=s.getInputStream();
对于(int i=0;i<100000;i++){
ps.println(System.currentTimeMillis()+”(“+(新日期()).toString()+”:+i);
试一试{
睡眠(100);
}捕捉(中断异常e){
e、 printStackTrace();
}
while(is.available()>0){
int a=is.available();
如果(a>1000)a=1000;
is.read(缓冲区,0,a);//清除回显
}
}
}捕获(未知后异常e){
e、 printStackTrace();
}捕获(IOE异常){
e、 printStackTrace();
}
_keepOnStop();
runOnUiThread(新的Runnable(){
公开募捐{
((按钮)findviewbyd(R.id.start)).setText(“完成”);
}
});
}
私有void_keepOnStart(){
如果(_powerManagement==null){
_powerManagement=(PowerManager)getSystemService(Context.POWER\u服务);
}
如果(_wakeLock==null){
_wakeLock=\u powerManagement.newWakeLock(PowerManager.PARTIAL\u WAKE\u LOCK | PowerManager.ACQUIRE\u原因|唤醒| PowerManager.ON _释放后,
“0备用电源锁”);
}
_wakeLock.acquire();
WifiManager WifiManager=(WifiManager)getSystemService(Context.WIFI_服务);
if(wifiManager!=null){
_wifiLock=wifiManager.createWifiLock(“0备份wifi锁”);
_wifiLock.acquire();
}
}
私有void_keepOnStop(){
如果((_wifiLock!=null)和(_wifiLock.ishelld()){
_wifiLock.release();
}
如果((_wakeLock!=null)和(_wakeLock.ishelld()){
_wakeLock.release();
}
}
}
}
舱单:

<?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>


有什么想法吗?

Android bug tracker上有许多与wifi睡眠/省电模式有关的bug,甚至还有试图纠正这一问题的应用程序。所以很可能你没有做错什么


还可以查看wifixer,它是一个开源项目,可以帮助您编写代码来保持连接的活力


谢谢。通过链接和深入浏览,HTC设备似乎更容易出现错误行为。。。这就是我的情况(HTC desire)。闻起来好像问题出在低级代码中,可能是在HTC WiFi驱动程序中-(我使用了一个变通方法。我在HTC Desire HD上也遇到了同样的问题。@Jevier,你能解释一下你的变通方法吗?Imon(对不起,我到现在为止还没有看到评论),非常简单:如果设备使用电池,中止执行。这对我的应用程序来说是可以接受的,但对其他应用程序来说可能不够:-(
<?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>