Track iPhone data usage

Hello I am trying to to track phone data usage (both Wi-Fi and Cellular). I am using the following code to get device data usage https://stackoverflow.com/questions/25888272/track-cellular-data-usage-using-swift as I understand it is the only way to get it without having to use private API's.

The problem is I can't figure out why the usage seems to be high compared to other apps that track data usage. I was wondering if anyone could provide documentation on the interfaces used on the code from stack overflow or how to get access to more detailed data usage.

What I am doing with the code from stack overflow is take the total Wi-Fi and cellular usage and compare it with the new one every 15 minutes to store a data usage event.

public func calculateTempDataUsageEvent() -> Void {
        
        let totalWifiDataUsage = Int64(wifiNetworkInfo.getWifiDataUsage())
        let totalCellularDataUsage = Int64(cellularNetworkInfo.getCellularDataUsage())
        let firstTimestamp = Date().millisecondsSince1970

        let tempDataUsageEvent : TempDataUsageEvent
        let phoneDataUsage : PhoneDataUsage
        
        let realm = try! Realm()
        
        //Check if realm for PhoneDataUsage is empty, if this is the case store initial phone data usage so we can keep track of it's changes
        if(realm.objects(PhoneDataUsage.self).isEmpty) {

            phoneDataUsage = PhoneDataUsage(timestamp: firstTimestamp, offsetMinutes: Int32(TimeZone.current.secondsFromGMT() * 1000), totalCellularDataUsage: totalCellularDataUsage, totalWifiDataUsage: totalWifiDataUsage)
            
            do {
                try realm.write {
                    realm.add(phoneDataUsage)
                    print("Stored Phone Data Usage in Realm")
                }
                
            } catch let error as NSError {
                print("Failed to store Phone Data Usage in Realm with \(error)")
            }
            
            return
            
        } else {
            
            //TODO: Handle this unwrap in a better way
            let lastPhoneDataUsage : PhoneDataUsage = getLastPhoneDataUsage()!
            let tempEndTimestamp : Int64 = Date().millisecondsSince1970
            let tempEventDuration : Int32 = Int32(tempEndTimestamp - lastPhoneDataUsage.timestamp)
            let tempOffsetMinutes : Int32 = Int32(TimeZone.current.secondsFromGMT() * 1000)
            
            //Handle phone restart
            //TODO: maybe need to know phone uptime possible issue time zone change? https://developer.apple.com/forums/thread/101874
            
            var tempEventWifiDataUsage : Int64
            var tempEventCellularDataUsage : Int64
            
            if(totalWifiDataUsage < lastPhoneDataUsage.totalWifiDataUsage || totalCellularDataUsage < lastPhoneDataUsage.totalCellularDataUsage) {

                if(totalWifiDataUsage < lastPhoneDataUsage.totalWifiDataUsage) {
                    tempEventWifiDataUsage = totalWifiDataUsage
                } else {
                    tempEventWifiDataUsage = totalWifiDataUsage - lastPhoneDataUsage.totalWifiDataUsage
                }
                
                if(totalCellularDataUsage < lastPhoneDataUsage.totalCellularDataUsage) {
                    tempEventCellularDataUsage = totalCellularDataUsage
                } else {
                    tempEventCellularDataUsage = totalCellularDataUsage - lastPhoneDataUsage.totalCellularDataUsage
                }
                
                phoneDataUsage = PhoneDataUsage(timestamp: tempEndTimestamp, offsetMinutes: tempOffsetMinutes, totalCellularDataUsage: totalCellularDataUsage, totalWifiDataUsage: totalWifiDataUsage)
                
                tempDataUsageEvent = TempDataUsageEvent(startTimestamp: lastPhoneDataUsage.timestamp, endTimestamp: tempEndTimestamp, offsetMinutes: tempOffsetMinutes, eventDuration: tempEventDuration, eventCellularDataUsage: tempEventCellularDataUsage, eventWifiDataUsage: tempEventWifiDataUsage, sendToBackend: true)
         
            } else {
                
                //Default case where phone has not rebooted and API not reset
                tempEventWifiDataUsage = totalWifiDataUsage - lastPhoneDataUsage.totalWifiDataUsage
                tempEventCellularDataUsage = totalCellularDataUsage - lastPhoneDataUsage.totalCellularDataUsage
                
                phoneDataUsage = PhoneDataUsage(timestamp: tempEndTimestamp, offsetMinutes: tempOffsetMinutes, totalCellularDataUsage: totalCellularDataUsage, totalWifiDataUsage: totalWifiDataUsage)
                
                tempDataUsageEvent = TempDataUsageEvent(startTimestamp: lastPhoneDataUsage.timestamp, endTimestamp: tempEndTimestamp, offsetMinutes: tempOffsetMinutes, eventDuration: tempEventDuration, eventCellularDataUsage: tempEventCellularDataUsage, eventWifiDataUsage: tempEventWifiDataUsage, sendToBackend: true)
            }
            
        }
        
        //Write to Realm
        do {
            try realm.write {
                realm.add(tempDataUsageEvent)
                realm.add(phoneDataUsage)
                print("Stored Temp Data Usage event in Realm")
            }
            
        } catch let error as NSError {
            print("Failed to store Temp Data Usage event in Realm with \(error)")
        }
        
       

I called temporal data usage as I then use a 'legacy' table to store all usage and temporal data usage is deleted. I do this to know what is not on backend. Finally I add the values from the events and sum them to show data usage.

public func getTempDataUsageEventSum() -> (wifiDataUsageSum : Int64, cellularDataUsageSum: Int64) {
        /**
        Returns Wi-Fi/Cell total data usage from TempDataUsageEvent Realm, 0 if empty
         */
        
        let realm = try! Realm()
        
        let totalTempWifiDataUsage: Int64 = realm.objects(TempDataUsageEvent.self).sum(ofProperty: "eventWifiDataUsage")
        let totalTempCellularDataUsage : Int64 = realm.objects(TempDataUsageEvent.self).sum(ofProperty: "eventCellularDataUsage")
        
        return (totalTempWifiDataUsage, totalTempCellularDataUsage)
    }

 it is the only way to get it without having to use private API's.

Actually that code does use a bit of private or undocumented API: the interface name prefixes it looks for ("pdp_ip" and "en") aren’t official API. They probably won’t change any time soon, but there’s no actual guarantee they won’t.

provide documentation on the interfaces used on the code

It’s using the old BSD function getifaddrs(3). In a command prompt, enter the command man getifaddrs to get started.

take the total Wi-Fi and cellular usage and compare it with the new one every 15 minutes

Here’s a big gotcha with that API: the returned byte count values are unsigned 32-bit integers, not 64 bits as the wrapper code suggests. So they can wrap around zero fairly often depending on data usage, and I don’t see that your code or the wrapper code handles this. With a sampling interval of 15 minutes there’s a risk of wrapping more than once between samples, which would make it impossible to track accurately. You can make this work if your sampling interval is guaranteed to be less than the time required for a single wraparound (that is, the minimum time needed to transfer 4GB of data). But if (for example) your app is waking from the background to take a sample while other apps run, then you may have trouble meeting this timing requirement.

Track iPhone data usage
 
 
Q