diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 883453b..408511f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,10 +11,15 @@ - + + + + diff --git a/app/src/main/java/com/yinuo/safetywatcher/TestUtils.kt b/app/src/main/java/com/yinuo/safetywatcher/TestUtils.kt index 11cac61..e30b744 100644 --- a/app/src/main/java/com/yinuo/safetywatcher/TestUtils.kt +++ b/app/src/main/java/com/yinuo/safetywatcher/TestUtils.kt @@ -1,11 +1,17 @@ package com.yinuo.safetywatcher +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.os.Build +import android.provider.Settings import com.yinuo.safetywatcher.watcher.db.DBUtils import com.yinuo.safetywatcher.watcher.db.entity.Gas import com.yinuo.safetywatcher.watcher.db.entity.GasType import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch + object TestUtils { @@ -46,4 +52,14 @@ object TestUtils { gasDao.insertAll(gases) } } + + private fun requestReadNetworkStats(context: Context) { + val intent = Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + // 经过测试,只有在 Android 10 及以上加包名才有效果 + // 如果在 Android 10 以下加包名会导致无法跳转 + intent.data = Uri.parse("package:" + context.getPackageName()) + } + context.startActivity(intent) + } } \ No newline at end of file diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/bean/TrafficBean.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/bean/TrafficBean.java new file mode 100644 index 0000000..fd9de7e --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/bean/TrafficBean.java @@ -0,0 +1,58 @@ +package com.yinuo.safetywatcher.watcher.bean; + +import com.yinuo.safetywatcher.watcher.utils.TrafficFormat; + +/** + * @author: tjf + * @date: 2022-12-10 + * @desc: 移动流量实体类 + */ +public class TrafficBean { + + + private long TotalData;// 总流量数据 + private long RxBytes;//移动 下载字节 + private long TxBytes;//移动 上传字节 + String uid;//包名uid + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public long getTotalData() { + return TotalData; + } + + public void setTotalData(long totalData) { + TotalData = totalData; + } + + public long getRxBytes() { + return RxBytes; + } + + public void setRxBytes(long rxBytes) { + RxBytes = rxBytes; + } + + public long getTxBytes() { + return TxBytes; + } + + public void setTxBytes(long txBytes) { + TxBytes = txBytes; + } + + @Override + public String toString() { + return "TrafficBean{" + + "TotalData=" + TrafficFormat.formatByte(TotalData) + + ", RxBytes=" + TrafficFormat.formatByte(RxBytes) + + ", TxBytes=" +TrafficFormat.formatByte( TxBytes )+ + '}'; + } +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/NetSettingActivity.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/NetSettingActivity.kt index 793ee45..761aede 100644 --- a/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/NetSettingActivity.kt +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/NetSettingActivity.kt @@ -1,12 +1,16 @@ package com.yinuo.safetywatcher.watcher.ui import android.annotation.SuppressLint +import android.app.usage.NetworkStatsManager import android.content.Intent import android.provider.Settings import android.view.View import com.yinuo.safetywatcher.R import com.yinuo.safetywatcher.databinding.ActivityNetSettingBinding import com.yinuo.safetywatcher.watcher.base.NoOptionsActivity +import com.yinuo.safetywatcher.watcher.utils.NetworkStatsHelper +import com.yinuo.safetywatcher.watcher.utils.TrafficFormat + class NetSettingActivity : NoOptionsActivity() { private val mBinding by lazy { @@ -24,12 +28,17 @@ class NetSettingActivity : NoOptionsActivity() { @SuppressLint("SetTextI18n") override fun initView() { mBinding.apply { - val usedValue = 100 - tvUsed.text = "流量使用情况:$usedValue G" itemWifi.setOnClickListener { Intent.ACTION_FACTORY_TEST startActivity(Intent(Settings.ACTION_WIFI_SETTINGS)) } } + + //流量使用情况 + val systemService = getSystemService(NETWORK_STATS_SERVICE) as NetworkStatsManager + val statsHelper = NetworkStatsHelper(systemService) + val info = statsHelper.getAllDay_MonthMobileInfo(this, false) + val showStr = if (info != null) TrafficFormat.formatByte(info.totalData) else "0B" + mBinding.tvUsed.text = "流量使用情况:$showStr" } } \ No newline at end of file diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/utils/NetworkStatsHelper.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/utils/NetworkStatsHelper.java new file mode 100644 index 0000000..1f11740 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/utils/NetworkStatsHelper.java @@ -0,0 +1,178 @@ +package com.yinuo.safetywatcher.watcher.utils; + +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.yinuo.safetywatcher.watcher.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 ? TrafficFormat.getTimesmorning() : TrafficFormat.getTimesMonthmorning(), + System.currentTimeMillis()); + } catch (RemoteException e) { + return trafficBean; + } + if (bucket != null) { + 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 即可 + * 需要权限 + * + * + * @param context 上下文 + * @param networkType 网络类型 + * @return null + */ + @SuppressLint("MissingPermission") + private String getSubscriberId(Context context, int networkType) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + return null; + } + + if (ConnectivityManager.TYPE_MOBILE == networkType) { + TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + return tm.getSubscriberId(); + } + return null; + } + + +} + \ No newline at end of file diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/utils/TrafficFormat.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/utils/TrafficFormat.java new file mode 100644 index 0000000..a6f2501 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/utils/TrafficFormat.java @@ -0,0 +1,68 @@ +package com.yinuo.safetywatcher.watcher.utils; + +import java.text.DecimalFormat; +import java.util.Calendar; + +/** + * @author: tjf + * @desc: 流量文本格式化工具类 + */ +public class TrafficFormat { + //定义TB的计算常量 + private static final double TB = 1024f * 1024f * 1024f * 1024f; + //定义GB的计算常量 + private static final double GB = 1024f * 1024f * 1024f; + //定义MB的计算常量 + private static final double MB = 1024f * 1024f; + //定义KB的计算常量 + private static final double KB = 1024f; + + /** + * 格式化数据 + * + * @param data + * @return + */ + public static String formatByte(long data) { + + DecimalFormat format = new DecimalFormat("####.##"); + if (data < KB) { + return data + "B"; + } else if (data < MB) { + return format.format(data / KB) + "KB"; + } else if (data < GB) { + return format.format(data / MB) + "MB"; + } else if (data < TB) { + return format.format(data / GB) + "GB"; + } else { + return "超出统计范围"; + } + } + + /** + * 获取当天的零点时间 + */ + public static long getTimesmorning() { + Calendar cal = Calendar.getInstance(); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.MILLISECOND, 0); + return (cal.getTimeInMillis()); + } + + + /** + * 获得本月第一天0点时间 + */ + public static long getTimesMonthmorning() { + 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.getTimeInMillis(); + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 889e3e5..4f95d20 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,5 +1,5 @@ - My Application + Watcher 设置 数据查询 报警记录