2012-09-03 13 views
7

Pracuję nad aplikacją na Androida, w której muszę, tak dokładnie, jak to możliwe, zmierzyć szybkość pobierania bieżącego połączenia. Oto najlepsza metoda, jaką udało mi się znaleźć do tej pory (w zasadzie uruchamiam programator, zaczynam pobierać dystrybucję Linuksa z szybkiego serwera, pobieram około 200 kilobajtów, zatrzymuję licznik czasu i sprawdzam czas, który upłynął oraz pobrano całkowite bajty):Pomiar prędkości pobierania z Java/Androidem

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

Po tym czasie wystarczy podzielić liczbę bajtów przesłanych przez czas wykonania, a prędkość pobierania zostanie podana w bps.

Pytania: 1. Czy ta metoda będzie dokładna? 2. Czy znasz lepszy?

Wielkie dzięki.

+0

W ten sposób skonfigurujesz to teraz, nie będzie to dokładne. 'InputStream.read' nie gwarantuje pełnego wypełnienia bufora. Musisz sprawdzić wartość zwracaną, aby zobaczyć, ile "bajtów" zostało faktycznie przeczytanych. – Jeffrey

+1

@Jeffrey, nie przeczytałeś dokładnie kodu. Nie liczę na read(), aby uzyskać liczbę bajtów. Otrzymuję go bezpośrednio z systemu operacyjnego za pomocą funkcji getTotalRxBytes(). –

+0

Ahh, moje złe. Rzeczywiście przejrzałem tę część. Twoje rozwiązanie będzie mniej lub bardziej dokładne. – Jeffrey

Odpowiedz

4

Istnieje kilka możliwych problemów tutaj:

  1. Jeśli szukasz to zrobić w locie na dowolnym urządzeniu (w porównaniu w warunkach laboratoryjnych), trzeba będzie się do zaleceń Jeffreya, ponieważ inne aplikacje mogą zużywać przepustowość, która byłaby zgłaszana przez getTotalRxBytes().

  2. Testuje prędkość pobierania od tego hosta. Jeśli to host, z którym będziesz się komunikować w "prawdziwych rzeczach", jest fajnie. Lub, jeśli zwyczajnie potrzebujesz pomysłu na prędkość pobierania, jest OK. Jednak test prędkości pobierania z witryny A i założenie, że będzie on dokładny dla witryny B, będzie niewiarygodny, ponieważ witryna A i witryna B mogą nawet nie znajdować się na tym samym kontynencie.

  3. Jeśli spodziewasz się tego zrobić dużo, właściciel hosta, z którym testujesz, może być lekko zirytowany kosztem przepustowości, nadmiernymi zapisami w logach itp. Najlepiej byłoby, gdybyś zrobił to tylko przeciwko własnemu posiadaniu.

  4. Dla planów taryfowych danych, 200 KB może drażnić właściciela urządzenia.

  5. Wszystkie standardowe zastrzeżenia dotyczące dostępu do Internetu (np. Serwer może być wyłączony) i urządzeń przenośnych (np. Użytkownik może rozpocząć korzystanie z WiFi i wyjść poza zasięg, drastycznie zmieniając możliwości pobierania).

Wszystko, co mówi, robi pobrania jest jedynym sposobem, aby zmierzyć prędkość pobierania.

+0

z szacunkiem do pierwszego punktu: "inne aplikacje mogą zużywać przepustowość, która byłaby zgłaszana przez getTotalRxBytes()" jeśli chodzi o pomiar szerokości pasma, to można użyć getTotalRxBytes(), ponieważ inne aplikacje zużywają pasmo, które chcesz rozważ to na swoich obliczeniach. – Chiara

1

Użyj poniższego kodu. Użyłem go do pomiaru prędkości pobierania. Nie musisz zapisywać pliku, aby zmierzyć prędkość pobierania. Prawdopodobnie nie musisz też używać OkHttp. Użyłem go, ponieważ został użyty w naszym projekcie.

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