Statistics of network data usage of android devices

two ways

Classes used:

TrafficStats (statistics of traffic since the device was started)
NetworkStatsManager (network historical data)

1. TrafficStats class

It is to read the text of the file object system type provided by Linux for parsing.
The android.net.TrafficStats class provides a variety of static methods, which can be directly called to obtain, and the return type is long. If the return is equal to -1, it means UNSUPPORTED, and the current device does not support statistics.

TrafficStats can obtain the data traffic and total network traffic consumption of the device (in general, the traffic information under Wi-Fi can also be obtained); the traffic information
corresponding to the uid can be queried, and the uid can be queried through the package name of the application, so it can Query the traffic statistics of an application (without considering shareuid).
Very conveniently, no special permissions are required for its use. On the other hand it has some limitations:

(1) The data flow consumption of the application cannot be obtained.
From the document, only the flow of the specified uid can be obtained, but the consumption under different network types cannot be distinguished. The
indirect method is to monitor the network switch and make a good flow record (but ensure that your application has been alive, and must receive accurate network switching information), basically unavailable.
(2) Unable to obtain traffic consumption within a certain period of time
From the API documentation, function parameters have no time-related information. And the important point is that the TrafficStats class records the traffic statistics since the device restarts. Because of the TrafficStats class, the bottom layer reads /proc/net/xt_qtaguid/stats to analyze the content, and returns the result to the upper layer.

The Android system encapsulates a set of traffic data APIs, which can well manage the traffic usage of the Android system. We can realize the function of managing mobile phone traffic based on these Android APIs.
These APIs are well encapsulated in TrafficStats under the android.net package. The main methods are:

/**
 * static long getMobileRxBytes()//获取通过Mobile连接收到的字节总数,但不包含WiFi 
 * static long getMobileRxPackets()//获取Mobile连接收到的数据包总数 
 * static long getMobileTxBytes()//Mobile发送的总字节数,
 * static long getMobileTxPackets()//Mobile发送的总数据包数 
 * static long getTotalRxBytes()//获取总的接受字节数,包含Mobile和WiFi等 
 * static long getTotalRxPackets()//总的接受数据包数,包含Mobile和WiFi等 
 * static long getTotalTxBytes()//总的发送字节数,包含Mobile和WiFi等 
 * static long getTotalTxPackets()//发送的总数据包数,包含Mobile和WiFi等 
 * static long getUidRxBytes(int uid)//获取某个网络UID的接受字节数 
 * static long getUidTxBytes(int uid) //获取某个网络UID的发送字节数
 */

2、NetworkStatsManager

The NetworkStatsManager class is a newly added class in Android 6.0 (API23), which provides historical statistics of network usage, and especially emphasizes the ability to query statistics within a specified time interval.
The NetworkStatsManager class overcomes the query limitations of TrafficStats, and the statistics are no longer data since the device was restarted. But it also has its own limitations and disadvantages.
(1) Permission restrictions
The use of NetworkStatsManager requires additional permissions, "android.permission.PACKAGE_USAGE_STATS" is a system permission, and users need to be guided to open the application's "apps with the right to view usage" (usage record access permission) permission
 

Take a look at some functions (non-static):
//Query the total traffic statistics of a specified network type within a certain time interval
NetworkStats.BucketquerySummaryForDevice(intnetworkType,StringsubscriberId,longstartTime,longendTime)
//Query a certain uid within a specified network type and time interval Traffic statistics within
NetworkStats.queryDetailsForUid(intnetworkType,StringsubscriberId,longstartTime,longendTime,intuid)
//Query the detailed traffic statistics of the specified network type within a certain time interval (including each uid)
NetworkStats.queryDetails(intnetworkType,StringsubscriberId, longstartTime, longendTime)

request for access

   <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

 User manual authorization

    private boolean hasPermissionToReadNetworkStats() {
       
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
                   return true;
        }
      
        final AppOpsManager appOps = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
        int mode = 0;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
           
            mode = appOps.unsafeCheckOpRaw(AppOpsManager.OPSTR_GET_USAGE_STATS,
                    android.os.Process.myUid(), getPackageName());
        }
      
        if (mode == AppOpsManager.MODE_ALLOWED) {
           
            return true;
        }

        requestReadNetworkStats();
       
        return false;
    }
    // 打开“有权查看使用情况的应用”页面
    private void requestReadNetworkStats() {
       
        Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
        startActivity(intent);
    }

 Statistics usage

NetworkStatsManager networkStatsManager = (NetworkStatsManager) getSystemService(NETWORK_STATS_SERVICE);
NetworkStats.Bucket bucket = null;
// 获取到目前为止设备的Wi-Fi流量统计
bucket = networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_WIFI, "", 0, System.currentTimeMillis());

 Problem encountered: NetworkStats.Bucket bucket is empty 

Reason: I collect the usage of Ethernet, and the SDK does not support this function, so the obtained bucket is empty. The source code is as follows:

public Bucket querySummaryForDevice(int networkType, String subscriberId,
            long startTime, long endTime) throws SecurityException, RemoteException {
        NetworkTemplate template;
        try {
            template = createTemplate(networkType, subscriberId);
        } catch (IllegalArgumentException e) {
            if (DBG) Log.e(TAG, "Cannot create template", e);
            return null;
        }

        return querySummaryForDevice(template, startTime, endTime);
    }
    private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
        final NetworkTemplate template;
        switch (networkType) {
            case ConnectivityManager.TYPE_MOBILE:
                template = subscriberId == null
                        ? NetworkTemplate.buildTemplateMobileWildcard()
                        : NetworkTemplate.buildTemplateMobileAll(subscriberId);
                break;
            case ConnectivityManager.TYPE_WIFI:
                template = NetworkTemplate.buildTemplateWifiWildcard();
                break;
            default:
                throw new IllegalArgumentException("Cannot create template for network type "
                        + networkType + ", subscriberId '"
                        + NetworkIdentity.scrubSubscriberId(subscriberId) + "'.");
        }
        return template;
    }

 The SDK only supports statistics on WiFi and mobile data traffic

Extension method:

frameworks\base\core\java\android\app\usage\NetworkStatsManager.java

Add case:

case ConnectivityManager.TYPE_ETHERNET:
                template = NetworkTemplate.buildTemplateEthernet();
                break;

frameworks\base\core\java\android\net\NetworkTemplate.java

Java gets the current day (today) at 0:00:00:00:00:00

There are two methods, one is to get the timestamp, and the other is to get the date format:

1. date format

Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
Date zero = calendar.getTime();

2. Timestamp


long current = System.currentTimeMillis();
long zero = current/(1000*3600*24)*(1000*3600*24) - TimeZone.getDefault().getRawOffset();

public static void main(String[] args) {
long current=System.currentTimeMillis();//当前时间毫秒数
long zero=current/(1000*3600*24)*(1000*3600*24)-TimeZone.getDefault().getRawOffset();//今天零点零分零秒的毫秒数
long twelve=zero+24*60*60*1000-1;//今天23点59分59秒的毫秒数
long yesterday=System.currentTimeMillis()-24*60*60*1000;//昨天这一时间的毫秒数
System.out.println(new Timestamp(current));//当前时间
System.out.println(new Timestamp(yesterday));//昨天这一时间点
System.out.println(new Timestamp(zero));//今天零点零分零秒
System.out.println(new Timestamp(twelve));//今天23点59分59秒
}

(213 messages) Android statistical traffic data_julie94212's blog-CSDN blog_android statistical traffic

java Get the current day (today) at 0:00:00:00:00 (shuzhiduo.com)

(213 messages) android statistics application traffic NetworkStatsManager_android get traffic usage_Arctic Pine Blog-CSDN Blog 

Guess you like

Origin blog.csdn.net/xiaowang_lj/article/details/128837169