2012-09-03 69 views
7

我正在開發一個Android應用程序,我需要儘可能準確地測量當前連接的下載速度。這是我能找到到目前爲止最好的方法(基本上我啓動一個定時器,開始從快速的服務器下載一個Linux發行版,下載大約200字節,則停止計時器,並檢查時間流逝和下載的總字節數):使用Java/Android測量下載速度

try{     
    InputStream is = new URL("http://www.domain.com/ubuntu-linux.iso").openStream(); 
    byte[] buf = new byte[1024]; 
    int n = 0;    
    startBytes = TrafficStats.getTotalRxBytes(); /*gets total bytes received so far*/ 
    startTime = System.nanoTime(); 
    while(n<200){ 
     is.read(buf); 
     n++;     
    } 
    endTime = System.nanoTime(); 
    endBytes = TrafficStats.getTotalRxBytes(); /*gets total bytes received so far*/ 
    totalTime = endTime - startTime; 
    totalBytes = endBytes - startBytes; 
} 
catch(Exception e){ 
    e.printStackTrace(); 
} 

之後,我只需要將傳輸的字節數除以所花費的時間,它將以bps爲單位給出下載速度。

問題: 1.此方法是否準確? 2.你認識一個更好的嗎?

非常感謝。

+0

他們的方式,你有它設置,現在,它不會是準確的。 InputStream.read不能保證完全填充你的緩衝區。您需要檢查返回值以查看實際讀取的字節數。 – Jeffrey

+1

@Jeffrey,你沒有詳細閱讀代碼。我不依賴read()來獲取字節數。我通過getTotalRxBytes()函數直接從操作系統獲取它。 –

+0

啊,我的不好。我確實在那部分上略過。您擁有的解決方案將會或多或少精確。 – Jeffrey

回答

4

這裏有幾個可能出現的問題:

  1. 如果您正在尋找這樣做在飛行中的任意設備上(在對實驗室環境),您將需要遵循傑弗裏的建議,因爲其他應用可能會消耗由getTotalRxBytes()報告的帶寬。

  2. 這測試從這個主機的下載速度。如果這是您將與「真正的東西」進行通信的主持人,那很酷。或者,如果您只是一般需要下載速度的想法,那沒關係。但是,從站點A測試下載速度並假設它對於站點B來說是準確的將是不可靠的,因爲站點A和站點B可能甚至不在同一大陸。

  3. 如果您希望做到這一點,您測試的主機的所有者可能會受到帶寬費用,過多的日誌條目等的輕度激怒。理想情況下,您只會對您擁有的東西做這件事。

  4. 對於計量數據計劃,200KB可能會刺激設備所有者。

  5. 所有有關因特網訪問(例如,服務器可能關閉)以及移動設備(例如,用戶可能在WiFi上啓動並移出範圍,大幅改變下載能力)的標準警告都適用。

所有的說法是,下載是衡量下載速度的唯一真正方法。

+0

關於第一點:「其他應用程序可能會消耗由getTotalRxBytes()報告的帶寬」,如果想法是測量帶寬,那麼可以使用getTotalRxBytes(),如果其他應用程序消耗帶寬,您希望考慮一下你的計算。 – Chiara

1

使用下面的代碼。我用它來測量下載速度。 爲了測量下載速度,您不需要保存該文件。你也可能不需要使用OkHttp。我用它是因爲它在我們的項目中使用。

String downloadURL = "http://test.talia.net/dl/1mb.pak"; 

    MediaType FILE = MediaType.parse("multipart/form-data;"); 

    OkHttpClient downloadClient = new OkHttpClient().newBuilder() 
      .build(); 

    Request download = new Request.Builder() 
      .url(downloadURL) 
      .build(); 

    downloadClient.newCall(download).enqueue(new Callback() { 
     @Override 
     public void onFailure(Call call, IOException e) { 

     } 

     @Override 
     public void onResponse(Call call, Response response) throws IOException { 
      if(response!=null) { 
       long startTime = System.currentTimeMillis(); 
       InputStream is = response.body().byteStream(); 
       BufferedInputStream bis = new BufferedInputStream(is); 
       long size = 0; 
       int red = 0; 
       byte[] buf = new byte[1024]; 
       while ((red = bis.read(buf)) != -1) { 
        size += red; 
       } 
       long endTime = System.currentTimeMillis(); 
       double rate = (((size/1024)/((endTime - startTime)/1000)) * 8); 
       rate = Math.round(rate * 100.0)/100.0; 
       String ratevalue; 
       if(rate > 1000) 
        ratevalue = String.valueOf(rate/1024).concat(" Mbps"); 
       else 
        ratevalue = String.valueOf(rate).concat(" Kbps"); 
       if(is!=null) { 
        is.close(); 
       } 
       if(bis!=null) { 
        bis.close(); 
       } 
       Log.d("download", "download speed = " + ratevalue); 
      } 
     } 
    });