Как получить сетевое использование приложений на Android Q? - PullRequest
4 голосов
/ 15 июня 2019

Фон

Я знаю, что мы можем получить сетевое использование (общая пропускная способность, используемая мобильными телефонами и Wi-Fi на данный момент, с определенного времени) определенного приложения, используя что-то подобное (спрашивалось в прошлом, здесь ):

    private final static int[] NETWORKS_TYPES = new int[]{ConnectivityManager.TYPE_WIFI, ConnectivityManager.TYPE_MOBILE};

    long rxBytes=0L, txBytes=0L;
    final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    final String subscriberId = telephonyManager.getSubscriberId();
    final ApplicationInfo applicationInfo = context.getPackageManager().getApplicationInfo(packageName, 0);
    final int uid = applicationInfo.uid;
    for (int networkType : NETWORKS_TYPES) {
        final NetworkStats networkStats = networkStatsManager.queryDetailsForUid(networkType, subscriberId, 0, System.currentTimeMillis(), uid); 
        final Bucket bucketOut = new Bucket();
        while (true) {
                networkStats.getNextBucket(bucketOut);
                final long rxBytes = bucketOut.getRxBytes();
                if (rxBytes >= 0)
                    totalRx += rxBytes;
                final long txBytes = bucketOut.getTxBytes();
                if (txBytes >= 0)
                    totalTx += txBytes;
                if (!networkStats.hasNextBucket())
                    break;
            }
        }
    }

Документы:

https://developer.android.com/reference/android/app/usage/NetworkStatsManager.html#queryDetailsForUid(int,%20java.lang.String,%20long,%20long,%20int)

Также возможно получить глобальное использование сети (используяTrafficStats.getUidRxBytes(applicationInfo.uid) и TrafficStats.getUidTxBytes(applicationInfo.uid)), но это не то, для чего предназначен этот поток.

Проблема

Похоже, что в Android Q планируется отключить множество функций идентификации устройств.работает больше, и getSubscriberId является одним из них.

Что я пробовал

Я попытался установить targetSdk на 29 (Q) и посмотреть, что произойдет, когда я попытаюсь использовать это.

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

019-06-11 02:08:01.871 13558-13558/com.android.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.android.myapplication, PID: 13558
    java.lang.SecurityException: getSubscriberId: The user 10872 does not meet the requirements to access device identifiers.
        at android.os.Parcel.createException(Parcel.java:2069)
        at android.os.Parcel.readException(Parcel.java:2037)
        at android.os.Parcel.readException(Parcel.java:1986)
        at com.android.internal.telephony.IPhoneSubInfo$Stub$Proxy.getSubscriberIdForSubscriber(IPhoneSubInfo.java:984)
        at android.telephony.TelephonyManager.getSubscriberId(TelephonyManager.java:3498)
        at android.telephony.TelephonyManager.getSubscriberId(TelephonyManager.java:3473)

Поиск в Интернете и здесь, я не вижу упомянутое, но я нашел о похожих проблемах получения IMEI и других идентификаторов:

Так что сейчас я только что сделал отчет об ошибке здесь (включая пример проекта):

https://issuetracker.google.com/issues/134919382

Вопрос

Возможно ли получить использование сетиуказанного приложения на Android Q (при нацеливании на него)?Может быть, без subscriberId?

Если да, то как?

Если нет, возможно ли это с помощью root или через adb?


РЕДАКТИРОВАТЬ:

ОК, я не знаю, как официально использовать это, но по крайней мере для корневого доступа можно получить subscriberId, используя это решение , найденное из здесь .

Что-то в этом роде:

@SuppressLint("MissingPermission", "HardwareIds")
fun getSubscriberId(telephonyManager: TelephonyManager): String? {
    try {
        return telephonyManager.subscriberId
    } catch (e: Exception) {
    }
    val commandResult = Root.runCommands("service call iphonesubinfo 1 | grep -o \"[0-9a-f]\\{8\\} \" | tail -n+3 | while read a; do echo -n \"\\u\${a:4:4}\\u\${a:0:4}\"; done")
    val subscriberId = commandResult?.getOrNull(0)
    return if (subscriberId.isNullOrBlank()) null else subscriberId
}

Конечно, это не официальное решение, но лучше, чем ничего ...

1 Ответ

0 голосов
/ 27 июня 2019

Команда Google в комментарии упомянутой вами ветки сказала: " Статус: не исправляется (предполагаемое поведение) Это работает по назначению. IMEI - это персональный идентификатор, и он не выдается приложениям в соответствии с политикой. Обходного пути нет.". Поэтому я предполагаю, что методы класса NetworkStatsManager, для работы которых требуется IMSI (который также считается персональным идентификатором) (например, queryDetailsForUid(int, String, long, long, int)), теперь не работают в Android Q. Вы можете использовать эти методы для получения сведений об использовании Wi-Fi приложений (путем передачи пустой строки для subscriberId), но для получения сведений об использовании Mobile вам теперь нужно полагаться на старый добрый класс TrafficStats, пока проблема не будет замечена и устранена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...