¿Puede alguien explicar cómo TrafficStats funciona su magia en el sistema operativo Android?

He escrito una pequeña aplicación Android para comprobar el uso de datos, por desgracia se basa en gran medida en android.net.TrafficStats que se introdujo con Froyo (Android 2.2).

Estoy intentando volver a portar esta clase para mis usuarios que no son Froyo, y lo que puedo determinar desde la fuente de Android es:

  1. TrafficStats.java es sólo un puntero nativo del archivo AC
  2. El archivo c abre dos archivos (ver más abajo) y lee su contenido
  3. Si contiene un valor numérico, lo vuelve a escupir como el recuento de "bytes usados"

Aquí está mi desafío … cuando llamo a TrafficStats a través de la API en mi dispositivo, obtengo una lectura (por ejemplo, 1113853 bytes). Cuando abro los dos archivos y comprobar su contenido, un archivo no existe y el otro archivo es 0 bytes.

Así que claramente entendí mal lo que TrafficStats está haciendo. ¿Puede alguien arrojar algo de luz sobre cómo funciona su magia?

Gracias por la ayuda.

(Aquí está mi intento de portar el archivo c a java)

package com.suttco.net; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import com.suttco.IOUtils; import com.suttco.StringUtils; import android.util.Log; public class TrafficStatsFile { private static final String mobileRxFile_1 = "/sys/class/net/rmnet0/statistics/rx_bytes"; private static final String mobileRxFile_2 = "/sys/class/net/ppp0/statistics/rx_bytes"; private static final String mobileTxFile_1 = "/sys/class/net/rmnet0/statistics/tx_bytes"; private static final String mobileTxFile_2 = "/sys/class/net/ppp0/statistics/tx_bytes"; private static final String LOGGING_TAG = TrafficStatsFile.class.getSimpleName(); public long getMobileRxBytes() { return tryBoth(mobileRxFile_1, mobileRxFile_2); } public long getMobileTxBytes() { return tryBoth(mobileTxFile_1, mobileTxFile_2); } // Return the number from the first file which exists and contains data private static long tryBoth(String a, String b) { long num = readNumber(a); return num >= 0 ? num : readNumber(b); } // Returns an ASCII decimal number read from the specified file, -1 on error. private static long readNumber(String filename) { File f = new File(filename); if(f.exists()) { if(f.canRead()) { try { Log.d(LOGGING_TAG, "f.length() = " + f.length()); String contents = IOUtils.readFileAsString(f); if(StringUtils.IsNotNullOrEmpty(contents)) { try { return Long.parseLong(contents); } catch(NumberFormatException nfex) { Log.w(LOGGING_TAG, "File contents are not numeric: " + filename); } } else { Log.w(LOGGING_TAG, "File contents are empty: " + filename); } } catch (FileNotFoundException fnfex) { Log.w(LOGGING_TAG, "File not found: " + filename, fnfex); } catch(IOException ioex) { Log.w(LOGGING_TAG, "IOException: " + filename, ioex); } } else { Log.w(LOGGING_TAG, "Unable to read file: " + filename); } } else { Log.w(LOGGING_TAG, "File does not exist: " + filename); } return -1; } } 

Aquí está una versión de trabajo, modificada del código anterior. Éste está utilizando RandomAccessFile y no confía en las imports encargo pero utiliza solamente las funciones incorporadas de la String con sus Exceptions .

 import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import android.util.Log; public class TrafficStatsFile { private static final String mobileRxFile_1 = "/sys/class/net/rmnet0/statistics/rx_bytes"; private static final String mobileRxFile_2 = "/sys/class/net/ppp0/statistics/rx_bytes"; private static final String mobileTxFile_1 = "/sys/class/net/rmnet0/statistics/tx_bytes"; private static final String mobileTxFile_2 = "/sys/class/net/ppp0/statistics/tx_bytes"; private static final String LOGGING_TAG = TrafficStatsFile.class.getSimpleName(); public long getMobileRxBytes() { return tryBoth(mobileRxFile_1, mobileRxFile_2); } public long getMobileTxBytes() { return tryBoth(mobileTxFile_1, mobileTxFile_2); } // Return the number from the first file which exists and contains data private static long tryBoth(String a, String b) { long num = readNumber(a); return num >= 0 ? num : readNumber(b); } // Returns an ASCII decimal number read from the specified file, -1 on error. private static long readNumber(String filename) { try { RandomAccessFile f = new RandomAccessFile(filename, "r"); try { Log.d(LOGGING_TAG, "f.length() = " + f.length()); String contents = f.readLine(); if(!contents.isEmpty() && contents!=null) { try { return Long.parseLong(contents); } catch(NumberFormatException nfex) { Log.w(LOGGING_TAG, "File contents are not numeric: " + filename); } } else { Log.w(LOGGING_TAG, "File contents are empty: " + filename); } } catch (FileNotFoundException fnfex) { Log.w(LOGGING_TAG, "File not found: " + filename, fnfex); } catch(IOException ioex) { Log.w(LOGGING_TAG, "IOException: " + filename, ioex); } }catch(FileNotFoundException ffe){ Log.w(LOGGING_TAG, "File not found: " + filename, ffe); } return -1; } } 

Cambiarlo a un archivo RandomAccessFile en lugar de a File.

Editar: Véase la respuesta de IBoS para el código de trabajo. Cambiar la respuesta aceptada a la suya.

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.