Подтвердить что ты не робот

Отслеживание использования нескольких виджетов приложений отдельно

В моем приложении на главном экране можно разместить несколько Виджеты приложений, при этом каждый виджет выбирает удаленные данные на периодической основе.

Мои цели:

  • отслеживать использование данных, связанных с каждым из нескольких виджетов отдельно
  • Использование 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: частичный ответ ниже.) Или, может быть, существует совершенно другой способ достижения моих целей?

4b9b3361

Ответ 1

Частичный ответ:

Итак, я думаю, что меня сбило это руководство, где я получил размещение setThreadStatsTag() и clearThreadStatsTag(), в preExecute() и postExecute() соответственно AsyncTask.

Когда я перехожу к настройке и отключая тэг в части doInBackground() AsyncTask, я начинаю видеть теги... Я заметил это первым в Android Device Monitor, но они также там при использовании методов NetworkStats, которые фильтруются с помощью tag.

Итак, представляется более правильным использовать что-то вроде описанного в этом руководстве, в соответствии с:

@Override
protected Bitmap doInBackground(String... baseUrls) {
    TrafficStats.setThreadStatsTag(appWidgetId);
    try {
        // fetch data with HttpURLConnection
    } finally {
        TrafficStats.clearThreadStatsTag();
    }
}

Итак, первое руководство просто неправильно?

Все еще не разрешено:

  • запрос на использование мобильных данных без каких-либо дополнительных разрешений (я опасаюсь, что требуется разрешение READ_PHONE_STATE... кажется излишним и раздражает, учитывая, что разрешение не требуется с помощью методов TrafficStats, которые также читают использование мобильных данных, хотя вместе с другими интерфейсами)
  • включает использование данных по WebView (опять же, я опасаюсь, что это невозможно, т.е. невозможно пометить трафик в WebView и, следовательно, невозможно различить по тегу только из-за характера соответствующих протоколов... this и этот может быть актуальным)