How To Detect Upload/download Transfer Rate In Android?
Solution 1:
It is feasible to obtain the transferred traffic amount using android.net.TrafficStats
. Here is an implementation of this idea which measures the up-stream and down-stream transfer rate. You can measure the rate of mobile network by passing TrafficSpeedMeasurer.TrafficType.MOBILE
to the TrafficSpeedMeasurer
constructor, otherwise using TrafficSpeedMeasurer.TrafficType.ALL
will result in measuring general traffic (WiFi/Mobile). Also by setting SHOW_SPEED_IN_BITS = true
in MainActivity
you can change the unit of speed measuring to bit
s per second.
MainActivity.java
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
publicclassMainActivityextendsAppCompatActivity {
privatestatic final booleanSHOW_SPEED_IN_BITS = false;
privateTrafficSpeedMeasurer mTrafficSpeedMeasurer;
privateTextView mTextView;
@OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = findViewById(R.id.connection_class);
mTrafficSpeedMeasurer = newTrafficSpeedMeasurer(TrafficSpeedMeasurer.TrafficType.ALL);
mTrafficSpeedMeasurer.startMeasuring();
}
@OverrideprotectedvoidonDestroy() {
super.onDestroy();
mTrafficSpeedMeasurer.stopMeasuring();
}
@OverrideprotectedvoidonPause() {
super.onPause();
mTrafficSpeedMeasurer.removeListener(mStreamSpeedListener);
}
@OverrideprotectedvoidonResume() {
super.onResume();
mTrafficSpeedMeasurer.registerListener(mStreamSpeedListener);
}
private ITrafficSpeedListener mStreamSpeedListener = newITrafficSpeedListener() {
@OverridepublicvoidonTrafficSpeedMeasured(final double upStream, final double downStream) {
runOnUiThread(newRunnable() {
@Overridepublicvoidrun() {
String upStreamSpeed = Utils.parseSpeed(upStream, SHOW_SPEED_IN_BITS);
String downStreamSpeed = Utils.parseSpeed(downStream, SHOW_SPEED_IN_BITS);
mTextView.setText("Up Stream Speed: " + upStreamSpeed + "\n" + "Down Stream Speed: " + downStreamSpeed);
}
});
}
};
}
TrafficSpeedMeasurer.java
import android.net.TrafficStats;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
publicclassTrafficSpeedMeasurer {
private ITrafficSpeedListener mTrafficSpeedListener;
private SamplingHandler mHandler;
private TrafficType mTrafficType;
privatelong mLastTimeReading;
privatelongmPreviousUpStream= -1;
privatelongmPreviousDownStream= -1;
publicTrafficSpeedMeasurer(TrafficType trafficType) {
mTrafficType = trafficType;
HandlerThreadthread=newHandlerThread("ParseThread");
thread.start();
mHandler = newSamplingHandler(thread.getLooper());
}
publicvoidregisterListener(ITrafficSpeedListener iTrafficSpeedListener) {
mTrafficSpeedListener = iTrafficSpeedListener;
}
publicvoidremoveListener() {
mTrafficSpeedListener = null;
}
publicvoidstartMeasuring() {
mHandler.startSamplingThread();
mLastTimeReading = SystemClock.elapsedRealtime();
}
publicvoidstopMeasuring() {
mHandler.stopSamplingThread();
finalReadTrafficStats();
}
privatevoidreadTrafficStats() {
longnewBytesUpStream= (mTrafficType == TrafficType.MOBILE ? TrafficStats.getMobileTxBytes() : TrafficStats.getTotalTxBytes()) * 1024;
longnewBytesDownStream= (mTrafficType == TrafficType.MOBILE ? TrafficStats.getMobileRxBytes() : TrafficStats.getTotalRxBytes()) * 1024;
longbyteDiffUpStream= newBytesUpStream - mPreviousUpStream;
longbyteDiffDownStream= newBytesDownStream - mPreviousDownStream;
synchronized (this) {
longcurrentTime= SystemClock.elapsedRealtime();
doublebandwidthUpStream=0;
doublebandwidthDownStream=0;
if (mPreviousUpStream >= 0) {
bandwidthUpStream = (byteDiffUpStream) * 1.0 / (currentTime - mLastTimeReading);
}
if (mPreviousDownStream >= 0) {
bandwidthDownStream = (byteDiffDownStream) * 1.0 / (currentTime - mLastTimeReading);
}
if (mTrafficSpeedListener != null) {
mTrafficSpeedListener.onTrafficSpeedMeasured(bandwidthUpStream, bandwidthDownStream);
}
mLastTimeReading = currentTime;
}
mPreviousDownStream = newBytesDownStream;
mPreviousUpStream = newBytesUpStream;
}
privatevoidfinalReadTrafficStats() {
readTrafficStats();
mPreviousUpStream = -1;
mPreviousDownStream = -1;
}
privateclassSamplingHandlerextendsHandler {
privatestaticfinallongSAMPLE_TIME=1000;
privatestaticfinalintMSG_START=1;
privateSamplingHandler(Looper looper) {
super(looper);
}
@OverridepublicvoidhandleMessage(Message msg) {
switch (msg.what) {
case MSG_START:
readTrafficStats();
sendEmptyMessageDelayed(MSG_START, SAMPLE_TIME);
break;
default:
thrownewIllegalArgumentException("Unknown what=" + msg.what);
}
}
voidstartSamplingThread() {
sendEmptyMessage(SamplingHandler.MSG_START);
}
voidstopSamplingThread() {
removeMessages(SamplingHandler.MSG_START);
}
}
publicenumTrafficType {
MOBILE,
ALL
}
}
ITrafficSpeedListener.java
publicinterfaceITrafficSpeedListener {
voidonTrafficSpeedMeasured(double upStream, double downStream);
}
Utils.java
import java.util.Locale;
publicclassUtils {
privatestaticfinallongB=1;
privatestaticfinallongKB= B * 1024;
privatestaticfinallongMB= KB * 1024;
privatestaticfinallongGB= MB * 1024;
publicstatic String parseSpeed(double bytes, boolean inBits) {
doublevalue= inBits ? bytes * 8 : bytes;
if (value < KB) {
return String.format(Locale.getDefault(), "%.1f " + (inBits ? "b" : "B") + "/s", value);
} elseif (value < MB) {
return String.format(Locale.getDefault(), "%.1f K" + (inBits ? "b" : "B") + "/s", value / KB);
} elseif (value < GB) {
return String.format(Locale.getDefault(), "%.1f M" + (inBits ? "b" : "B") + "/s", value / MB);
} else {
return String.format(Locale.getDefault(), "%.2f G" + (inBits ? "b" : "B") + "/s", value / GB);
}
}
}
. Visual Result
Solution 2:
What you're trying to determine is the transfer rate of the bytes being uploaded over your HTTP Client. Obviously, this depends on the HTTP client you're using.
There's no out-of-the-box solution which applies to all HTTP clients used on Android. The Android SDK does not provide any methods for you to determine the transfer rate of a particular upload.
Fortunately, you're using OKHttp and there is a relatively straight-forward way to do this. You're going to have to implement a custom RequestBody
, and observe the bytes being written to the buffer when the request is in flight.
There's a 'recipe' for doing this on the OkHttp Github: https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/Progress.java
You could also refer to this StackOverflow question dealing with the exact same topic: Tracking progress of multipart file upload using OKHTTP
Another here: OKHTTP 3 Tracking Multipart upload progress
Solution 3:
I am talking in the context of your app since this makes it easier to capture the real time speed of your uploaded data. You don't need any extra libraries or sdk api's.
You are presumably uploading the data in chunks to the server. So
a) You know the data size of each packet b) You know the start time before sending the packet / before sending multiple packets c) You know the end time of xy packets by the server response e.g. status 200
With that you have all parameters to calculate the upload speed
double uploadSpeed = packet.size / (endTime - startTime)
// time * 1000 to have it in seconds
EDIT:
Since you are using MultiPart
from OkHttp
you can monitor the amount of bytes uploaded. Tracking progress of multipart file upload using OKHTTP. You would replace packet.size
with the current uploaded amount and the endTime
would be an interval of xy seconds.
Post a Comment for "How To Detect Upload/download Transfer Rate In Android?"