История использования мобильных устройств Android NetworkStatsManager

Я делаю приложение для Android 6.0 и хочу использовать новый класс NetworkStatsManager для получения мобильных данных.

Я добавил все необходимые разрешения в манифест и требует разрешения времени выполнения.

Когда я вызываю метод:

bucket = networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_WIFI, "", fromDate.getTime(), toDate.getTime());

верните правильное значение для использования WIFI.

Но если я заменю TYPE_WIFI на TYPE_MOBILE, результат всегда будет 0.

    NetworkStats.Bucket bucket = null;
    try {
        bucket = networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_MOBILE, "", fromDate.getTime(), toDate.getTime());

        if(bucket == null){
            Log.i("Info", "Error");
        }else{
            Log.i("Info", "Total: " + (bucket.getRxBytes() + bucket.getTxBytes()));
        }

    } catch (RemoteException e) {
        e.printStackTrace();
    }

1 ответ

Решение

Я нашел решение этой проблемы с помощью скрытых API-интерфейсов ( статистика 3g android для каждого приложения, как?), И при попытке получить информацию об использовании мобильных данных с помощью TYPE_MOBILE было необходимо сообщить SubscriberID, в отличие от того, когда я пытался получить информацию TYPE WIFI.

Попробуйте этот код

    TelephonyManager  tm = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
    String subscriberID = tm.getSubscriberId();

    NetworkStats networkStatsByApp = networkStatsManager.queryDetailsForUid(ConnectivityManager.TYPE_MOBILE, subscriberID, start, end, uid);

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

В качестве продолжения принятого ответа я также хотел бы отметить, что в следующем коде

TelephonyManager  tm = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
String subscriberID = tm.getSubscriberId(); //subscriberID is usually the IMSI number (for GSM phones)

TelephonyManager tm содержит информацию о телефонной службе по умолчанию (SIM-карте), которая используется для совершения звонков. Итак, если вы используете телефон с двумя SIM-картами, а SIM 1 используется для звонков, а SIM 2 используется для передачи данных, то TelephonyManager tm будет хранить информацию о SIM 1 и в вашем случае использования, где вы используете NetworkStatsManager для получения статистики использования данных информация с SIM 1 будет бесполезной, поскольку она не используется для использования данных. Итак, вам как-то нужно получить TelephonyManager для SIM 2, чтобы вы могли использовать правильный идентификатор абонента SIM 2 в networkStatsManager.querySummaryForDevice() чтобы получить статистику использования мобильных данных. Итак, как ты это делаешь?

Один из способов, который я понял, таков:

public void subscriberIdsOfDualSim(){
    SubscriptionManager subscriptionManager = SubscriptionManager.from(this);
    //we'll now get a List of information of active SIM cards
    //for example, if there are 2 SIM slots and both the slots have 1 SIM card each, then the List size will be 2
    List<SubscriptionInfo> activeSubscriptionInfoList = subscriptionManager.getActiveSubscriptionInfoList();
    TelephonyManager manager = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
    for (SubscriptionInfo subscriptionInfo : activeSubscriptionInfoList) {
        //loop through the SIM card info
        //if there are 2 SIM cards, then we'll try to print the subscriberId of each of the SIM cards
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
            //the following createForSubscriptionId() is available from API 24 :(
            TelephonyManager manager1=manager.createForSubscriptionId(subscriptionInfo.getSubscriptionId());
            String operatorName=manager1.getNetworkOperatorName();
            String subscriberId=manager1.getSubscriberId(); //use this subscriberId to do NetworkStatsManager stuff
            System.out.println("subscriberIdsOfDualSim: Carrier Name: "+operatorName+", subscriber id: "+subscriberId);
        }
    }
}

Обратите внимание, что я использовал createForSubscriptionId() метод. Одним из ограничений этого метода является то, что его можно использовать только из API 24 (Android 7.0 Nougat).

Таким образом, если вы используете SIM 1 и SIM 2 для потребления данных, вы можете получить информацию об использовании данных для каждой из SIM-карт, предоставив subscriberId каждого из них networkStatsManager.querySummaryForDevice(), Но если вы хотите получить правильное потребление данных с мобильных устройств (включая SIM 1 и SIM 2 включительно) и хотите поддерживать телефоны ниже нуга, то старый добрый getMobileRxBytes() а также getMobileTxBytes() методы в TrafficStats класс - это то, что вам, возможно, придется использовать.

Еще одно дополнение к принятому ответу и @Nandan, можно получить идентификаторы подписчиков обеих SIM-карт, используя приведенный ниже код

SubscriptionManager subman = (SubscriptionManager)getSystemService(TELEPHONY_SUBSCRIPTION_SERVICE);
TelephonyManager telman = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);

List<SubscriptionInfo> li = subman.getActiveSubscriptionInfoList();

for(SubscriptionInfo info : li){
    int sid = info.getSubscriptionId(); //not the id we want

    try{
        Class c = Class.forName("android.telephony.TelephonyManager");
        Method m = c.getMethod("getSubscriberId", new Class[]{int.class});
        Object o = m.invoke(telman, new Object[]{sid});

        String subid = (String)o;  //id we want
        Log.i("SubscriptionId", subid);
    }
    catch(Exception e){}

}

Кредит, чтобы ответить на ссылку /questions/20210995/subscriptionmanager-dlya-chteniya-imsi-dlya-ustrojstv-s-dvumya-sim-kartami-rabotayuschimi-na-android-51/20211000#20211000

Другие вопросы по тегам