Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android移动使用历史网络StatsManager_Java_Android_Android Trafficstats_Networkstatsmanager - Fatal编程技术网

Java Android移动使用历史网络StatsManager

Java Android移动使用历史网络StatsManager,java,android,android-trafficstats,networkstatsmanager,Java,Android,Android Trafficstats,Networkstatsmanager,我正在为Android 6.0制作一个应用程序,我想使用新的NetworkStatsManager类来获取移动数据使用情况 我在清单中添加了我需要的所有权限,并且需要运行时权限 当我调用该方法时: bucket = networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_WIFI, "", fromDate.getTime(), toDate.getTime()); 返回WIFI使用的正确值 但是,如果我用TYPE_

我正在为Android 6.0制作一个应用程序,我想使用新的NetworkStatsManager类来获取移动数据使用情况

我在清单中添加了我需要的所有权限,并且需要运行时权限

当我调用该方法时:

bucket = networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_WIFI, "", fromDate.getTime(), toDate.getTime());
返回WIFI使用的正确值

但是,如果我用TYPE_MOBILE替换TYPE_WIFI,结果总是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();
    }

我通过隐藏API()找到了这个问题的解决方案,当我尝试使用类型_检索移动数据使用信息时,移动设备是通知订阅ID所必需的,这与我尝试获取信息类型WIFI时不同

试试这个代码

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

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

因此,当您使用TYPE_MOBILE时,必须使用有效的subscriberID。

作为接受答案的后续,我还想指出,在以下代码中

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信息将不起作用,因为它不用于消费数据。因此,您需要获取SIM 2的
TelephonyManager
,以便在
networkStatsManager.querySummaryForDevice()
中使用SIM 2的正确用户Id来获取移动数据使用情况统计信息。那么,你是如何做到这一点的

我发现的一个方法是:

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);
        }
    }
}
public void subscriberIdsOfDualSim(){
SubscriptionManager SubscriptionManager=SubscriptionManager.from(this);
//我们现在将获得活动SIM卡的信息列表
//例如,如果有两个SIM卡插槽,且两个插槽各有一张SIM卡,则列表大小将为2
List activeSubscriptionInfoList=subscriptionManager.getActiveSubscriptionInfoList();
TelephonyManager=(TelephonyManager)this.getSystemService(Context.TELEPHONY_服务);
对于(SubscriptionInfo SubscriptionInfo:ActiveSubscriptionInfo列表){
//循环查看SIM卡信息
//如果有2张SIM卡,那么我们将尝试打印每个SIM卡的订阅ID
if(android.os.Build.VERSION.SDK\u INT>=android.os.Build.VERSION\u code.N){
//以下createForSubscriptionId()可从API 24获得:(
TelephonyManager manager1=manager.createForSubscriptionId(subscriptionInfo.getSubscriptionId());
字符串operatorName=manager1.getNetworkOperatorName();
String subscriberId=manager1.getSubscriberId();//使用此subscriberId执行NetworkStatsManager操作
System.out.println(“subscriberIdsOfDualSim:运营商名称:“+operatorName+”,订户id:“+subscriberId”);
}
}
}
请注意,我使用了
createForSubscriptionId()
方法。该方法的一个限制是只能从API 24(Android 7.0 Nougat)使用


因此,如果您同时使用SIM 1和SIM 2进行数据消费,那么您可以通过向
networkStatsManager.querySummaryForDevice()
提供每个SIM卡的
订阅ID来获取每个SIM卡的数据使用信息。但是,如果您想获得正确的移动数据消费(包括SIM 1和SIM 2)如果您想支持牛轧糖以下的手机,那么您可能必须使用
TrafficStats
类中的好的
getMobileRxBytes()
getMobileTxBytes()
方法。

另一个跟进已接受的答案和@Nandan,您可以使用下面的代码获得两张SIM卡的用户ID

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){}

}
SubscriptionManager subman=(SubscriptionManager)getSystemService(电话订阅服务);
TelephonyManager telman=(TelephonyManager)getSystemService(电话服务);
List li=subman.getActiveSubscriptionInfoList();
对于(订阅信息:li){
int sid=info.getSubscriptionId();//不是我们想要的id
试一试{
Class c=Class.forName(“android.telephony.TelephonyManager”);
方法m=c.getMethod(“getSubscriberId”,新类[]{int.Class});
对象o=m.invoke(telman,新对象[]{sid});
String subid=(String)o;//我们需要的id
Log.i(“SubscriptionId”,subid);
}
捕获(例外e){}
}

回答信用链接

请不要只是将代码作为答案发布…至少解释一下你的答案/代码。对不起,我添加了更多关于解决方案的信息。酷东西@emidiooliviera:)是否有机会将移动统计数据拆分为家庭和漫游网络?使用此代码时,我仍然会得到零。公共长GetAllrXBytes-Mobile1(上下文上下文){NetworkStats.Bucket Bucket;尝试{Bucket=networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_-mobile,getSubscriberId(context,ConnectivityManager.TYPE_MOBILE),0,System.currentTimeMillis();}catch(RemoteException e){return-1;}return bucket.getRxBytes();}另一个限制是来自API 28(针对它的应用程序)的getSubscriberId()返回null,如果目标为API 29,则返回异常!