安卓统计每个应用程序的3g流量,如何



对于每个应用程序的网络流量统计,我现在使用的是Android TrafficStats

我可以得到如下结果:

  • Youtube 50.30 MB
  • Facebook 2139 MB
  • Google Play 103.38 MB
  • (以及更多…)

正如我所知,"Android Trafficstats"只是一个指向c文件的本地指针。(也许是.so?)

但它混合了Wifi&3g流量,有没有办法只获取非WiFi流量统计?

晚上,我有办法做到这一点。。。

首先,我必须创建一个扩展BroadcastrReceiver的类,如下所示:

清单定义:

<receiver android:name=".core.CoreReceiver" android:enabled="true" android:exported="false">
<intent-filter>
<action android:name="android.net.ConnectivityManager.CONNECTIVITY_ACTION" />
<action android:name="android.net.wifi.STATE_CHANGE" />
</intent-filter>
</receiver>

代码:

/**
* @author me
*/
public class CoreReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
if (Constants.phone == null) {
// Receive [network] event
Constants.phone=new PhoneListen(context);
TelephonyManager telephony=(TelephonyManager) 
context.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(Constants.phone, PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);
}
WifiManager wifi=(WifiManager)context.getSystemService(Context.WIFI_SERVICE);
boolean b=wifi.isWifiEnabled();
if (Constants.STATUS_WIFI != b) {
// WiFi status changed...
}
}
}

下面是一个电话统计收听者。。。

public class PhoneListen extends PhoneStateListener {
private Context context;    
public PhoneListen(Context c) {
context=c;
}    
@Override
public void onDataConnectionStateChanged(int state) {
switch(state) {
case TelephonyManager.DATA_DISCONNECTED:// 3G
//3G has been turned OFF
break;
case TelephonyManager.DATA_CONNECTING:// 3G
//3G is connecting
break;
case TelephonyManager.DATA_CONNECTED:// 3G
//3G has turned ON
break;
}
}
}

最后,这是我的逻辑

  1. 将计数收集到SQLite数据库中
  2. 仅当3G开启时,每1分钟通过TrafficStats收集所有应用程序网络使用情况
  3. 如果3G关闭,则停止收集
  4. 如果3G&WiFi打开,停止收集

正如我所知,网络流量将只通过WiFi,如果3G&提供WiFi。

经过长期的努力,我能够找到通过android中每个安装的应用程序的任何接口获取数据的解决方案装置

由于Android提供TrafficStats Apis,但这些API提供了自设备启动以来每个应用程序uid的编译数据统计信息,甚至API不支持通过特定应用程序的任何接口获取数据。即使我们依赖TraffiucStates APIS,我们也会为每个应用程序获取新的数据统计信息。

所以我想使用隐藏的API来使用这个。。

在这里,我提到了在Android中的任何接口上获取每个应用程序的数据统计的步骤。。。

  1. 建立"INetworkStatsSession"会话

    import android.net.INetworkStatsSession;
    INetworkStatsSession mStatsSession = mStatsService.openSession();
    
  2. 根据要测量的接口创建网络模板。。

    import static android.net.NetworkTemplate.buildTemplateEthernet;
    import static android.net.NetworkTemplate.buildTemplateMobile3gLower;
    import static android.net.NetworkTemplate.buildTemplateMobile4g;
    import static android.net.NetworkTemplate.buildTemplateMobileAll;
    import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
    import android.net.NetworkTemplate;
    private NetworkTemplate mTemplate;
    mTemplate = buildTemplateMobileAll(getActiveSubscriberId(this
    .getApplicationContext()));
    
  3. GetActive SubscriberID:

    private static String getActiveSubscriberId(Context context) {
    final TelephonyManager tele = TelephonyManager.from(context);
    final String actualSubscriberId = tele.getSubscriberId();
    return SystemProperties.get(TEST_SUBSCRIBER_PROP, actualSubscriberId);
    }
    
  4. 通过传递应用程序UID来收集各个应用程序的网络HIStory。。。

    private NetworkStatsHistory collectHistoryForUid(NetworkTemplate template,
    int uid, int set) throws RemoteException {
    final NetworkStatsHistory history = mStatsSession.getHistoryForUid(
    template, uid, set, TAG_NONE, FIELD_RX_BYTES | FIELD_TX_BYTES);
    return history;
    }
    
  5. 获取总消耗数据:

    public void showConsuption(int UID){
    NetworkStatsHistory history = collectHistoryForUid(mTemplate, UID,
    SET_DEFAULT);
    Log.i(DEBUG_TAG, "load:::::SET_DEFAULT:.getTotalBytes:"+ Formatter.formatFileSize(context, history.getTotalBytes()));
    history = collectHistoryForUid(mTemplate, 10093,
    SET_FOREGROUND);
    Log.i(DEBUG_TAG, "load::::SET_FOREGROUND::.getTotalBytes:"+ Formatter.formatFileSize(context, history.getTotalBytes()));
    history = collectHistoryForUid(mTemplate, 10093,
    SET_ALL);
    Log.i(DEBUG_TAG, "load::::SET_ALL::.getTotalBytes:"+ Formatter.formatFileSize(context, history.getTotalBytes()));
    }
    

我找到了只获取wifi流量的方法

long totalbyte = Trafficstats.getTotalRxBytes();
long mobilenetworkbyte = Trafficstats.getMobileRxBytes();
String total = Long.toString(totalbyte);
String mobile = Long.toString(mobilenetworkbyte);
String wifibyte = total - mobile + "kb";

现在wifi字节字符串显示wifi总字节这对我来说很好,我希望对你来说很好

尝试以下代码并关闭"WIFI",只使用"3G"进行检查

  1. 在Eclipse中创建一个新的Android项目。请记住使用TrafficStats类,您必须针对Android 2.2(Froyo)或更高版本的API。

  2. 在/res/layout文件夹中,我们将创建一个main.xml资源。对于这个项目,我们只是在垂直堆叠的线性布局中使用一系列文本视图。

    main.xml
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textSize="16sp"
    android:textStyle="bold"
    android:gravity="center"
    android:paddingBottom="20dip"
    android:text="Traffic Stats Demo" />
    <TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textSize="14sp"
    android:textColor="#00ff00"
    android:gravity="center"
    android:text="Transmit Bytes" />
    <TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textSize="14sp"
    android:gravity="center"
    android:text="0"
    android:id="@+id/TX"/>
    <TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textSize="14sp"
    android:textColor="#ff0000"
    android:gravity="center"
    android:text="Receive Bytes" />
    <TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textSize="14sp"
    android:gravity="center"
    android:text="0"
    android:id="@+id/RX"/>
    </LinearLayout>
    
  3. 布局到位后,我们可以转到/src文件夹。通过扩展Activity类创建Main.java。让我们继续声明三个私有类变量。

Main.java

package com.authorwjf;
import android.app.Activity;
import android.app.AlertDialog;
import android.net.TrafficStats;
import android.os.Bundle;
import android.os.Handler;
import android.widget.TextView;
public class Main extends Activity {
private Handler mHandler = new Handler();
private long mStartRX = 0;
private long mStartTX = 0;
}
  1. 我们将使用on create覆盖来初始化我们的私有变量,并在UI线程上调度回调。记下对枚举TrafficStats.UNSUPPORTED的检查。虽然我使用TrafficStats类的经验没有遇到任何问题,但谷歌官方文档指出,一些设备可能不支持这种类型的报告,在这种情况下,调用会返回上述值。因此,正如我在这里演示的那样,编写防御性代码是个好主意。

    Main.java
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    mStartRX = TrafficStats.getTotalRxBytes();
    mStartTX = TrafficStats.getTotalTxBytes();
    if (mStartRX == TrafficStats.UNSUPPORTED || mStartTX ==     TrafficStats.UNSUPPORTED) {
    AlertDialog.Builder alert = new AlertDialog.Builder(this);
    alert.setTitle("Uh Oh!");
    alert.setMessage("Your device does not support traffic stat monitoring.");
    alert.show();
    } else {
    mHandler.postDelayed(mRunnable, 1000);
    }
    }
    
  2. 最后但并非最不重要的是,我们需要更新我们的显示并重新安排可运行。

    Main.java
    private final Runnable mRunnable = new Runnable() {
    public void run() {
    TextView RX = (TextView)findViewById(R.id.RX);
    TextView TX = (TextView)findViewById(R.id.TX);
    long rxBytes = TrafficStats.getTotalRxBytes()- mStartRX;
    RX.setText(Long.toString(rxBytes));
    long txBytes = TrafficStats.getTotalTxBytes()- mStartTX;
    TX.setText(Long.toString(txBytes));
    mHandler.postDelayed(mRunnable, 1000);
    }
    };
    

最新更新