对于每个APP的统计网络流量,我现在使用的是Android TrafficStats
我可以得到如下结果:
- Youtube 50.30 MB
- 脸书 21.39 MB
- 谷歌播放 103.38 MB
- (和更多...)
据我所知,“Android Trafficstats”只是一个指向 ac 文件的本机指针。(也许是 .so ?)
但它混合了 Wifi 和 3g 流量,有没有办法只获得非 WiFi 流量统计?
对于每个APP的统计网络流量,我现在使用的是Android TrafficStats
我可以得到如下结果:
据我所知,“Android Trafficstats”只是一个指向 ac 文件的本机指针。(也许是 .so ?)
但它混合了 Wifi 和 3g 流量,有没有办法只获得非 WiFi 流量统计?
晚上,我有办法做到这一点......
首先,我必须创建一个扩展 BroadcasrReceiver 的类,如下所示:
清单定义:
<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;
}
}
}
最后,这是我的逻辑
据我所知,如果 3G 和 WiFi 都可用,网络流量将仅通过 WiFi。
经过长时间的努力,我能够找到通过任何接口为每个已安装应用程序在 android 设备中获取数据的解决方案。
由于 Android 提供了 TrafficStats API,但这些 API 为每个应用程序 uid 提供编译数据统计信息,因为设备启动并且甚至 API 不支持通过特定应用程序的任何接口获取数据。即使我们依赖 TraffiucStates APIS,我们也会为每个应用程序获得一个新的数据统计信息。
所以我想使用隐藏的 API 来使用它..
在这里,我提到了通过 Android 中的任何接口获取每个应用程序的数据统计信息的步骤...
建立“INetworkStatsSession”会话
import android.net.INetworkStatsSession;
INetworkStatsSession mStatsSession = mStatsService.openSession();
根据您要测量的接口创建网络模板..
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()));
GetActive 订阅者 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);
}
通过传递应用程序 UID 收集各个应用程序的网络历史记录...
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;
}
获取总消费数据:
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";
现在wifibyte字符串显示wifi总字节它对我有用我希望对你有用
尝试以下代码并关闭您的“WIFI”并仅检查“3G”
在 Eclipse 中创建一个新的 Android 项目。请记住使用 TrafficStats 类,您必须针对 Android 2.2 (Froyo) 或更高版本的 API。
在 /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>
布局到位后,我们可以转到 /src 文件夹。通过扩展 Activity 类创建 Main.java。让我们继续声明三个私有类变量。
主.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;
}
我们将使用 on create override 来初始化我们的私有变量,并在 UI 线程上安排回调。记下对枚举 TrafficStats.UNSUPPORTED 的检查。虽然我对 TrafficStats 类的体验一帆风顺,但 Google 官方文档指出,某些设备可能不支持这种类型的报告,在这种情况下,调用会返回上述值。出于这个原因,防御性地编写代码是一个好主意,正如我在这里演示的那样。
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);
}
}
最后但并非最不重要的一点是,我们需要更新我们的显示并重新安排可运行文件。
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);
}
};