¿Alguien puede explicar cómo funciona TrafficStats en el sistema operativo Android?

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

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

  1. TrafficStats.java es solo un puntero nativo al archivo ac
  2. El archivo c abre dos archivos (ver abajo) y lee sus contenidos
  3. Si cualquiera de los dos contiene un valor numérico, lo escupe nuevamente como el recuento de “bytes utilizados”

Este es 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 verifico su contenido, un archivo no existe y el otro archivo es 0 bytes.

Entonces claramente entendí mal lo que TrafficStats está haciendo. ¿Alguien puede arrojar algo de luz sobre cómo está funcionando es magia?

Gracias por la ayuda.

(aquí está mi bash 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í hay una versión modificada y funcional del código anterior. Éste utiliza RandomAccessFile y no se basa en imports personalizadas, sino que utiliza solo funciones de String incorporadas 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 RandomAccessFile en lugar de File funcionó.

Editar: vea la respuesta de IBoS para el código de trabajo. Cambiando la respuesta aceptada a la suya.