苏州建设银行网站,西安最新通告公告,广东省建设系统数据开放平台,绍兴网站建设方案推广关于作者#xff1a;CSDN内容合伙人、技术专家#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 #xff0c;擅长java后端、移动开发、商业变现、人工智能等#xff0c;希望大家多多支持。 目录 一、导读二、概览三、相关工具3.1 network profiler/ In… 关于作者CSDN内容合伙人、技术专家 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 擅长java后端、移动开发、商业变现、人工智能等希望大家多多支持。 目录 一、导读二、概览三、相关工具3.1 network profiler/ Inspector3.2 抓包工具3.3 三方库 stetho3.4 通过 TrafficStats 来统计流量3.5 通过 NetworkStatsManager 来统计流量 四、优化五、 推荐阅读 一、导读
我们继续总结学习基础知识温故知新。
本文主要讲述网络优化相关的概念及思路。
HTTP即超文本传输协议HyperText Transfer Protocol 是一个简单的请求-响应协议它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应(百度百科)。
二、概览
针对网络优化的维度比较多可以从多方面入手 比如流量使用情况单位时间内流量消耗用户网络类型是否前后台等 添加流量监控最好从请求开始到结束的完整流程。 再比如网络请求的成功率、请求速度等等。
网络的测试细节会比较多我们要充分的进行线下测试并进行多维度的模拟如弱网、无网、网络切换等。 为了更精准的测试我们app的流量可以在设置里面将其他app联网权限关闭。
对于线上用户监控在客户端也要多维度监控尽可能多的获取信息以便排查问题要获取到接口的每一步详细信息 如某个接口的dns解析时间连接时间、请求时间请求状态网络包大小网络状态等等再配合用户日志系统进行统一收集展示。
三、相关工具
3.1 network profiler/ Inspector
目前网络性能剖析器仅支持 HttpURLConnection 和 OkHttp 网络连接库。 在新包的android studio profiler上已经移除在新的菜单中。 打开方式如下 View Tool Windows App Inspection
如下图所示
这个工具会实时显示网络活动包括发送、接受的数据及连接数、状态等。
使用方式大家自行学习吧比较简单。 官网链接
3.2 抓包工具
要熟悉一些抓包工具如 charles fidder
工具的使用请自行学习。
3.3 三方库 stetho
stetho是facebook开发的一个开源库Android应用通过引入stetho可以在Chrome/Chromium浏览器监控查看网络请求、数据库、SharedPreferences、UI布局层级等.
chrome://inspect/Stetho库的地址
工具的使用请自行学习。
3.4 通过 TrafficStats 来统计流量
我们使用 android.net.TrafficStats 类 来统计流量 这个类只在api 18 以上才有用来统计手机重启以来的流量使用情况。
其实本身TrafficStats类也是读取Linux提供的文件对象系统类型的文本进行解析。 android.net.TrafficStats类中提供了多种静态方法可以直接调用获取返回类型均为 long型如果返回等于-1代表 UNSUPPORTED 当前设备不支持统计。
static long getMobileRxBytes() //获取通过Mobile连接收到的字节总数不包含WiFi
static long getMobileRxPackets() //获取Mobile连接收到的数据包总数
static long getMobileTxBytes() //Mobile发送的总字节数
static long getMobileTxPackets() //Mobile发送的总数据包数
static long getTotalRxBytes() //获取总的接受字节数包含Mobile和WiFi等
static long getTotalRxPackets() //总的接受数据包数包含Mobile和WiFi等
static long getTotalTxBytes() //总的发送字节数包含Mobile和WiFi等
static long getTotalTxPackets() //发送的总数据包数包含Mobile和WiFi等
static long getUidRxBytes(int uid) //获取某个网络UID的 接受 字节数
static long getUidTxBytes(int uid) //获取某个网络UID的 发送字节数 我们可以间隔一段时间读取一下使用的流量, public void start() {uid Process.myUid();thread new HandlerThread(123);thread.start();handler new Handler(thread.getLooper()) {Overridepublic void handleMessage(NonNull Message msg) {if (msg.what 1) {// TODO: 比如计算一下差值handler.sendEmptyMessageDelayed(1, 5 * 60 * 1000);}}};handler.sendEmptyMessageDelayed(1, 5 * 60 * 1000);}1无法获取应用的数据流量消耗 从文档中仅能获取到指定uid的流量但无法区分不同网络类型下的消耗 2无法获取某个时间段内的流量消耗
3.5 通过 NetworkStatsManager 来统计流量
精准统计流量消耗的方法 可以获取指定时间间隔内的流量消耗。
NetworkCapabilities.TRANSPORT_WIFI
NetworkStatsManager networkStatsManager (NetworkStatsManager) getSystemService(NETWORK_STATS_SERVICE);//查询 指定网络类型 在 某时间间隔内 的总的流量统计信息
NetworkStats.Bucket querySummaryForDevice(int networkType, String subscriberId, long startTime, long endTime)//查询某uid在 指定网络类型 和 时间间隔内 的流量统计信息
NetworkStats queryDetailsForUid(int networkType, String subscriberId, long startTime, long endTime, int uid) //查询 指定网络类型 在 某时间间隔内 的详细的流量统计信息包括每个uid
NetworkStats queryDetails(int networkType, String subscriberId, long startTime, long endTime) 需要添加权限
uses-permission android:nameandroid.permission.READ_PHONE_STATE /
uses-permission android:nameandroid.permission.PACKAGE_USAGE_STATS tools:ignoreProtectedPermissions/使用
RequiresApi(api Build.VERSION_CODES.M)public static long getNetStats(NonNull Context context, long startTime, long endTime, int netType) {// 接收的流量long netDataReceive 0;// 发送的流量long netDataSend 0;String subId null;// 通过 service获取NetworkStatsManager manager (NetworkStatsManager) context.getApplicationContext().getSystemService(Context.NETWORK_STATS_SERVICE);if (manager null) {return 0;}NetworkStats networkStats null;NetworkStats.Bucket bucket new NetworkStats.Bucket();try {// //查询 指定网络类型, 在 某时间间隔内 的总的流量统计信息networkStats manager.querySummary(netType, subId, startTime, endTime);} catch (Exception e) {e.printStackTrace();}//查询某应用uid的数据流量统计信息while (networkStats ! null networkStats.hasNextBucket()) {networkStats.getNextBucket(bucket);int uid bucket.getUid();if (getAppUid(context) uid) {// 接收的流量netDataReceive bucket.getRxBytes();// 发送的流量netDataSend bucket.getTxBytes();}}// 返回总流量 这个量跟在设置里面看应该是差不多的return (netDataReceive netDataSend);}这个方式在线上排查问题还是有用的比如我们可以获取用户昨天的流量消耗情况这些信息一起写入用户行为日志中进行辅助排查。
这个时候最好带上用户所处的状态比如是否在前后台等等。
前后台流量消耗统计 当然我们也可启用定时任务如TrafficStats获取流量的方式隔一段时间记录一次并且区分前后台然后统一上报。
网络请求流量优化
四、优化
在应用内使用网络的情况非常多比如各种功能接口api图片日志等那么我们要优化的话可以从下面几个方面入手。
数据缓存一些不常用的数据进行网络缓存设定过期时间。增量更新根据版本进行更新。数据压缩如gzip。图片处理进行压缩
页面打不开、打开慢、图片加载不出来等等大部分都是由于网络加载慢请求成功率低导致。 我们先来看下http请求的流程 图片来源网络
dns被劫持或者dns解析速度慢都是导致网络慢所以要防劫持可以使用httpdns绕过运营商域名解析我们稍微解释下 httpdns HTTPDNS是面向多端应用移动端APPPC客户端应用的域名解析服务具有域名防劫持、精准调度、实时解析生效的特性。
其工作流程是这样的图片来源于 阿里dns文章
使用httpdns可以降低平均访问时长提高链接成功率防止劫持。
尽量使用最新版的http协议里面有很多的网络优化。
另外我们自己需要统计一下接口请求耗时成功率错误码等等通过okhttp 的eventlistener就可以实现如果是其他的网络链接可自行调研。 public class OkHttpEventListener extends EventListener {Overridepublic void callStart(Call call) {super.callStart(call);}Overridepublic void dnsStart(Call call, String domainName) {super.dnsStart(call, domainName);}Overridepublic void dnsEnd(Call call, String domainName, ListInetAddress inetAddressList) {super.dnsEnd(call, domainName, inetAddressList);}Overridepublic void responseBodyStart(Call call) {super.responseBodyStart(call);}Overridepublic void responseBodyEnd(Call call, long byteCount) {super.responseBodyEnd(call, byteCount);}Overridepublic void callEnd(Call call) {super.callEnd(call);}Overridepublic void callFailed(Call call, IOException ioe) {super.callFailed(call, ioe);}...
}我们可以看到里面有很多的回调在对应的方法里面计算时间差就可以算出请求时间。
而对于图片监控来说 如果使用的是 Fresco 则直接可以使用sdk提供的方法来做监控在内部有一个 com.facebook.imagepipeline.listener.RequestListener类 可以监控到具体的每一步。 我们只需要在fresco初始化时设置一个监听即可
ImagePipelineConfig config ImagePipelineConfig.newBuilder(mContext).setRequestListeners(listenerset) // 设置监听.setRequestListener2s() // 设置监听.build();Fresco.initialize(mContext,config);通过接口可以拿到成功失败及失败原因
public interface RequestListener2 extends ProducerListener2 {void onRequestStart(ProducerContext producerContext);void onRequestSuccess(ProducerContext producerContext);void onRequestFailure(ProducerContext producerContext, Throwable throwable);void onRequestCancellation(ProducerContext producerContext);
}
如果是其他的图片加载库可自行调研。
最后针对服务端需要做好网络容灾方案。
五、 推荐阅读
Java 专栏
SQL 专栏
数据结构与算法
Android学习专栏