Java Android移动使用历史网络StatsManager
我正在为Android 6.0制作一个应用程序,我想使用新的NetworkStatsManager类来获取移动数据使用情况 我在清单中添加了我需要的所有权限,并且需要运行时权限 当我调用该方法时: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_
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,则返回异常!