You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取Android系统各应用月度等时段的移动及WiFi数据用量?

How to Get Per-App Mobile & WiFi Data Usage for a Specific Time Period on Android

Hey there! I’ve tackled this exact problem before, so let’s walk through how to retrieve per-app mobile and WiFi data usage for a custom time window (like a full month) on Android. The key here is using Android’s NetworkStatsManager API (available from API 23 onwards), which lets you filter usage by time, network type, and app.

1. Required Permissions

You’ll need two critical permissions to make this work:

  • android.permission.INTERNET (a basic permission, often already included in most app manifests)
  • android.permission.PACKAGE_USAGE_STATS (a special system permission that users have to enable manually via settings)

Add these to your AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission
    android:name="android.permission.PACKAGE_USAGE_STATS"
    android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
    android:protectionLevel="signature|preinstalled" />

Note on the Usage Stats Permission

This permission can’t be requested via the standard runtime permission prompt. You’ll need to redirect users to the system settings to enable it:

private fun checkUsageStatsPermission(): Boolean {
    val appOps = getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
    val mode = appOps.checkOpNoThrow(
        AppOpsManager.OPSTR_GET_USAGE_STATS,
        android.os.Process.myUid(),
        packageName
    )
    return mode == AppOpsManager.MODE_ALLOWED
}

private fun requestUsageStatsPermission() {
    startActivity(Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS))
}

2. Query Data Usage with NetworkStatsManager

Once you have the necessary permissions, you can use NetworkStatsManager to fetch data for specific network types and time ranges. Let’s break this down with code examples.

First, Define Your Time Range

For a monthly report, calculate the start and end timestamps of the current month:

// Get start of current month (midnight on the 1st)
val calendar = Calendar.getInstance()
calendar.set(Calendar.DAY_OF_MONTH, 1)
calendar.set(Calendar.HOUR_OF_DAY, 0)
calendar.set(Calendar.MINUTE, 0)
calendar.set(Calendar.SECOND, 0)
val startTimestamp = calendar.timeInMillis

// Get end of current month (11:59 PM on the last day)
calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH))
calendar.set(Calendar.HOUR_OF_DAY, 23)
calendar.set(Calendar.MINUTE, 59)
calendar.set(Calendar.SECOND, 59)
val endTimestamp = calendar.timeInMillis

Fetch Data for All Apps

Create a function to retrieve usage data for a specific network type (mobile or WiFi):

@SuppressLint("MissingPermission")
private fun getAppDataUsage(networkType: Int, start: Long, end: Long): Map<String, Pair<Long, Long>> {
    // Package name -> (Received bytes, Transmitted bytes)
    val usageMap = mutableMapOf<String, Pair<Long, Long>>()
    val networkStatsManager = getSystemService(Context.NETWORK_STATS_SERVICE) as NetworkStatsManager
    val packageManager = packageManager

    try {
        // Query all app usage for the specified network and time range
        val subscriberId = if (networkType == ConnectivityManager.TYPE_MOBILE_DATA) getSubscriberId() else ""
        val statsIterator = networkStatsManager.queryDetails(
            networkType,
            subscriberId,
            start,
            end
        )

        while (statsIterator.hasNextBucket()) {
            val bucket = NetworkStats.Bucket()
            statsIterator.getNextBucket(bucket)

            val uid = bucket.uid
            val packageNames = packageManager.getPackagesForUid(uid) ?: continue
            val rxBytes = bucket.rxBytes
            val txBytes = bucket.txBytes

            // Aggregate usage for each package linked to the UID
            packageNames.forEach { packageName ->
                val currentUsage = usageMap[packageName] ?: Pair(0L, 0L)
                usageMap[packageName] = Pair(currentUsage.first + rxBytes, currentUsage.second + txBytes)
            }
        }
    } catch (e: SecurityException) {
        e.printStackTrace()
        // Handle permission error (remind user to enable usage stats access)
    }

    return usageMap
}

// Helper to get subscriber ID for mobile network (required for mobile data queries)
private fun getSubscriberId(): String {
    val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        telephonyManager.subscriptionId.toString()
    } else {
        @Suppress("DEPRECATION")
        telephonyManager.subscriberId ?: ""
    }
}

Network Type References

  • Mobile Data: Use ConnectivityManager.TYPE_MOBILE_DATA (API 29+; for older versions, use ConnectivityManager.TYPE_MOBILE)
  • WiFi: Use ConnectivityManager.TYPE_WIFI

3. Put It All Together

Here’s how to use the above functions to get monthly mobile and WiFi usage:

if (checkUsageStatsPermission()) {
    // Handle network type compatibility for mobile data
    val mobileNetworkType = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        ConnectivityManager.TYPE_MOBILE_DATA
    } else {
        ConnectivityManager.TYPE_MOBILE
    }

    // Fetch usage data
    val mobileUsage = getAppDataUsage(mobileNetworkType, startTimestamp, endTimestamp)
    val wifiUsage = getAppDataUsage(ConnectivityManager.TYPE_WIFI, startTimestamp, endTimestamp)

    // Example: Print top 5 apps by total mobile data usage
    mobileUsage.entries.sortedByDescending { it.value.first + it.value.second }
        .take(5)
        .forEach { entry ->
            val totalBytes = entry.value.first + entry.value.second
            val totalMB = totalBytes / (1024 * 1024)
            Log.d("DataUsage", "${entry.key}: ${totalMB}MB (Rx: ${entry.value.first/(1024*1024)}MB, Tx: ${entry.value.second/(1024*1024)}MB)")
        }
} else {
    // Prompt user to enable usage stats access
    requestUsageStatsPermission()
}

Important Notes

  • API Compatibility: NetworkStatsManager only works on API 23+. For older Android versions, you’ll have to use TrafficStats, but it doesn’t support time-range filtering (only total usage since device boot).
  • Multi-SIM Devices: If the device has multiple SIM cards, you’ll need to iterate over active subscriptions to get subscriber IDs for each SIM.
  • Unit Conversion: The API returns data in bytes—convert to KB/MB/GB by dividing by 1024 (KB), 1024*1024 (MB), or 1024*1024*1024 (GB).

内容的提问来源于stack exchange,提问作者Haresh Solanki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:24:40