سؤال

I'm trying to perform an AsyncTask class in my Android application that analyzes the network connection speed in for downloading and uploading. I'm working on the download portion now, but I'm not getting results I expect. I'm testing on a Wifi network that gets 15Mbps down/up speeds consistently, however, the results I'm getting from my application are more around barely 1Mbps. When I run the speed test apk on the device I'm testing on that gets around 3.5Mbps. The function works, just seems to be half the speed it should be. Should the following code produce accurate results?

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

Example output

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

Thanks in advance for the help. If there is a better method, please let me know.

هل كانت مفيدة؟

المحلول

Following on my comments, here is an example of how to read several bytes from the stream

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

What this does is it reads into a byte[] buffer, and return the amount of read bytes. This is in turn written to the OutputStream, specifying the amount of bytes to write.

ByteArrayOutputStream also have a toByteArray that behaves similarly.

Alternatively, you can also write directly to the file, if you consider that the write to file operation is significantly faster than the read function :

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

Moreover, if you really only care about the download speed, it is not mandatory to write to the file, or to anywhere, this would be sufficient :

long size = 0;
byte[] buf = new byte[1024];
while ((red = bis.read(buf)) != -1) {
    size += red;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top