Android流量监控

**

一、需求:

**

获得设备里程序耗费流量的具体情况。

二、代码实现:

1.首先是赋予权限:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

2.自定义个bean对象,封装拿到的内容。

/**
 * Created by Jim斌 on 2017/8/27.
 */
public class TrafficInfo {
    private String Packagename;
    private String Appname;
    private int Icon;
    private long Rx;
    private long Tx;

    public long getRx() {
        return Rx;
    }

    public void setRx(long rx) {
        Rx = rx;
    }

    public long getTx() {
        return Tx;
    }

    public void setTx(long tx) {
        Tx = tx;
    }

    public String getPackagename() {
        return Packagename;
    }

    public void setPackagename(String packagename) {
        Packagename = packagename;
    }

    public String getAppname() {
        return Appname;
    }

    public void setAppname(String appname) {
        Appname = appname;
    }

    public int getIcon() {
        return Icon;
    }

    public void setIcon(int icon) {
        Icon = icon;
    }

}

3.下面的工具类为流量监控的代码实现

/**
 * Created by Jim斌 on 2017/8/29.
 */

public class FlowUtil {
    private static long Rx;//上传的流量
    private static long Tx;//下载的流量
    /**
     * 通过uid查询文件夹中的数据
     *
     * @param localUid
     * @return
     */
    public static Long getTotalBytesManual(int localUid) {
//        Log.e("BytesManual*****", "localUid:" + localUid);
        File dir = new File("/proc/uid_stat/");
        String[] children = dir.list();
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < children.length; i++) {
            stringBuffer.append(children[i]);
            stringBuffer.append("   ");
        }
        if (!Arrays.asList(children).contains(String.valueOf(localUid))) {
            return 0L;
        }
        File uidFileDir = new File("/proc/uid_stat/" + String.valueOf(localUid));
        File uidActualFileReceived = new File(uidFileDir, "tcp_rcv");
        File uidActualFileSent = new File(uidFileDir, "tcp_snd");
        String textReceived = "0";
        String textSent = "0";
        try {
            BufferedReader brReceived = new BufferedReader(new FileReader(uidActualFileReceived));
            BufferedReader brSent = new BufferedReader(new FileReader(uidActualFileSent));
            String receivedLine;
            String sentLine;

            if ((receivedLine = brReceived.readLine()) != null) {
                textReceived = receivedLine;
            }
            if ((sentLine = brSent.readLine()) != null) {
                textSent = sentLine;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        Rx=Long.valueOf(textReceived).longValue();
        Tx=Long.valueOf(textSent).longValue();
//        Log.d(TAG, "上传: "+Long.valueOf(textReceived).longValue()+"下载:"+Long.valueOf(textSent).longValue());
        return Long.valueOf(textReceived).longValue() + Long.valueOf(textSent).longValue();
    }

    /**
     * 返回所有的有互联网访问权限的应用程序的流量信息。
     * TrafficInfo 为一个Bean 模型类。使用的时候可以自定义一个、。
     *
     * @return
     */
    public static List getTrafficInfo(Context context) {
        //获取到配置权限信息的应用程序
        PackageManager pms = context.getPackageManager();
        List packinfos = pms
                .getInstalledPackages(PackageManager.GET_PERMISSIONS);
        //存放具有Internet权限信息的应用
        List trafficInfos = new ArrayList();
        for (PackageInfo packinfo : packinfos) {
            //获取该应用的所有权限信息
            String[] permissions = packinfo.requestedPermissions;
            if (permissions != null && permissions.length > 0) {
                for (String permission : permissions) {
                    //筛选出具有Internet权限的应用程序
                    if ("android.permission.INTERNET".equals(permission)) {
                        //用于封装具有Internet权限的应用程序信息
                        TrafficInfo trafficInfo = new TrafficInfo();
                        //封装应用信息
                        trafficInfo.setPackagename(packinfo.packageName);
//                        trafficInfo.setIcon(packinfo.applicationInfo.loadIcon(pms));//设置图标,用到时再改
                        trafficInfo.setAppname(packinfo.applicationInfo.loadLabel(pms).toString());
                        //获取到应用的uid(user id)
                        int uid = packinfo.applicationInfo.uid;
                        //TrafficStats对象通过应用的uid来获取应用的下载、上传流量信息

                        //发送的 上传的流量byte
                        trafficInfo.setRx(TrafficStats.getUidRxBytes(uid));
                        //下载的流量 byte
                        trafficInfo.setTx(TrafficStats.getUidTxBytes(uid));//不晓得为什么这两个为空
                        trafficInfos.add(trafficInfo);
                        if (getTotalBytesManual(uid) != 0) {
                            Log.d(TAG, "getTrafficInfo: "+"\n" +
                                    "包名:            " + trafficInfo.getPackagename() +"\n"+
                                    "APP名:           " + trafficInfo.getAppname() +"\n"+
                                    "uid:              " + uid +"\n"+
                                    "上传的流量  byte: " + Rx +"\n"+
                                    "下载的流量  byte: " + Tx +"\n"+
                                    "消耗总流量  byte:" + getTotalBytesManual(uid));
                        }
                        trafficInfo = null;
                        break;
                    }
                }
            }
        }
        return trafficInfos;
    }

}

三、总结:

Android其实封装了一个流量控制类TrafficStats,本来以为直接用就可以,但是在用的过程中遇到了一个

。这个类里面的getUidRxBytes(int uid) 和 getUidTxBytes(int uid)好像没用….

getUidRxBytes(int uid) 和 getUidTxBytes(int uid)这两个方法时一直返回0,无论什么应用都说流量消耗为0,这明显是错误的。
一开始以为这两个方法只是获取2G或者3G消耗的流量,而我的手机信号显示的是4G,尝试了一下在网络上搜索“Android获取4G流量消耗”,毛都没收到,接着看到了日志里getMobileTxBytes()返回的数据不为空,猜应该是不分3G、4G的,可能是我的获取方法没起作用或获取错。
查了Android的API文档,确认方法调用时正确的,调试了下,发现方法返回的仍旧是空。很迷,后来在网上查到资料,通过访问“/proc/uid_stat/”这个文件可以获取到消耗的流量,就是上面演示的代码。
至于TrafficStats类里面拿两个方法为什么不能用我现在还没搞懂。

四、参考资料

http://dev.10086.cn/cmdn/bbs/thread-49242-1-1.html
http://www.cnblogs.com/0616–ataozhijia/p/6628462.html

你可能感兴趣的:(android,流量,android)