有人可以解释一下TrafficStats如何在Android操作系统中发挥其神奇作用?

时间:2010-10-27 00:53:26

标签: android

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

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

  1. TrafficStats.java只是指向c文件的本机指针
  2. c文件打开两个文件(见下文)并读取其内容
  3. 如果其中任何一个包含数值,则会将其作为“使用的字节数”计数
  4. 这是我的挑战......当我通过设备上的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;
     }
    }
    

2 个答案:

答案 0 :(得分:11)

这是上面代码的工作修改版本。这一个使用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;
}

}

答案 1 :(得分:4)

将其更改为RandomAccessFile而不是File。

编辑:请参阅IBoS对工作代码的回答。改变他接受的答案。