此方法主要用到系统API提供的SharedPreferences和TrafficStats。
当然也可以用数据库,但是原理是一样的。
思路是每次完成连网服务后,都调用一次saveFlow()方法,具体方法如下:
/**
* 保存改变后的流量使用量
*/
public void saveFlow(){
if (sp == null){
sp = getSharedPreferences(LoginActivity.username, Context.MODE_PRIVATE);
}
long oldin = sp.getLong("inFlow-old",0) ;
long oldout = sp.getLong("outFlow-old",0) ;
long allin = sp.getLong("inFlow",0) ;
long allout = sp.getLong("outFlow",0) ;
long time = sp.getLong("flow-time",0) ;
SharedPreferences.Editor editor = sp.edit();
if (time == 0 || !getMoth4Long(System.currentTimeMillis()).equals(getMoth4Long(time))){
oldin = 0 ;
oldout = 0 ;
allin = 0 ;
allout = 0 ;
editor.putLong("flow-time", System.currentTimeMillis());
}
long in = TrafficStats.getUidRxBytes(getApplicationInfo().uid) ;
long out = TrafficStats.getUidTxBytes(getApplicationInfo().uid) ;
if (in >= oldin && out >= oldout){
editor.putLong("inFlow", allin + in-oldin);
editor.putLong("outFlow", allout + out-oldout);
}else {
editor.putLong("inFlow", allin + in);
editor.putLong("outFlow", allout + out);
}
editor.putLong("inFlow-old", in);
editor.putLong("outFlow-old", out);
editor.commit();
}
每月更新一次流量统计,所以有时间判断。
private String getMoth4Long(Long time){
SimpleDateFormat sDateFormat = new SimpleDateFormat("MM");
Date date = new Date(time) ;
return sDateFormat.format(date) ;
}
获取手机指定 UID 对应的应程序用通过所有网络方式接收的字节流量总数(包括 wifi) TrafficStats.getUidRxBytes(getApplicationInfo().uid); 获取手机指定 UID 对应的应用程序通过所有网络方式发送的字节流量总数(包括 wifi) TrafficStats.getUidTxBytes(getApplicationInfo().uid);
以上得到的是所有流量(包括WiFi),但是实际上只想监听移动数据的,怎么办呢。
很简单,只需要在每次保存前判断一下当前网络状况,如果是移动数据的就添加,否则不加,得到的就是移动数据的了。
/** * 保存改变后的流量使用量 */ public synchronized void saveFlow(){ if (sp == null){ sp = getSharedPreferences(LoginActivity.username, Context.MODE_PRIVATE); } long oldin = sp.getLong("inFlow-old",0) ; long oldout = sp.getLong("outFlow-old",0) ; long allin = sp.getLong("inFlow",0) ; long allout = sp.getLong("outFlow",0) ; long innet = sp.getLong("inFlow-net",0) ; long outnet = sp.getLong("outFlow-net",0) ; long time = sp.getLong("flow-time",0) ; SharedPreferences.Editor editor = sp.edit(); if (time == 0 || !getMoth4Long(System.currentTimeMillis()).equals(getMoth4Long(time))){ //隔月或者第一次 oldin = 0 ; oldout = 0 ; allin = 0 ; allout = 0 ; innet = 0 ; outnet = 0 ; editor.putLong("flow-time", System.currentTimeMillis()); } long in = TrafficStats.getUidRxBytes(getApplicationInfo().uid) ; long out = TrafficStats.getUidTxBytes(getApplicationInfo().uid) ; int type = getNetType() ; if (in >= oldin && out >= oldout){ //没关机 editor.putLong("inFlow", allin + in-oldin); editor.putLong("outFlow", allout + out-oldout); if (type != -1 && type != 1){ editor.putLong("inFlow-net", innet + in-oldin); editor.putLong("outFlow-net", outnet + out-oldout); } }else { //关过机 editor.putLong("inFlow", allin + in); editor.putLong("outFlow", allout + out); if (type != -1 && type != 1){ editor.putLong("inFlow-net", innet + in); editor.putLong("outFlow-net", outnet + out); } } editor.putLong("inFlow-old", in); editor.putLong("outFlow-old", out); editor.commit(); } //返回值 -1:没有网络 1:WIFI网络2:wap网络3:net网络 public int getNetType() { int netType = -1; ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = connMgr.getActiveNetworkInfo(); if(networkInfo==null) { return netType; } int nType = networkInfo.getType(); if(nType==ConnectivityManager.TYPE_MOBILE) { if(networkInfo.getExtraInfo().toLowerCase().equals("cmnet")) { netType = 3; } else { netType = 2; } } else if(nType==ConnectivityManager.TYPE_WIFI) { netType = 1; } return netType; }
如果想要监控别的APP,建立一个service,每秒钟运行一次就行了。