代码之家  ›  专栏  ›  技术社区  ›  RRTW

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

  •  15
  • RRTW  · 技术社区  · 13 年前

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

    我可以得到如下结果:

    • Youtube 5030 MB
    • 脸书2139 MB
    • 谷歌播放103.38 MB
    • (以及更多…)

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

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

    4 回复  |  直到 13 年前
        1
  •  8
  •   ChuongPham    11 年前

    晚上好,我有办法。。。

    首先,我必须创建一个扩展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。

        2
  •  5
  •   ByteHamster hexerei software    10 年前

    经过长时间的挣扎,我能够找到解决方案,通过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. 获取活动订阅者ID:

      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()));
      
      }
      
        3
  •  2
  •   er reflex    11 年前

    我找到了只获取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总字节 它对我有用我希望对你有用

        4
  •  -2
  •   G M Ramesh    13 年前

    尝试以下代码,关闭“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。让我们继续声明三个私有类变量。

    主类

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