2011-02-28 91 views
19

总结:即使在获取wifi锁定时,当手机使用电池时,WiFi会在一段时间后断开连接。即使有锁,Wifi睡觉

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

然而,当手机电池运行和用户关闭手机,则会持续发送了一段时间的字符串,然后无线网络连接断开,手机甚至不响应Ping。它需要600到6000秒才能断开(数字是那么一轮,所以我认为它们很重要)。

连接的A/C时,它完美的作品,所以我想这是主题相关的电源管理。

为了测试它,我只需启动活动,启动回显服务器,启动WireShark,按下“开始”按钮(android:onClick="doStart"),封锁手机并将其放在桌子上。我去吃午餐或任何东西,在600-6000s之后,我可以看到WireShark上的tx错误,echo服务器已经停止接收流量,并且电话不响应ping。

的手机是2.2,与“15米后睡眠”设置为无线网络政策。

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(); 
     } 
    } 
    } 
} 

清单:

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

任何想法?

回答

11

有对Android bug跟踪许多错误做了WiFi睡眠/省电模式,甚至应用程式可用的试图纠正这一点。所以很可能你没有做错任何事情。

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

还检查了wififixer这是一个开源项目,它可以帮助你用代码来保持连接

http://wififixer.wordpress.com/

+2

感谢。根据您的链接和浏览更深入,似乎HTC设备更可能不正确的行为......这是我的情况(宏达愿望)。它闻起来像是问题是在低层次的代码,可能在HTC WiFi驱动程序等等。 :-(我用一种变通方法 – 2011-03-26 06:59:33

+0

我面临的HTC Desire HD相同的问题@Jevier请你解释一下你的解决方法 – Imon 2011-11-22 14:18:55

+0

亿盟(对不起,我没看到到现在为止评论),很简单:?如果该设备使用电池,中止执行。对于我的应用程序是可以接受的,但对其他人可能不够。:-( – 2012-02-03 09:26:59