iPhone डेटा उपयोग ट्रैकिंग / निगरानी


136

मैंने इस विषय पर खोज की है, लेकिन बहुत कम विवरण मिले जो मददगार थे। इन विवरणों के साथ मैंने कुछ कोड पकाने की कोशिश की है।

नोट: कृपया इस पोस्ट में साझा किए गए विवरण की तुलना DUPLICATE के रूप में चिह्नित करने से पहले अन्य पदों के साथ करें, न कि केवल विषय द्वारा।

- (NSArray *)getDataCountersForType:(int)type {
    BOOL success;
    struct ifaddrs *addrs = nil;
    const struct ifaddrs *cursor = nil;
    const struct sockaddr_dl *dlAddr = nil;
    const struct if_data *networkStatisc = nil; 

    int dataSent = 0;
    int dataReceived = 0;

    success = getifaddrs(&addrs) == 0;
    if (success) {
        cursor = addrs;
        while (cursor != NULL) {
            if (cursor->ifa_addr->sa_family == AF_LINK) {
                dlAddr = (const struct sockaddr_dl *) cursor->ifa_addr;
                networkStatisc = (const struct if_data *) cursor->ifa_data;

                if (type == WiFi) {
                    dataSent += networkStatisc->ifi_opackets;
                    dataReceived += networkStatisc->ifi_ipackets;   
                }
                else if (type == WWAN) {
                    dataSent += networkStatisc->ifi_obytes;
                    dataReceived += networkStatisc->ifi_ibytes; 
                }
            }
            cursor = cursor->ifa_next;
        }
        freeifaddrs(addrs);
    }       
    return [NSArray arrayWithObjects:[NSNumber numberWithInt:dataSent], [NSNumber numberWithInt:dataReceived], nil];    
}

यह कोड एक iPhone डिवाइस के इंटरनेट उपयोग की जानकारी एकत्र करता है (और अकेले मेरा आवेदन नहीं)।

अब, यदि मैं वाईफाई के माध्यम से या 3 जी के माध्यम से इंटरनेट का उपयोग करता हूं, तो मुझे केवल ifi_obytes(भेजे गए) और ifi_ibytes(प्राप्त) में डेटा (बाइट्स) मिलता है, लेकिन मुझे लगता है कि मुझे वाईफाई उपयोग में ifi_opacketsऔर प्राप्त करना चाहिए ifi_ipackets

इसके अलावा जोड़ने के लिए है कि अगर मैं एक WiFi नेटवर्क से कनेक्ट हूँ, लेकिन इंटरनेट का उपयोग नहीं कर रहा हूँ, मैं अभी भी मूल्य में जुड़ती चाहता था ifi_obytesऔर ifi_ibytes

हो सकता है कि मैं कार्यान्वयन या समझ में गलत हूं। मेरी मदद करने के लिए किसी की जरूरत है।


संपादित करें: इसके बजाय AF_LINKमैंने कोशिश की AF_INET( sockaddr_inइसके बजाय sockaddr_dl)। इससे एप्लिकेशन क्रैश हो जाता है।

जवाबों:


175

बात यह है कि pdp_ip0इंटरफेस में से एक है, सभी इंटरफेस विभिन्न कार्यों, ध्वनि मेल, सामान्य नेटवर्किंग इंटरफ़ेस के लिए समर्पित pdpXXXहैं WWAN

मैंने Apple फोरम में पढ़ा है कि: OS नेटवर्क के आंकड़ों को प्रोसेस-बाय-प्रोसेस आधार पर नहीं रखता है। जैसे, इस समस्या का कोई सटीक समाधान नहीं है। हालाँकि, आप प्रत्येक नेटवर्क इंटरफ़ेस के लिए नेटवर्क आँकड़े प्राप्त कर सकते हैं।

सामान्य तौर en0पर आपका Wi-Fiइंटरफ़ेस है और pdp_ip0आपका WWANइंटरफ़ेस है।

विशेष तिथि के बाद से, सूचना वाईफाई / सेलुलर नेटवर्क डेटा प्राप्त करने का कोई अच्छा तरीका नहीं है!

डेटा सांख्यिकीय ( ifa_data->ifi_obytesऔर ifa_data->ifi_ibytes) पिछले डिवाइस रिबूट से संग्रहीत किए जाते हैं।

मैं क्यों नहीं पता है, लेकिन ifi_opacketsऔर ifi_ipacketsदिखाया जाता है बस के लिए lo0(मैं अपने मुख्य इंटरफ़ेस लगता है)।

हाँ। फिर डिवाइस के माध्यम से जुड़ा हुआ हैWiFi और इंटरनेट if_iobytesमूल्यों का उपयोग नहीं करता भी आते हैं क्योंकि यह विधि नेटवर्क बाइट्स एक्सचेंज प्रदान करती है और न केवल इंटरनेट।

#include <net/if.h>
#include <ifaddrs.h>

static NSString *const DataCounterKeyWWANSent = @"WWANSent";
static NSString *const DataCounterKeyWWANReceived = @"WWANReceived";
static NSString *const DataCounterKeyWiFiSent = @"WiFiSent";
static NSString *const DataCounterKeyWiFiReceived = @"WiFiReceived";

NSDictionary *DataCounters()
{
    struct ifaddrs *addrs;
    const struct ifaddrs *cursor;

    u_int32_t WiFiSent = 0;
    u_int32_t WiFiReceived = 0;
    u_int32_t WWANSent = 0;
    u_int32_t WWANReceived = 0;

    if (getifaddrs(&addrs) == 0)
    {
        cursor = addrs;
        while (cursor != NULL)
        {
            if (cursor->ifa_addr->sa_family == AF_LINK)
            {
#ifdef DEBUG
                const struct if_data *ifa_data = (struct if_data *)cursor->ifa_data;
                if (ifa_data != NULL)
                {
                    NSLog(@"Interface name %s: sent %tu received %tu",cursor->ifa_name,ifa_data->ifi_obytes,ifa_data->ifi_ibytes);
                }
#endif

                // name of interfaces:
                // en0 is WiFi
                // pdp_ip0 is WWAN
                NSString *name = @(cursor->ifa_name);
                if ([name hasPrefix:@"en"])
                {
                    const struct if_data *ifa_data = (struct if_data *)cursor->ifa_data;
                    if (ifa_data != NULL)
                    {
                        WiFiSent += ifa_data->ifi_obytes;
                        WiFiReceived += ifa_data->ifi_ibytes;
                    }
                }

                if ([name hasPrefix:@"pdp_ip"])
                {
                    const struct if_data *ifa_data = (struct if_data *)cursor->ifa_data;
                    if (ifa_data != NULL)
                    {
                        WWANSent += ifa_data->ifi_obytes;
                        WWANReceived += ifa_data->ifi_ibytes;
                    }
                }
            }

            cursor = cursor->ifa_next;
        }

        freeifaddrs(addrs);
    }

    return @{DataCounterKeyWiFiSent : @(WiFiSent),
             DataCounterKeyWiFiReceived : @(WiFiReceived),
             DataCounterKeyWWANSent : @(WWANSent),
             DataCounterKeyWWANReceived : @(WWANReceived)};
}

बेहतर कॉपी / पेस्ट समर्थन!


1
बहुत बहुत धन्यवाद। इस कोड ने अद्भुत काम किया। सामान को समझाने के लिए भी धन्यवाद।
साहिल खन्ना

20
आपको इस लाइब्रेरी को आयात करने की आवश्यकता है: #include <arpa / inet.h> #include <net / if.h> #include <ifaddrs.h> #include <net / if_dl.it>
user982705

9
क्या इस कोड के साथ आईओएस एप्लिकेशन के अनुसार डेटा ट्रैफ़िक ट्रैक करना संभव है?
fvisticot

2
@ मैट: वह समाधान जो मैंने एंटरप्राइज़ क्लाइंट के लिए डिज़ाइन किया है और AppStore पर तैनात नहीं है।
साहिल खन्ना

4
क्या किसी को पता चला है कि प्रति ऐप डेटा कैसे मिलेगा? कृपया कोड साझा करें :)
Bob de Graaf

16

यह समझना महत्वपूर्ण है कि ये काउंटर प्रदान किए गए हैं डिवाइस के अंतिम बूट के बाद से ।

तो, उनमें से प्रभावी उपयोग करने के लिए, आप डिवाइस के सक्रिय रहने की अवधि के साथ हर नमूना के साथ करना चाहिए (आप उपयोग कर सकते हैं mach_absolute_time()- देखना यह अधिक जानकारी के लिए देखें)

एक बार जब आप काउंटरों के नमूने + अपटाइम करते हैं, तो आपके पास डेटा उपयोग के रूप में बेहतर आंकड़े हो सकते हैं ...


mach_absolute_time अपटाइम नहीं है। यह सीपीयू के सक्रिय होने के समय की मात्रा है। मशीन सोते समय mach_absolute_time ज्यादातर गिनती बंद कर देता है।
बॉब व्हाइटमैन

13

स्वीकृत उत्तर में जोड़ने के लिए, यह महसूस करना महत्वपूर्ण है कि इंटरफ़ेस द्वारा प्रदर्शित डेटा की मात्रा 0प्रत्येक के बाद अधिक हो जाती है और फिर से शुरू होती है 4 GB, खासकर यदि आप दो रीडिंग के बीच अंतर की गणना करने के लिए इस कोड का उपयोग कर रहे हैं। यह है क्योंकि ifi_obytesऔर ifi_ibytesहैं uint_32और उनका अधिकतम मूल्य है4294967295

इसके अलावा, मैं उपयोग करने की सलाह देता हूं unsigned int भेजे गए और प्राप्त किए गए डेटा वाले चर के लिए एस । नियमित intएस में एक अहस्ताक्षरित पूर्णांक का अधिकतम मूल्य होता है, इसलिए जोड़ते समय ifi_obytes, यह अतिप्रवाह का कारण बन सकता है।

unsigned int sent = 0;
sent += networkStatisc->ifi_obytes;

4

स्वीकृत उत्तर का स्विफ्ट संस्करण। मैं कोड को छोटी इकाइयों में भी तोड़ता हूं।

struct DataUsageInfo {
    var wifiReceived: UInt32 = 0
    var wifiSent: UInt32 = 0
    var wirelessWanDataReceived: UInt32 = 0
    var wirelessWanDataSent: UInt32 = 0

    mutating func updateInfoByAdding(info: DataUsageInfo) {
        wifiSent += info.wifiSent
        wifiReceived += info.wifiReceived
        wirelessWanDataSent += info.wirelessWanDataSent
        wirelessWanDataReceived += info.wirelessWanDataReceived
    }
}

class DataUsage {

    private static let wwanInterfacePrefix = "pdp_ip"
    private static let wifiInterfacePrefix = "en"

    class func getDataUsage() -> DataUsageInfo {
        var interfaceAddresses: UnsafeMutablePointer<ifaddrs> = nil
        var dataUsageInfo = DataUsageInfo()

        guard getifaddrs(&interfaceAddresses) == 0 else { return dataUsageInfo }

        var pointer = interfaceAddresses
        while pointer != nil {
            guard let info = getDataUsageInfo(from: pointer) else {
                pointer = pointer.memory.ifa_next
                continue
            }
            dataUsageInfo.updateInfoByAdding(info)
            pointer = pointer.memory.ifa_next
        }

        freeifaddrs(interfaceAddresses)

        return dataUsageInfo
    }

    private class func getDataUsageInfo(from infoPointer: UnsafeMutablePointer<ifaddrs>) -> DataUsageInfo? {
        let pointer = infoPointer

        let name: String! = String.fromCString(infoPointer.memory.ifa_name)

        let addr = pointer.memory.ifa_addr.memory
        guard addr.sa_family == UInt8(AF_LINK) else { return nil }

        return dataUsageInfo(from: pointer, name: name)
    }

    private class func dataUsageInfo(from pointer: UnsafeMutablePointer<ifaddrs>, name: String) -> DataUsageInfo {
        var networkData: UnsafeMutablePointer<if_data> = nil
        var dataUsageInfo = DataUsageInfo()

        if name.hasPrefix(wifiInterfacePrefix) {
            networkData = unsafeBitCast(pointer.memory.ifa_data, UnsafeMutablePointer<if_data>.self)
            dataUsageInfo.wifiSent += networkData.memory.ifi_obytes
            dataUsageInfo.wifiReceived += networkData.memory.ifi_ibytes
        } else if name.hasPrefix(wwanInterfacePrefix) {
            networkData = unsafeBitCast(pointer.memory.ifa_data, UnsafeMutablePointer<if_data>.self)
            dataUsageInfo.wirelessWanDataSent += networkData.memory.ifi_obytes
            dataUsageInfo.wirelessWanDataReceived += networkData.memory.ifi_ibytes
        }

        return dataUsageInfo
    }
}

4

मैंने स्विफ्ट 3 संस्करण के लिए स्रोत कोड के ऊपर तय किया है

struct DataUsageInfo {
    var wifiReceived: UInt32 = 0
    var wifiSent: UInt32 = 0
    var wirelessWanDataReceived: UInt32 = 0
    var wirelessWanDataSent: UInt32 = 0

    mutating func updateInfoByAdding(_ info: DataUsageInfo) {
        wifiSent += info.wifiSent
        wifiReceived += info.wifiReceived
        wirelessWanDataSent += info.wirelessWanDataSent
        wirelessWanDataReceived += info.wirelessWanDataReceived
    }
}


class DataUsage {

    private static let wwanInterfacePrefix = "pdp_ip"
    private static let wifiInterfacePrefix = "en"

    class func getDataUsage() -> DataUsageInfo {
        var ifaddr: UnsafeMutablePointer<ifaddrs>?
        var dataUsageInfo = DataUsageInfo()

        guard getifaddrs(&ifaddr) == 0 else { return dataUsageInfo }
        while let addr = ifaddr {
            guard let info = getDataUsageInfo(from: addr) else {
                ifaddr = addr.pointee.ifa_next
                continue
            }
            dataUsageInfo.updateInfoByAdding(info)
            ifaddr = addr.pointee.ifa_next
        }

        freeifaddrs(ifaddr)

        return dataUsageInfo
    }

    private class func getDataUsageInfo(from infoPointer: UnsafeMutablePointer<ifaddrs>) -> DataUsageInfo? {
        let pointer = infoPointer
        let name: String! = String(cString: pointer.pointee.ifa_name)
        let addr = pointer.pointee.ifa_addr.pointee
        guard addr.sa_family == UInt8(AF_LINK) else { return nil }

        return dataUsageInfo(from: pointer, name: name)
    }

    private class func dataUsageInfo(from pointer: UnsafeMutablePointer<ifaddrs>, name: String) -> DataUsageInfo {
        var networkData: UnsafeMutablePointer<if_data>?
        var dataUsageInfo = DataUsageInfo()

        if name.hasPrefix(wifiInterfacePrefix) {
            networkData = unsafeBitCast(pointer.pointee.ifa_data, to: UnsafeMutablePointer<if_data>.self)
            if let data = networkData {
                dataUsageInfo.wifiSent += data.pointee.ifi_obytes
                dataUsageInfo.wifiReceived += data.pointee.ifi_ibytes
            }

        } else if name.hasPrefix(wwanInterfacePrefix) {
            networkData = unsafeBitCast(pointer.pointee.ifa_data, to: UnsafeMutablePointer<if_data>.self)
            if let data = networkData {
                dataUsageInfo.wirelessWanDataSent += data.pointee.ifi_obytes
                dataUsageInfo.wirelessWanDataReceived += data.pointee.ifi_ibytes
            }
        }

        return dataUsageInfo
    }
}

4

पिछले संस्करणों के आधार पर एक नया संस्करण, लेकिन स्विफ्ट 4 और एक्सकोड 9 के लिए अनुकूलित

struct DataUsageInfo {
    var wifiReceived: UInt32 = 0
    var wifiSent: UInt32 = 0
    var wirelessWanDataReceived: UInt32 = 0
    var wirelessWanDataSent: UInt32 = 0

    mutating func updateInfoByAdding(info: DataUsageInfo) {
        wifiSent += info.wifiSent
        wifiReceived += info.wifiReceived
        wirelessWanDataSent += info.wirelessWanDataSent
        wirelessWanDataReceived += info.wirelessWanDataReceived
    }
}

class DataUsage {

    private static let wwanInterfacePrefix = "pdp_ip"
    private static let wifiInterfacePrefix = "en"

    class func getDataUsage() -> DataUsageInfo {
        var interfaceAddresses: UnsafeMutablePointer<ifaddrs>? = nil

        var dataUsageInfo = DataUsageInfo()

        guard getifaddrs(&interfaceAddresses) == 0 else { return dataUsageInfo }

        var pointer = interfaceAddresses
        while pointer != nil {
            guard let info = getDataUsageInfo(from: pointer!) else {
                pointer = pointer!.pointee.ifa_next
                continue
            }
            dataUsageInfo.updateInfoByAdding(info: info)
            pointer = pointer!.pointee.ifa_next
        }

        freeifaddrs(interfaceAddresses)

        return dataUsageInfo
    }

    private class func getDataUsageInfo(from infoPointer: UnsafeMutablePointer<ifaddrs>) -> DataUsageInfo? {
        let pointer = infoPointer

        let name: String! = String(cString: infoPointer.pointee.ifa_name)
        let addr = pointer.pointee.ifa_addr.pointee
        guard addr.sa_family == UInt8(AF_LINK) else { return nil }

        return dataUsageInfo(from: pointer, name: name)
    }

    private class func dataUsageInfo(from pointer: UnsafeMutablePointer<ifaddrs>, name: String) -> DataUsageInfo {
        var networkData: UnsafeMutablePointer<if_data>? = nil
        var dataUsageInfo = DataUsageInfo()

        if name.hasPrefix(wifiInterfacePrefix) {
            networkData = unsafeBitCast(pointer.pointee.ifa_data, to: UnsafeMutablePointer<if_data>.self)
            dataUsageInfo.wifiSent += networkData?.pointee.ifi_obytes ?? 0
            dataUsageInfo.wifiReceived += networkData?.pointee.ifi_ibytes ?? 0
        } else if name.hasPrefix(wwanInterfacePrefix) {
            networkData = unsafeBitCast(pointer.pointee.ifa_data, to: UnsafeMutablePointer<if_data>.self)
            dataUsageInfo.wirelessWanDataSent += networkData?.pointee.ifi_obytes ?? 0
            dataUsageInfo.wirelessWanDataReceived += networkData?.pointee.ifi_ibytes ?? 0
        }

        return dataUsageInfo
    }
}

यह प्रत्येक ऐप या वास्तविक ऐप के लिए प्रदर्शित होता है जहां इसका उपयोग किया जाता है?
मक्सिम नियाज़ेव

यह वैश्विक उपयोग है ... इसे ऐप द्वारा अलग नहीं किया गया है।
dede.exe

और मान अंतिम रिबूट से है। पिछले / चालू महीने के लिए मिलने का कोई तरीका नहीं?
स्लावचो

@Slavcho। इस पोस्ट की तारीख तक यह संभव नहीं था। IOS12 के बाद भी मैंने इसके बारे में एक नया शोध नहीं किया। मैं आपको इसे पुनर्प्राप्त करने के लिए किसी स्थान पर ir संचित करने की सलाह देता हूं।
dede.exe

0

फिर से उसी जवाब के लिए क्षमा करें।

लेकिन मैंने पाया कि UInt32 पर्याप्त नहीं है, इसलिए जब यह बहुत बड़ा हो गया तो यह दुर्घटनाग्रस्त हो गया।

मैंने अभी UInt32 को UInt64 में बदल दिया है और यह ठीक काम करता है।

struct DataUsageInfo {
    var wifiReceived: UInt64 = 0
    var wifiSent: UInt64 = 0
    var wirelessWanDataReceived: UInt64 = 0
    var wirelessWanDataSent: UInt64 = 0

    mutating func updateInfoByAdding(info: DataUsageInfo) {
        wifiSent += info.wifiSent
        wifiReceived += info.wifiReceived
        wirelessWanDataSent += info.wirelessWanDataSent
        wirelessWanDataReceived += info.wirelessWanDataReceived
    }
}

class DataUsage {

    private static let wwanInterfacePrefix = "pdp_ip"
    private static let wifiInterfacePrefix = "en"

    class func getDataUsage() -> DataUsageInfo {
        var interfaceAddresses: UnsafeMutablePointer<ifaddrs>? = nil

        var dataUsageInfo = DataUsageInfo()

        guard getifaddrs(&interfaceAddresses) == 0 else { return dataUsageInfo }

        var pointer = interfaceAddresses
        while pointer != nil {
            guard let info = getDataUsageInfo(from: pointer!) else {
                pointer = pointer!.pointee.ifa_next
                continue
            }
            dataUsageInfo.updateInfoByAdding(info: info)
            pointer = pointer!.pointee.ifa_next
        }

        freeifaddrs(interfaceAddresses)

        return dataUsageInfo
    }

    private class func getDataUsageInfo(from infoPointer: UnsafeMutablePointer<ifaddrs>) -> DataUsageInfo? {
        let pointer = infoPointer

        let name: String! = String(cString: infoPointer.pointee.ifa_name)
        let addr = pointer.pointee.ifa_addr.pointee
        guard addr.sa_family == UInt8(AF_LINK) else { return nil }

        return dataUsageInfo(from: pointer, name: name)
    }

    private class func dataUsageInfo(from pointer: UnsafeMutablePointer<ifaddrs>, name: String) -> DataUsageInfo {
        var networkData: UnsafeMutablePointer<if_data>? = nil
        var dataUsageInfo = DataUsageInfo()

        if name.hasPrefix(wifiInterfacePrefix) {
            networkData = unsafeBitCast(pointer.pointee.ifa_data, to: UnsafeMutablePointer<if_data>.self)
            dataUsageInfo.wifiSent += UInt64(networkData?.pointee.ifi_obytes ?? 0)
            dataUsageInfo.wifiReceived += UInt64(networkData?.pointee.ifi_ibytes ?? 0)
        } else if name.hasPrefix(wwanInterfacePrefix) {
            networkData = unsafeBitCast(pointer.pointee.ifa_data, to: UnsafeMutablePointer<if_data>.self)
            dataUsageInfo.wirelessWanDataSent += UInt64(networkData?.pointee.ifi_obytes ?? 0)
            dataUsageInfo.wirelessWanDataReceived += UInt64(networkData?.pointee.ifi_ibytes ?? 0)
        }

        return dataUsageInfo
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.