2011-02-28 90 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