2013-10-08 4 views
3

Я пытаюсь выполнить класс AsyncTask в своем приложении для Android, который анализирует скорость сетевого подключения для загрузки и выгрузки. Сейчас я работаю над частью загрузки, но я не ожидаю результатов. Я тестирую сеть Wi-Fi, которая получает 15 Мбит/с скорость/скорость, но результаты, которые я получаю от моего приложения, составляют примерно 1 Мпб. Когда я запускаю тест скорости apk на устройстве, которое я тестирую, он получает около 3.5 Мбит/с. Функция работает, похоже, на половину скорости она должна быть. Должен ли следующий код давать точные результаты?Как правильно измерить скорость загрузки с помощью Java/Android

try { 
      String DownloadUrl = "http://ipv4.download.thinkbroadband.com:8080/5MB.zip"; 
      String fileName = "testfile.bin"; 


      File dir = new File (context.getFilesDir() + "/temp/"); 
      if(dir.exists()==false) { 
       dir.mkdirs(); 
      } 

      URL url = new URL(DownloadUrl); //you can write here any link 
      File file = new File(context.getFilesDir() + "/temp/" + fileName); 


      long startTime = System.currentTimeMillis(); 
      Log.d("DownloadManager", "download begining: " + startTime); 
      Log.d("DownloadManager", "download url:" + url); 
      Log.d("DownloadManager", "downloaded file name:" + fileName); 

      /* Open a connection to that URL. */ 
      URLConnection ucon = url.openConnection(); 

      //Define InputStreams to read from the URLConnection. 
      InputStream is = ucon.getInputStream(); 
      BufferedInputStream bis = new BufferedInputStream(is); 

      //Read bytes to the Buffer until there is nothing more to read(-1). 
      ByteArrayBuffer baf = new ByteArrayBuffer(1024); 
      int current = 0; 
      while ((current = bis.read()) != -1) { 
       baf.append((byte) current); 
      } 
      long endTime = System.currentTimeMillis(); //maybe 

      /* Convert the Bytes read to a String. */ 
      FileOutputStream fos = new FileOutputStream(file); 
      fos.write(baf.toByteArray()); 
      fos.flush(); 
      fos.close(); 

      File done = new File(context.getFilesDir() + "/temp/" + fileName); 
      Log.d("DownloadManager", "Location being searched: "+ context.getFilesDir() + "/temp/" + fileName); 
      double size = done.length(); 
      if(done.exists()) { 
       done.delete(); 
      } 

      Log.d("DownloadManager", "download ended: " + ((endTime - startTime)/1000) + " secs"); 
      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"); 
      Log.d("DownloadManager", "download speed: "+ratevalue);  
    } catch (IOException e) { 
     Log.d("DownloadManager", "Error: " + e); 
    } 

Пример выходных

10-08 15:09:52.658: D/DownloadManager(13714): download ended: 70 secs 
10-08 15:09:52.662: D/DownloadManager(13714): download speed: 585.14 Kbps 

Заранее спасибо за помощь. Если есть лучший способ, пожалуйста, дайте мне знать.

+0

Вы читаете по одному байт за раз, это может быть довольно долго. почему бы не использовать байт [] и читать как несколько Kb одновременно? – njzk2

+0

Обычно у вас есть ~ 600 тыс. Вызовов для 'read' и' append' каждую секунду. – njzk2

+0

, ваше значение ставки может быть не очень точным, так как 'size',' endTime' и 'startTime' являются целыми, как 1024, 1000 и 8, и поэтому ваши вычисления производятся в целых числах до того, как они будут отправлены на длинные (это должен давать неточную фиксацию, но не несет ответственности за большую разницу, которую вы наблюдаете) – njzk2

ответ

2

После моих комментариев, вот пример того, как считывать несколько байт из потока

//Define InputStreams to read from the URLConnection. 
InputStream is = ucon.getInputStream(); 
BufferedInputStream bis = new BufferedInputStream(is); 

//I usually use a ByteArrayOutputStream, as it is more common. 
ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
int red = 0; 
// This size can be changed 
byte[] buf = new byte[1024]; 
while ((red = bis.read(buf)) != -1) { 
    baos.write(buf, 0, red); 
} 

Что это делает он читает в байт [] буфера, и возвращает количество считанных байтов. Это, в свою очередь, записывается в OutputStream, указывая количество байтов для записи.

ByteArrayOutputStream также имеет toByteArray, который ведет себя аналогичным образом.

В качестве альтернативы, вы можете также записать непосредственно в файл, если вы считаете, что запись в файл операции значительно быстрее, чем функция чтения:

// Simply start by defining the fileoutputstream 
FileOutputStream fos = new FileOutputStream(file); 
int red = 0; 
// This size can be changed 
byte[] buf = new byte[1024]; 
while ((red = bis.read(buf)) != -1) { 
    // And directly write to it. 
    fos.write(buf, 0, red); 
} 
long endTime = System.currentTimeMillis(); //maybe 
// Flush after, as this may trigger a commit to disk. 
fos.flush(); 
fos.close(); 

Кроме того, если вы на самом деле только заботитесь о скорости загрузки , не обязательно писать в файл или в любом месте, этого было бы достаточно:

long size = 0; 
byte[] buf = new byte[1024]; 
while ((red = bis.read(buf)) != -1) { 
    size += red; 
} 
+0

Жаль, что не вернулась раньше. Я очень ценю подробный ответ. Я пробовал оба метода и в конечном итоге пошел с предложением даже не писать размер данных, я действительно хочу сосредоточиться только на скорости загрузки. Поскольку изменение на несколько байтов, мои результаты должны быть близки к тому или другому тесту скорости. Опять же, еще раз спасибо за пример, они отлично работали. – Joffroi

Смежные вопросы