Obtener el historial de uso de datos móviles usando NetworkStatsManager

Quiero saber el historial de uso de datos y noté el "nuevo" android-6NetworkStatsManager lo que parece positivo (he usadoTrafficStats un tiempo, pero eso no cubrirá nada anterior a un reinicio).

De la documentación de la API:

NOTA: Esta API requiere el permiso PACKAGE_USAGE_STATS, que es un permiso de nivel de sistema y no se otorgará a aplicaciones de terceros. Sin embargo, declarar el permiso implica la intención de usar la API y el usuario del dispositivo puede otorgar permiso a través de la aplicación Configuración. Las aplicaciones del propietario del perfil reciben automáticamente permiso para consultar datos en el perfil que administran (es decir, para cualquier consulta excepto querySummaryForDevice (int, String, long, long)). Las aplicaciones del propietario del dispositivo también obtienen acceso a los datos de uso del usuario principal.

Quiero saber el uso de datos en un nivel agregado yno hasta qué aplicación usa los datos, así que intenté usarlo así:

NetworkStatsManager service = context.getSystemService(NetworkStatsManager.class);

NetworkStats.Bucket bucket = 
        service.querySummaryForDevice(ConnectivityManager.TYPE_MOBILE, null, from, to);
...

Desafortunadamente eso arroja unSecurityException:

java.lang.SecurityException: NetworkStats: Neither user 10174 nor current process has android.permission.READ_NETWORK_USAGE_HISTORY.
at android.os.Parcel.readException(Parcel.java:1620)
at android.os.Parcel.readException(Parcel.java:1573)
at android.net.INetworkStatsSession$Stub$Proxy.getDeviceSummaryForNetwork(INetworkStatsSession.java:259)
at android.app.usage.NetworkStats.getDeviceSummaryForNetwork(NetworkStats.java:316)
at android.app.usage.NetworkStatsManager.querySummaryForDevice(NetworkStatsManager.java:100)
...

losandroid.permission.READ_NETWORK_USAGE_HISTORY el permiso no está permitido para aplicaciones de terceros. Así que esto parecía un callejón sin salida.

Sin embargo, profundicé un poco en las partes internas y descubrí que puede usar la API interna / oculta para hacer lo mismo sin solicitar ningún permiso:

INetworkStatsService service =
        INetworkStatsService.Stub.asInterface(
                ServiceManager.getService(Context.NETWORK_STATS_SERVICE));

INetworkStatsSession session = service.openSession();

NetworkTemplate mobileTemplate = NetworkTemplate.buildTemplateMobileWildcard();
int fields = NetworkStatsHistory.FIELD_RX_BYTES | NetworkStatsHistory.FIELD_TX_BYTES;

NetworkStatsHistory mobileHistory = session.getHistoryForNetwork(mobileTemplate, fields);

for (int i = 0; i < mobileHistory.size(); i++) {
    NetworkStatsHistory.Entry entry = mobileHistory.getValues(i, null);
    ...
}

session.close();

Realmente quiero hacer lo mismo con la API pública, entonces, ¿cómo hago exactamente eso?

Respuestas a la pregunta(2)

Su respuesta a la pregunta