/*
Copyright 2012-2013, Polyvi Inc. (http://polyvi.github.io/openxface)
This program is distributed under the terms of the GNU General Public License.
This file is part of xFace.
xFace is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
xFace is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with xFace. If not, see <http://www.gnu.org/licenses/>.
*/
package com.polyvi.xface.extension.trafficstats;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
import android.net.TrafficStats;
/**
* 流量统计类,负责对mobile、wifi、noNetwork流量进行统计,其中包含了3个内部类,
* 分别统计不同类型的流量,同时在网络类型切换时,更新相应的流量统计
*/
public class XTrafficStats {
private static final int CONST_NUM = 1024;
private Context mContext;
/** 应用的唯一标识 */
private int mUID;
/** 负责统计wifi流量 */
private XWifiTraffic mWifiTraffic;
/** 负责统计mobile流量,包括2G,3G */
private XMobileTraffic mMobileTraffic;
/** 统计进程间通信的流量,主要是为了减少wif和mobile流量统计的误差 */
private XNoNetworkTraffic mNoNetworkTraffic;
/** 负责监听网络连接状态改变 */
private BroadcastReceiver mConnectionMonitor;
/** 表示当前的网络状态 */
XTrafficStatsBase mCurrentNetworkState;
public XTrafficStats(Context context) {
mContext = context;
PackageManager pm = mContext.getPackageManager();
try {
ApplicationInfo info = pm.getApplicationInfo(
context.getPackageName(), PackageManager.GET_META_DATA);
mUID = info.uid;
} catch (NameNotFoundException e) {
e.printStackTrace();
}
init();
}
/**
* 初始化,初始化当前的网络状态和流量数据
*/
private void init() {
initTrafficStats();
initConnectionMonitor();
}
public void destroy()
{
mContext.unregisterReceiver(mConnectionMonitor);
}
/**
* 初始化网络连接状态
*/
private void initConnectionMonitor() {
// 需要监听网络连接变化事件,以便及时更新connection
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
if (mConnectionMonitor == null) {
mConnectionMonitor = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
stateTransition(context);
}
};
mContext.registerReceiver(mConnectionMonitor, intentFilter);
}
}
/**
* 初始化流量数据
*/
private void initTrafficStats() {
mWifiTraffic = new XWifiTraffic(mUID);
mMobileTraffic = new XMobileTraffic(mUID);
mNoNetworkTraffic = new XNoNetworkTraffic(mUID);
updateCurrentNetwork(mContext);
long totalTraffic = TrafficStats.getUidRxBytes(mUID);
mCurrentNetworkState.updateTotalTraffic(totalTraffic);
}
/**
* 当网络状态改变后,会统计前一个网络状态使用的流量和更新当前网络连接状态
*
* @param context
*/
private void stateTransition(Context context) {
XTrafficStatsBase previousState = updateCurrentNetwork(context);
previousState.updateTraffic();
mCurrentNetworkState.updateTotalTraffic(TrafficStats
.getUidRxBytes(mUID));
}
/**
* 更新当前网络连接状态
*
* @param context
* @return
*/
private XTrafficStatsBase updateCurrentNetwork(Context context) {
XTrafficStatsBase previousState = mCurrentNetworkState;
State mobileState = null;
State wifiState = null;
ConnectivityManager cm = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo wifiNetworkInfo = cm
.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if (null != wifiNetworkInfo) {
wifiState = wifiNetworkInfo.getState();
}
NetworkInfo mobileNetworkInfo = cm
.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if (null != mobileNetworkInfo) {
mobileState = mobileNetworkInfo.getState();
}
if (State.CONNECTED != wifiState && State.CONNECTED == mobileState) {
// 手机网络连接成功
mCurrentNetworkState = mMobileTraffic;
} else if (State.CONNECTED != wifiState
&& State.CONNECTED != mobileState) {
// 手机没有任何的网络
mCurrentNetworkState = mNoNetworkTraffic;
} else if (State.CONNECTED == wifiState) {
// 无线网络连接成功
mCurrentNetworkState = mWifiTraffic;
}
return previousState;
}
/**
* 获取Wifi流量数据,获取的流量是从应用启动到调用接口其间的流量数据
*
* @return 流量数据,单位为KB
*/
public long getWifiTraffic() {
mCurrentNetworkState.updateTraffic();
return mWifiTraffic.getTraffic() / CONST_NUM;
}
/**
* 获取2G和3G流量数据,获取的流量是从应用启动到调用接口其间的流量数据
*
* @return 流量数据,单位为KB
*/
public long getMobileTraffic() {
mCurrentNetworkState.updateTraffic();
return mMobileTraffic.getTraffic() / CONST_NUM;
}
/**
* 负责统计Wifi使用的流量
*/
class XWifiTraffic extends XTrafficStatsBase {
public XWifiTraffic(int uid) {
super(uid);
}
}
/**
* 负责统计Mobile使用的流量
*/
class XMobileTraffic extends XTrafficStatsBase {
public XMobileTraffic(int uid) {
super(uid);
}
}
/**
* 负责统计在没有network状态下的流量,该流量为进程间的通信流量
*/
class XNoNetworkTraffic extends XTrafficStatsBase {
public XNoNetworkTraffic(int uid) {
super(uid);
}
}
}