В моем приложении на главном экране можно разместить несколько Виджеты приложений, при этом каждый виджет выбирает удаленные данные на периодической основе.
Мои цели:
- отслеживать использование данных, связанных с каждым из нескольких виджетов отдельно
- Использование Wi-Fi и мобильных данных
- только моего собственного приложения (не интересуется использованием данных других приложений)
- никаких дополнительных разрешений
- позволяют виджетам выполнять сетевые операции одновременно без двойного подсчета использования данных.
- включает использование данных в
WebView
активность, инициированную из виджета - вывод результатов в приложении (а не только при привязке к Network Traffic Tool)
Достаточно легко зарегистрировать использование данных для вашего собственного UID до и после обновления виджета с помощью TrafficStats
, используя getUidRxBytes()
и getUidTxBytes()
(передача вашего собственного UID приложения) и то принимая разницу. Несмотря на то, что этот приблизительный подход дает разумные значения, когда виджеты работают последовательно, когда они работают одновременно, неизбежно происходит счёт двойного (тройного и т.д.) Подсчета.
Я бы предпочел не заставлять виджеты обновляться последовательно, потому что я предпочел бы, чтобы механизм планирования работы устройства работал над тем, что лучше. Поэтому мне нужен способ разделения использования данных для каждого виджета друг от друга.
Похоже, что использование тегов может быть способом... выполнять сетевые операции с тегом appWidgetId
, а затем фильтровать статистику на основе этого appWidgetId
. Я не убежден, что этот подход фактически позволит использовать данные одного виджета для отличия от другого (возможно, ведра будут запутаны), но факт в том, что я не могу заставить теги работать вообще, поэтому я пока не могу сказать.
Вы можете установить тег setThreadStatsTag(tag)
перед началом сетевой операции, но я не вижу никакого метода в TrafficStats
класс для получения результатов, отфильтрованных по тегу. Кто-нибудь знает разные?
Итак, я тогда посмотрел на NetworkStatsManager, и в частности NetworkStatsManager.queryDetailsForUidTag(... , tag)
. Это, по-видимому, позволяет фильтровать на основе определенного tag
и работает без каких-либо дополнительных разрешений (для вашего собственного UID приложения), что хорошо. Но я не могу получить этот метод, чтобы возвращать любые ведра с данными, несмотря на установку TrafficStats.setThreadStatsTag(appWidgetId)
перед сетевыми операциями с использованием HttpURLConnection
и запрос с тем же тегом впоследствии, вызывая NetworkStatsManager.queryDetailsForUidTag(... , appWidgetId)
.
С другой стороны, NetworkStatsManager.queryDetailsForUid()
(параметр tag
) возвращает ведра с действительными данными, поэтому, похоже, это просто тег, который не работает, а не что-то фундаментальное, я делаю неправильно с NetworkStatsManager
как таковым.
Я установил тег:
@Override
protected void onPreExecute() {
TrafficStats.setThreadStatsTag(appWidgetId);
}
@Override
protected Bitmap doInBackground(String... baseUrls) {
// fetch data with HttpURLConnection
}
@Override
protected void onPostExecute(Bitmap bmp) {
TrafficStats.clearThreadStatsTag();
}
И (для данных WiFi) Я запрашиваю статистику с помощью:
void networkStatsStuff() {
NetworkStats networkStats;
NetworkStats networkStatsTagged;
int networkType = ConnectivityManager.TYPE_WIFI;
try {
networkStats = networkStatsManager.queryDetailsForUid(networkType, "", startTime, endTime, myUid);
} catch (RemoteException e) {
return;
}
networkStatsTagged = networkStatsManager.queryDetailsForUidTag(networkType, "", startTime, endTime, myUid, appWidgetId);
long totalData = getTotalData(networkStats);
long totalDataTagged = getTotalData(networkStatsTagged);
Log.d(TAG, "totalData: " + totalData); // this seems to work
Log.d(TAG, "totalDataTagged: " + totalDataTagged); // this is always zero
}
long getTotalData(NetworkStats networkStats) {
long totalData = 0;
do {
NetworkStats.Bucket bucket = new NetworkStats.Bucket();
networkStats.getNextBucket(bucket);
totalData = totalData + bucket.getRxBytes() + bucket.getTxBytes();
} while (networkStats.hasNextBucket());
return totalData;
}
Что я делаю неправильно? (EDIT: частичный ответ ниже.) Или, может быть, существует совершенно другой способ достижения моих целей?