2012-09-03 46 views
7

Tôi đang làm việc trên một ứng dụng Android mà tôi cần, chính xác nhất có thể, đo tốc độ tải xuống của kết nối hiện tại. Dưới đây là phương pháp tốt nhất mà tôi có thể tìm thấy (về cơ bản tôi bắt đầu hẹn giờ, bắt đầu tải xuống bản phân phối Linux từ máy chủ nhanh, tải xuống khoảng 200 kbyte, sau đó dừng bộ đếm thời gian và kiểm tra thời gian trôi qua và tổng số byte đã tải xuống):Đo tốc độ tải xuống bằng 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(); 
} 

Sau đó, tôi chỉ cần chia số byte được truyền theo thời gian đã thực hiện và nó sẽ cho tốc độ tải xuống bằng bps.

Câu hỏi: 1. Phương pháp này có chính xác không? 2. Bạn có biết tốt hơn không?

Cảm ơn rất nhiều.

+0

Chúng theo cách bạn đã thiết lập ngay bây giờ, nó sẽ không chính xác. 'InputStream.read' không được đảm bảo để điền đầy đủ bộ đệm của bạn. Bạn cần kiểm tra giá trị trả về để xem có bao nhiêu 'byte' đã thực sự được đọc. – Jeffrey

+1

@Jeffrey, bạn không đọc mã chi tiết. Tôi không dựa vào read() để lấy số byte. Tôi nhận được nó trực tiếp từ hệ điều hành thông qua hàm getTotalRxBytes(). –

+0

Ahh, tệ lắm. Tôi đã thực sự lướt qua phần đó. Giải pháp bạn có sẽ ít nhiều chính xác. – Jeffrey

Trả lời

4

Có một vài vấn đề có thể ở đây:

  1. Nếu bạn đang tìm kiếm để làm được điều này khi đang bay trên một thiết bị tùy ý (so với trong một khung cảnh phòng thí nghiệm), bạn sẽ cần phải làm theo khuyến cáo Jeffrey, vì các ứng dụng khác có thể tiêu thụ băng thông sẽ được báo cáo bởi getTotalRxBytes().

  2. Tốc độ tải xuống thử nghiệm này từ máy chủ lưu trữ này. Nếu đó là máy chủ, bạn sẽ liên lạc với "những thứ thực", điều đó thật tuyệt. Hoặc, nếu bạn chỉ cần một ý tưởng chung về tốc độ tải xuống thì không sao cả. Nhưng thử nghiệm tốc độ tải xuống từ trang web A và giả sử rằng trang web B sẽ không chính xác, vì trang web A và trang web B có thể không nằm trên cùng một lục địa.

  3. Nếu bạn mong muốn thực hiện điều này, chủ sở hữu máy chủ bạn đang thử nghiệm có thể bị kích thích nhẹ với chi phí băng thông, mục nhập nhật ký quá mức, v.v. Lý tưởng nhất là bạn chỉ thực hiện việc này đối với nội dung bạn sở hữu.

  4. Đối với gói dữ liệu được đo, 200KB có thể kích thích chủ sở hữu thiết bị.

  5. Tất cả các cảnh báo chuẩn về truy cập Internet (ví dụ: máy chủ có thể ngừng hoạt động) và thiết bị di động (ví dụ: người dùng có thể bắt đầu sử dụng WiFi và di chuyển ra khỏi phạm vi, thay đổi đáng kể khả năng tải xuống của bạn).

Tất cả những gì được nói, thực hiện tải xuống là cách duy nhất để đo tốc độ tải xuống.

+0

đối với điểm đầu tiên: "các ứng dụng khác có thể tiêu thụ băng thông sẽ được báo cáo bởi getTotalRxBytes()" nếu ý tưởng là để đo chiều rộng băng tần thì OK sử dụng getTotalRxBytes(), nếu các ứng dụng khác tiêu thụ băng thông mà bạn muốn hãy xem xét tính toán của bạn. – Chiara

1

Sử dụng mã bên dưới. Tôi đã sử dụng nó để đo tốc độ tải xuống. Bạn không cần phải lưu tệp với mục đích đo tốc độ tải xuống. Bạn cũng có thể không cần phải sử dụng OkHttp. Tôi đã sử dụng nó vì nó đã được sử dụng trong dự án của chúng tôi.

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); 
      } 
     } 
    }); 
Các vấn đề liên quan