【问题标题】:Can someone explain how TrafficStats works its magic in the Android OS?有人能解释一下 TrafficStats 如何在 Android 操作系统中发挥它的魔力吗?
【发布时间】:2010-10-27 00:53:26
【问题描述】:

我编写了一个不错的小 Android 应用程序来检查数据使用情况,不幸的是它严重依赖于 Froyo (Android 2.2) 引入的 android.net.TrafficStats。

我正在尝试为我的非 Froyo 用户反向移植这个类,我可以从 Android source 确定的是:

  1. TrafficStats.java 只是一个指向 c 文件的本地指针
  2. c 文件打开两个文件(见下文)并读取它们的内容
  3. 如果其中任何一个包含数值,它会将其作为“使用的字节数”计数返回

这是我的挑战...当我通过设备上的 API 调用 TrafficStats 时,我得到一个读数(例如 1113853 字节)。当我打开这两个文件并检查它们的内容时,一个文件不存在,另一个文件为 0 字节。

很明显,我误解了 TrafficStats 在做什么。任何人都可以阐明它是如何工作的吗?

感谢您的帮助。

(这是我将c文件移植到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;
 }
}

【问题讨论】:

标签: android


【解决方案1】:

这是上面代码的有效修改版本。这个使用RandomAccessFile,不依赖于自定义imports,而是仅使用内置的String函数和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;
}

}

【讨论】:

  • 我的设备中没有以下目录:rmnet0、ppp0、rmnet0 和 ppp0。我正在使用三星 SM-T111。是否依赖于该设备?
【解决方案2】:

将其更改为 RandomAccessFile 而不是 File 有效。

编辑:查看 IBoS 对工作代码的回答。将接受的答案更改为他的。

【讨论】:

    猜你喜欢
    • 2016-12-02
    • 2017-11-05
    • 1970-01-01
    • 1970-01-01
    • 2012-01-11
    • 1970-01-01
    • 1970-01-01
    • 2016-06-13
    • 2021-10-04
    相关资源
    最近更新 更多