# trafficDemo **Repository Path**: ddchub/traffic-demo ## Basic Information - **Project Name**: trafficDemo - **Description**: 移动流量监控 demo - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2024-01-06 - **Last Updated**: 2024-01-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # trafficDemo ## 介绍 移动流量监控 demo ## 先上完成效果  ## 编译 环境 及工具 AS4.0 jdk1.8 测试的android系统 6.0 以上 在7.1安卓板 和 手机 android13 上测试了可以使用 。只写了移动流量的展示 ## NetworkStatsManager 的api 说明 ### 1. NetworkStatsManager类 网络数据管理类 Android 6.0后推出的 提供对网络使用历史和统计数据的访问,分为Summary queries(摘要查询)和 History queries(历史查询) 根据实际场景 个人建议尽量使用Summary queries ### 2.我使用的几个api如下 #### 2.1.API方法 ``` 查询网络使用统计摘要。(查询多个应用流量统计) 会返回多个桶 需要循环遍历 在根据uid 的到每一个的实时流量 querySummary(int networkType, String subscriberId, long startTime, long endTime) 查询网络使用统计摘要。结果是整个设备的汇总数据使用情况。结果是随着时间、状态、uid、标签、计量和漫游聚合的单个存储桶 querySummaryForDevice(int networkType, String subscriberId, long startTime, long endTime) ``` #### 2.2.API方法中的参数说明 ``` 1.networkType 查询网络类型 (ConnectivityManager.TYPE_WIFI,ConnectivityManager.TYPE_MOBILE) 2.subscriberId 设备唯一id(android 10及以后设备 获取不了,可不传) 3.startTime 查询指定时间段 开始时间戳 4.endTime 查询指定时间段 结束时间戳 5.uid 查询设备的Uid 这个我用的是在方法里判断了 ``` ### 3. api方法的使用 #### 3.1.querySummaryForDevice的使用 整个设备的汇总数据使用情况 ``` /** * 获取 所有移动使用流量信息 * * @param context 上下文 * @param isDayAndMonth 是否是当天还是当月 * @return 返回 当天 还是当月的流量信息 */ public TrafficBean getAllDay_MonthMobileInfo(Context context, boolean isDayAndMonth) { TrafficBean trafficBean = new TrafficBean(); NetworkStats.Bucket bucket; try { bucket = networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_MOBILE, getSubscriberId(context, ConnectivityManager.TYPE_MOBILE), isDayAndMonth ? getTimesmorning() : getTimesMonthmorning(), System.currentTimeMillis()); } catch (RemoteException e) { return trafficBean; } trafficBean.setRxBytes(bucket.getRxBytes()); trafficBean.setTxBytes(bucket.getTxBytes()); trafficBean.setTotalData(bucket.getTxBytes() + bucket.getRxBytes()); return trafficBean; } ``` #### 3.2.querySummary 的使用 (查询多个应用流量统计) 我使用这个是查询每一个应用的的实时流量情况 **记得使用过后 记得释放 网络统计信息 networkStats.close() 记得判空 我开始没有释放这个,报系统system 异常 但是不影响使用** ``` /** * 获取今日 或者今月的实时流量使用情况 * * @param context 上下文 * @param isDayAndMonth 是否是今天还是今月 * @return 获取今日 或者今月的流量使用情况 */ public TrafficBean getSummaryTrafficMobile(Context context, boolean isDayAndMonth) { TrafficBean trafficBean = new TrafficBean(); trafficBean.setUid(packageUid + ""); NetworkStats networkStats = null; try { networkStats = networkStatsManager.querySummary( ConnectivityManager.TYPE_MOBILE, getSubscriberId(context, ConnectivityManager.TYPE_MOBILE), isDayAndMonth ? getTimesmorning() : getTimesMonthmorning(), System.currentTimeMillis()); long mobileTraffic = 0;// long mobileRx = 0; long mobileTx = 0; NetworkStats.Bucket bucket = new NetworkStats.Bucket(); do { networkStats.getNextBucket(bucket); int summaryUid = bucket.getUid(); if (packageUid == summaryUid) { mobileTx += bucket.getTxBytes(); mobileRx += bucket.getRxBytes(); } } while (networkStats.hasNextBucket()); mobileTraffic = mobileRx + mobileTx; trafficBean.setTxBytes(mobileTx); trafficBean.setRxBytes(mobileRx); trafficBean.setTotalData(mobileTraffic); } catch (RemoteException e) { e.printStackTrace(); } finally { if (networkStats != null) { networkStats.close(); } } return trafficBean; } ``` #### 3.3完整代码NetworkStatsHelper ``` import android.annotation.SuppressLint; import android.app.usage.NetworkStats; import android.app.usage.NetworkStatsManager; import android.content.Context; import android.net.ConnectivityManager; import android.os.Build; import android.os.RemoteException; import android.telephony.TelephonyManager; import androidx.annotation.RequiresApi; import com.tjf.traffic.bean.TrafficBean; /** * @author: tjf * @date: 2022-12-10 * @desc: NetworkStatsHelper 流量查询辅助类 * *
使用方式 * * NetworkStatsManager networkStatsManager = (NetworkStatsManager) getSystemService(NETWORK_STATS_SERVICE); * * NetworkStatsHelper helper = new NetworkStatsHelper(networkStatsManager); *
*/ @RequiresApi(api = Build.VERSION_CODES.M) public class NetworkStatsHelper { NetworkStatsManager networkStatsManager; int packageUid; public void setPackageUid(int packageUid) { this.packageUid = packageUid; } public NetworkStatsHelper(NetworkStatsManager networkStatsManager) { this.networkStatsManager = networkStatsManager; } public NetworkStatsHelper(NetworkStatsManager networkStatsManager, int packageUid) { this.networkStatsManager = networkStatsManager; this.packageUid = packageUid; } /** * 获取 所有移动使用流量信息 * * @param context 上下文 * @param isDayAndMonth 是否是当天还是当月 * @return 返回 当天 还是当月的流量信息 */ public TrafficBean getAllDay_MonthMobileInfo(Context context, boolean isDayAndMonth) { TrafficBean trafficBean = new TrafficBean(); NetworkStats.Bucket bucket; try { bucket = networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_MOBILE, getSubscriberId(context, ConnectivityManager.TYPE_MOBILE), isDayAndMonth ? DateUtil.getTimesmorning() :DateUtil. getTimesMonthmorning(), System.currentTimeMillis()); } catch (RemoteException e) { return trafficBean; } trafficBean.setRxBytes(bucket.getRxBytes()); trafficBean.setTxBytes(bucket.getTxBytes()); trafficBean.setTotalData(bucket.getTxBytes() + bucket.getRxBytes()); return trafficBean; } /** * 获取所有应用一天使用的移动流量信息 * * @param context 上下文 * @param startTime 开始时间 * @return 流量信息 */ public TrafficBean getOneDayMobileInfo(Context context, long startTime) { TrafficBean trafficBean = new TrafficBean(); NetworkStats.Bucket bucket; try { bucket = networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_MOBILE, getSubscriberId(context, ConnectivityManager.TYPE_MOBILE), startTime, startTime + 86400000 ); trafficBean.setRxBytes(bucket.getRxBytes()); trafficBean.setTxBytes(bucket.getTxBytes()); trafficBean.setTotalData(bucket.getTxBytes() + bucket.getRxBytes()); } catch (RemoteException e) { return trafficBean; } return trafficBean; } /** * 获取今日 或者今月的 应用 的实时流量使用情况 * * @param context 上下文 * @param isDayAndMonth 是否是今天还是今月 * @return 获取今日 或者今月的流量使用情况 */ public TrafficBean getSummaryTrafficMobile(Context context, boolean isDayAndMonth) { TrafficBean trafficBean = new TrafficBean(); trafficBean.setUid(packageUid + ""); NetworkStats networkStats = null; try { networkStats = networkStatsManager.querySummary( ConnectivityManager.TYPE_MOBILE, getSubscriberId(context, ConnectivityManager.TYPE_MOBILE), isDayAndMonth ? DateUtil.getTimesmorning() :DateUtil. getTimesMonthmorning(), System.currentTimeMillis()); long mobileTraffic = 0;// long mobileRx = 0; long mobileTx = 0; NetworkStats.Bucket bucket = new NetworkStats.Bucket(); do { networkStats.getNextBucket(bucket); int summaryUid = bucket.getUid(); if (packageUid == summaryUid) { mobileTx += bucket.getTxBytes(); mobileRx += bucket.getRxBytes(); } } while (networkStats.hasNextBucket()); mobileTraffic = mobileRx + mobileTx; trafficBean.setTxBytes(mobileTx); trafficBean.setRxBytes(mobileRx); trafficBean.setTotalData(mobileTraffic); } catch (RemoteException e) { e.printStackTrace(); } finally { if (networkStats != null) { networkStats.close(); } } return trafficBean; } /** * 获取用户id android 10 以后获取不了 传null 即可 * 需要权限 *
* HH:mm:ss SS为零
*
* @return
*/
public static Date firstDayOfMonthData() {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.DAY_OF_MONTH, 1); // M月置1
cal.set(Calendar.HOUR_OF_DAY, 0);// H置零
cal.set(Calendar.MINUTE, 0);// m置零
cal.set(Calendar.SECOND, 0);// s置零
cal.set(Calendar.MILLISECOND, 0);// S置零
return cal.getTime();
}
/**
* 获得当前月的第一天
*
* HH:mm:ss SS为零
*
*
*/
public static long firstDayOfMonth(int DAY_OF_MONTH) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.DAY_OF_MONTH, DAY_OF_MONTH); // M月置1
cal.set(Calendar.HOUR_OF_DAY, 0);// H置零
cal.set(Calendar.MINUTE, 0);// m置零
cal.set(Calendar.SECOND, 0);// s置零
cal.set(Calendar.MILLISECOND, 0);// S置零
return cal.getTimeInMillis();
}
/**
* 获得当前月的第一天到当前时间的时间戳集合
*
* HH:mm:ss SS为零
*
*
*/
public static List getListDayOfMonth() {
List dayOfMonth = new ArrayList<>();
long days = getDayDiff(firstDayOfMonthData(), now());
for (int i = 1; i <= days; i++) {
long day = firstDayOfMonth(i);
dayOfMonth.add(day);
}
Collections.sort(dayOfMonth, new Comparator() {
@Override
public int compare(Long o1, Long o2) {
return (int) (o2 - o1);
}
});
return dayOfMonth;
}
/**
* 获得天数差
*
* @param begin 开始
* @param end 结束
* @return 天数
*/
public static long getDayDiff(Date begin, Date end) {
long day = 1;
if (end.getTime() < begin.getTime()) {
day = -1;
} else if (end.getTime() == begin.getTime()) {
day = 1;
} else {
day += (end.getTime() - begin.getTime()) / (24 * 60 * 60 * 1000);
}
return day;
}
}
```
### 5.主App的结构展示及具体实现
#### 5.1 结构如下图所示

#### 5.2 功能的实现
##### 5.2.1. TrafficActivity 流量监控首页 进行整个流量及每一天的总流量展示
```
import android.app.AppOpsManager;
import android.app.usage.NetworkStatsManager;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Process;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.tjf.traffic.adapter.TrafficDateAdapter;
import com.tjf.traffic.bean.TrafficDayInfo;
import com.tjf.traffic.utils.DateUtil;
import com.tjf.traffic.utils.NetworkStatsHelper;
import com.tjf.traffic.bean.TrafficBean;
import com.tjf.traffic.utils.TrafficFormat;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
/**
* 流量监控首页 进行整个流量及每一天的总流量展示
*/
public class TrafficActivity extends AppCompatActivity {
@BindView(R.id.traffic_list_rev)
RecyclerView trafficListRev;
@BindView(R.id.traffic_month_all_tv)
TextView trafficMonthAllTv;
@BindView(R.id.traffic_day_all_tv)
TextView trafficDayAllTv;
@BindView(R.id.traffic_month_downall_tv)
TextView trafficMonthDownallTv;
@BindView(R.id.traffic_month_upall_tv)
TextView trafficMonthUpallTv;
@BindView(R.id.traffic_day_downall_tv)
TextView trafficDayDownallTv;
@BindView(R.id.traffic_day_upall_tv)
TextView trafficDayUpallTv;
@BindView(R.id.total_traffic_tv)
TextView totalTrafficTv;
@BindView(R.id.total_up_traffic_tv)
TextView totalUpTrafficTv;
@BindView(R.id.total_down_traffic_tv)
TextView totalDownTrafficTv;
@BindView(R.id.traffic_app_sort_lly)
LinearLayout trafficAppSortLly;
@BindView(R.id.traffic_goback)
ImageView trafficGoback;
TrafficDateAdapter trafficDateAdapter;//每天流量展示适配器
NetworkStatsManager networkStatsManager = null;//网络数据管理
NetworkStatsHelper helper = null;//网络数据助手
List dateTraficlist = new ArrayList<>();//每天的流量集合
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_traffic);
ButterKnife.bind(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
networkStatsManager = (NetworkStatsManager) getSystemService(NETWORK_STATS_SERVICE);
}
helper = new NetworkStatsHelper(networkStatsManager);
trafficAppSortLly.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
checkUserAppListPerMission();
}
});
trafficGoback.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
protected void onResume() {
super.onResume();
if (!hasPermissionToReadNetworkStats()) {
Log.i("流量-", "==有权查看使用情况的应用的权限未授权==");
return;
}
Log.i("流量-", "==有权查看使用情况的应用的权限授权成功==");
setTrafficList();
}
@RequiresApi(api = Build.VERSION_CODES.M)
public void setTrafficList() {
TrafficBean monthTraffic = helper.getAllDay_MonthMobileInfo(this, false);
TrafficBean dayTraffic = helper.getAllDay_MonthMobileInfo(this, true);
trafficMonthAllTv.setText(String.format("当月已用总流量\n%s", TrafficFormat.formatByte(
monthTraffic.getTotalData())));
trafficDayAllTv.setText(String.format("当天已用总流量\n%s", TrafficFormat.formatByte(
dayTraffic.getTotalData())));
trafficMonthDownallTv.setText(String.format("当月下载流量\n%s", TrafficFormat.formatByte(
monthTraffic.getRxBytes())));
trafficMonthUpallTv.setText(String.format("当月上传流量\n%s", TrafficFormat.formatByte(
monthTraffic.getTxBytes())));
trafficDayDownallTv.setText(String.format("当天下载流量\n%s", TrafficFormat.formatByte(
dayTraffic.getRxBytes())));
trafficDayUpallTv.setText(String.format("当天上传流量\n%s", TrafficFormat.formatByte(
dayTraffic.getTxBytes())));
getDateAndMonthInfo();
trafficDateAdapter = new TrafficDateAdapter(this,
dateTraficlist, R.layout.traffic_date_item);
trafficListRev.setLayoutManager(new LinearLayoutManager(this));
trafficListRev.setAdapter(trafficDateAdapter);
}
public void startAppListPage() {
Toast.makeText(this, "点击了应用排行", Toast.LENGTH_SHORT).show();
startActivity(new Intent(TrafficActivity.this,
TrafficAppActivity.class));
}
// 打开 "有权查看使用情况的应用"页面
private void requestReadNetworkStats() {
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// 经过测试,只有在 Android 10 及以上加包名才有效果
// 如果在 Android 10 以下加包名会导致无法跳转
intent.setData(Uri.parse("package:" + getPackageName()));
}
startActivity(intent);
}
/**
* 检查是否有有权查看使用情况的应用的权限
*
* @return true false
*/
private boolean hasPermissionToReadNetworkStats() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
Log.i("流量-", "==当前版本小于23==");
return true;
}
final AppOpsManager appOps = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
int mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, Process.myUid(), getPackageName());
if (mode == AppOpsManager.MODE_ALLOWED) {
return true;
}
requestReadNetworkStats();
return false;
}
/**
* 查询应用列表权限进行跳页
*/
public void checkUserAppListPerMission() {
startAppListPage();
}
@RequiresApi(api = Build.VERSION_CODES.M)
public void getDateAndMonthInfo() {
dateTraficlist.clear();
long totalTx = 0;
long totalRx = 0;
long totalTraffic;
List dateList = DateUtil.getListDayOfMonth();
for (Long datelong : dateList) {
TrafficBean oneTraffic = helper.getOneDayMobileInfo(this, datelong);
TrafficDayInfo usageDate = new TrafficDayInfo();
usageDate.setDateDay(datelong);
usageDate.setDateDayStr(DateUtil.getDay(datelong));
usageDate.setTotalRxBytes(TrafficFormat.formatByte(oneTraffic.getRxBytes()));
usageDate.setTotalTxBytes(TrafficFormat.formatByte(oneTraffic.getTxBytes()));
usageDate.setTotalTraffic(TrafficFormat.formatByte(oneTraffic.getTotalData()));
dateTraficlist.add(usageDate);
totalTx += oneTraffic.getTxBytes();
totalRx += oneTraffic.getRxBytes();
}
totalTraffic = totalRx + totalTx;
setTotalTraffic(TrafficFormat.formatByte(totalTraffic),
TrafficFormat.formatByte(totalTx), TrafficFormat.formatByte(totalRx));
Log.i("流量-", "==流量的汇总==\n"
+ TrafficFormat.formatByte(totalTraffic)
+ "\n上传流量合计:" +
TrafficFormat.formatByte(totalTx)
+ "\n下载流量合计:" + TrafficFormat.formatByte(totalRx));
}
/**
* 流量合计
*/
public void setTotalTraffic(String totalTraffic, String upTraffic, String downTraffic) {
totalTrafficTv.setText(String.format("总流量:%s", totalTraffic));
totalUpTrafficTv.setText(String.format("上传总流量:%s", upTraffic));
totalDownTrafficTv.setText(String.format("下载总流量:%s", downTraffic));
}
}
```
##### 5.2.2. TrafficAppActivity 应用流量排行APP页 进行今日和今月列表切换 App流量的排行展示
```
import android.app.usage.NetworkStatsManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.tjf.traffic.adapter.TrafficAppAdapter;
import com.tjf.traffic.bean.TrafficInfo;
import com.tjf.traffic.utils.NetworkStatsHelper;
import com.tjf.traffic.bean.TrafficBean;
import com.tjf.traffic.utils.TrafficFormat;
import com.tjf.traffic.utils.TrafficManagerApp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
/**
* 应用流量排行APP页 进行今日和今月列表切换 App流量的排行展示
*/
public class TrafficAppActivity extends AppCompatActivity {
@BindView(R.id.traffic_list_rev)
RecyclerView trafficListRev;
@BindView(R.id.traffic_day_month_tv)
TextView trafficDayMonthTv;
@BindView(R.id.total_traffic_tv)
TextView totalTrafficTv;
@BindView(R.id.total_up_traffic_tv)
TextView totalUpTrafficTv;
@BindView(R.id.total_down_traffic_tv)
TextView totalDownTrafficTv;
@BindView(R.id.traffic_goback)
ImageView trafficGoback;
TrafficAppAdapter trafficAppAdapter;
NetworkStatsManager networkStatsManager = null;
NetworkStatsHelper helper;
List trafficApplist = new ArrayList<>();
TrafficManagerApp trafficManagerApp;
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_traffic_app);
ButterKnife.bind(this);
trafficManagerApp = new TrafficManagerApp(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
networkStatsManager = (NetworkStatsManager) getSystemService(NETWORK_STATS_SERVICE);
}
helper = new NetworkStatsHelper(networkStatsManager);
getDayAndMonthInfo(true);
trafficAppAdapter = new TrafficAppAdapter(this,
trafficApplist, R.layout.traffic_app_item);
trafficListRev.setLayoutManager(new LinearLayoutManager(this));
trafficListRev.setAdapter(trafficAppAdapter);
trafficDayMonthTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (trafficDayMonthTv.getText().toString().equals("今日")) {
trafficDayMonthTv.setText("今月");
getDayAndMonthInfo(false);
} else if (trafficDayMonthTv.getText().toString().equals("今月")) {
trafficDayMonthTv.setText("今日");
getDayAndMonthInfo(true);
}
Toast.makeText(TrafficAppActivity.this,
"点击了" + trafficDayMonthTv.getText().toString(), Toast.LENGTH_SHORT).show();
if (trafficAppAdapter != null) {
trafficAppAdapter.notifyDataSetChanged();
}
}
});
trafficGoback.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
@RequiresApi(api = Build.VERSION_CODES.M)
public void getDayAndMonthInfo(boolean isDayAndMonth) {
trafficApplist.clear();
trafficApplist.addAll(trafficManagerApp.getInternetTrafficInfos());
long totalTx = 0;
long totalRx = 0;
long totalTraffic;
for (TrafficInfo trafficInfo : trafficApplist) {
helper.setPackageUid(trafficInfo.getUid());
TrafficBean trafficBean = helper.getSummaryTrafficMobile(this, isDayAndMonth);
trafficInfo.setTraffic(TrafficFormat.formatByte(trafficBean.getTotalData()));
trafficInfo.setMobleTotalData(trafficBean.getTotalData());
trafficInfo.setMobleRxBytes(trafficBean.getRxBytes());
trafficInfo.setMobleTxBytes(trafficBean.getTxBytes());
totalTx += trafficBean.getTxBytes();
totalRx += trafficBean.getRxBytes();
}
totalTraffic = totalRx + totalTx;
Log.i("流量-", "==流量的汇总==\n"
+ TrafficFormat.formatByte(totalTraffic)
+ "\n上传流量合计:" +
TrafficFormat.formatByte(totalTx)
+ "\n下载流量合计:" + TrafficFormat.formatByte(totalRx));
setTotalTraffic(TrafficFormat.formatByte(totalTraffic),
TrafficFormat.formatByte(totalTx), TrafficFormat.formatByte(totalRx));
for (int i = trafficApplist.size() - 1; i >= 0; i--) {
TrafficInfo trafficInfo = trafficApplist.get(i);
if (trafficInfo.getTraffic().startsWith("0")) {
trafficApplist.remove(i);
}
}
Log.i("流量-", "过滤后的app的数量=" + trafficApplist.size());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Collections.sort(trafficApplist, new Comparator() {
@Override
public int compare(TrafficInfo o1, TrafficInfo o2) {
//流量最大值排列
int max = (int) (o2.getMobleTotalData() - o1.getMobleTotalData());
return max;
}
});
}
}
/**
* 流量合计
*/
public void setTotalTraffic(String totalTraffic, String upTraffic, String downTraffic) {
totalTrafficTv.setText(String.format("总流量:%s", totalTraffic));
totalUpTrafficTv.setText(String.format("上传总流量:%s", upTraffic));
totalDownTrafficTv.setText(String.format("下载总流量:%s", downTraffic));
}
```
##### 5.2.3. 具体布局及整体实现请看开头的gif 或者源码 自行实现
demo项目地址 https://toscode.gitee.com/code_tjf/traffic-demo
### 6.下面是参考的博客地址:
https://blog.csdn.net/Rookie_or_beginner/article/details/123376004?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-123376004-blog-8440160.pc_relevant_multi_platform_whitelistv4&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-123376004-blog-8440160.pc_relevant_multi_platform_whitelistv4&utm_relevant_index=1
### 7.完结
