Je travaille sur une application qui télécharge une grande quantité de données. Je souhaite déterminer le taux de transfert du téléchargement, à afficher dans une notification.

  • Un message suggère d'utiliser le WifiInfo qui ne fonctionnera pas pour les données mobiles.
  • Un autre message suggère d'obtenir le type de réseau pour estimer la vitesse.

Je ne suis pas satisfait des réponses dans ces messages, alors je pose à nouveau la question.

J'ai vu des applications qui affichent le taux de transfert de téléchargement, ainsi que des ROM personnalisées telles que Resurrection Remix.

Comment puis-je déterminer le taux de transfert de ces téléchargements?

4
user10655681 20 nov. 2018 à 15:38

3 réponses

Meilleure réponse

Il est possible d'obtenir le montant du trafic transféré en utilisant android.net.TrafficStats. Voici une implémentation de cette idée qui mesure le taux de transfert en amont et en aval. Vous pouvez mesurer le débit du réseau mobile en passant TrafficSpeedMeasurer.TrafficType.MOBILE au constructeur TrafficSpeedMeasurer, sinon l'utilisation de TrafficSpeedMeasurer.TrafficType.ALL entraînera la mesure du trafic général (WiFi / Mobile). De plus, en définissant SHOW_SPEED_IN_BITS = true dans MainActivity, vous pouvez changer l'unité de mesure de la vitesse en bit s par seconde.

MainActivity.java

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private static final boolean SHOW_SPEED_IN_BITS = false;

    private TrafficSpeedMeasurer mTrafficSpeedMeasurer;
    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = findViewById(R.id.connection_class);

        mTrafficSpeedMeasurer = new TrafficSpeedMeasurer(TrafficSpeedMeasurer.TrafficType.ALL);
        mTrafficSpeedMeasurer.startMeasuring();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mTrafficSpeedMeasurer.stopMeasuring();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mTrafficSpeedMeasurer.removeListener(mStreamSpeedListener);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mTrafficSpeedMeasurer.registerListener(mStreamSpeedListener);
    }

    private ITrafficSpeedListener mStreamSpeedListener = new ITrafficSpeedListener() {

        @Override
        public void onTrafficSpeedMeasured(final double upStream, final double downStream) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    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;


public class TrafficSpeedMeasurer {

    private ITrafficSpeedListener mTrafficSpeedListener;
    private SamplingHandler mHandler;

    private TrafficType mTrafficType;
    private long mLastTimeReading;
    private long mPreviousUpStream = -1;
    private long mPreviousDownStream = -1;

    public TrafficSpeedMeasurer(TrafficType trafficType) {
        mTrafficType = trafficType;
        HandlerThread thread = new HandlerThread("ParseThread");
        thread.start();
        mHandler = new SamplingHandler(thread.getLooper());
    }

    public void registerListener(ITrafficSpeedListener iTrafficSpeedListener) {
        mTrafficSpeedListener = iTrafficSpeedListener;
    }

    public void removeListener(ITrafficSpeedListener iTrafficSpeedListener) {
        mTrafficSpeedListener = iTrafficSpeedListener;
    }

    public void startMeasuring() {
        mHandler.startSamplingThread();
        mLastTimeReading = SystemClock.elapsedRealtime();
    }

    public void stopMeasuring() {
        mHandler.stopSamplingThread();
        finalReadTrafficStats();
    }

    private void readTrafficStats() {
        long newBytesUpStream = (mTrafficType == TrafficType.MOBILE ? TrafficStats.getMobileTxBytes() : TrafficStats.getTotalTxBytes()) * 1024;
        long newBytesDownStream = (mTrafficType == TrafficType.MOBILE ? TrafficStats.getMobileRxBytes() : TrafficStats.getTotalRxBytes()) * 1024;

        long byteDiffUpStream = newBytesUpStream - mPreviousUpStream;
        long byteDiffDownStream = newBytesDownStream - mPreviousDownStream;

        synchronized (this) {
            long currentTime = SystemClock.elapsedRealtime();
            double bandwidthUpStream = 0;
            double bandwidthDownStream = 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;
    }

    private void finalReadTrafficStats() {
        readTrafficStats();
        mPreviousUpStream = -1;
        mPreviousDownStream = -1;
    }

    private class SamplingHandler extends Handler {

        private static final long SAMPLE_TIME = 1000;
        private static final int MSG_START = 1;

        private SamplingHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_START:
                    readTrafficStats();
                    sendEmptyMessageDelayed(MSG_START, SAMPLE_TIME);
                    break;
                default:
                    throw new IllegalArgumentException("Unknown what=" + msg.what);
            }
        }

        void startSamplingThread() {
            sendEmptyMessage(SamplingHandler.MSG_START);
        }

        void stopSamplingThread() {
            removeMessages(SamplingHandler.MSG_START);
        }

    }

    public enum TrafficType {
        MOBILE,
        ALL
    }

}

ITrafficSpeedListener.java

public interface ITrafficSpeedListener {

    void onTrafficSpeedMeasured(double upStream, double downStream);
}

Utils.java

import java.util.Locale;

public class Utils {

    private static final long B = 1;
    private static final long KB = B * 1024;
    private static final long MB = KB * 1024;
    private static final long GB = MB * 1024;

    public static String parseSpeed(double bytes, boolean inBits) {
        double value = inBits ? bytes * 8 : bytes;
        if (value < KB) {
            return String.format(Locale.getDefault(), "%.1f " + (inBits ? "b" : "B") + "/s", value);
        } else if (value < MB) {
            return String.format(Locale.getDefault(), "%.1f K" + (inBits ? "b" : "B") + "/s", value / KB);
        } else if (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);
        }
    }

}

.

Résultat visuel

enter image description here

8
aminography 30 nov. 2018 à 09:38

Je parle dans le contexte de votre application car cela facilite la capture de la vitesse en temps réel de vos données téléchargées. Vous n'avez pas besoin de bibliothèques supplémentaires ou d'API sdk.

Vous téléchargez probablement les données par blocs sur le serveur. Alors

A) Vous connaissez la taille des données de chaque paquet
b) Vous connaissez l'heure de début avant d'envoyer le paquet / avant d'envoyer plusieurs paquets
c) Vous connaissez l'heure de fin des paquets xy par la réponse du serveur, par ex. statut 200

Avec cela, vous avez tous les paramètres pour calculer la vitesse de téléchargement

double uploadSpeed = packet.size / (endTime - startTime) // temps * 1000 pour l'avoir en secondes

ÉDITER:

Puisque vous utilisez MultiPart de OkHttp, vous pouvez surveiller la quantité d'octets téléchargés. Suivi de la progression du téléchargement de fichiers en plusieurs parties à l'aide d'OKHTTP. Vous remplaceriez packet.size par le montant téléversé actuel et le endTime serait un intervalle de xy secondes.

0
Murat Karagöz 28 nov. 2018 à 12:07

Ce que vous essayez de déterminer, c'est le taux de transfert des octets téléchargés sur votre client HTTP. Évidemment, cela dépend du client HTTP que vous utilisez.

Il n'y a pas de solution prête à l'emploi qui s'applique à tous les clients HTTP utilisés sur Android. Le SDK Android ne fournit aucune méthode vous permettant de déterminer le taux de transfert d'un téléchargement particulier.

Heureusement, vous utilisez OKHttp et il existe un moyen relativement simple de le faire. Vous allez devoir implémenter un RequestBody personnalisé et observer les octets en cours d'écriture dans le tampon lorsque la requête est en cours.

Il existe une `` recette '' pour faire cela sur le Github OkHttp: https: // github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/Progress.java

Vous pouvez également vous référer à cette question StackOverflow traitant exactement du même sujet: Suivi de la progression du téléchargement de fichiers en plusieurs parties à l'aide d'OKHTTP

Un autre ici: OKHTTP 3 Suivi de la progression de l'importation en plusieurs parties

4
Tim Malseed 28 nov. 2018 à 13:56