http 1.0 TCP链接不复用 http 1.1 引入持久连接,数据按照次序进行 http 2.0 多工 客户端服务端 双向实时通信
1.网络检测工具
1. Network Profiler
只支持httpurlconnection 和okhttp 请求 开启高级分析 run --edit configure —profiling
androidstudio 高版本都已经支持该功能
2.charles
Charles 是在 PC 端常用的网络封包截取工具,在做移动开发时,我们为了调试与服务器端的网络通讯协议,常常需要截取网络封包来分析。除了在做移动开发中调试端口外,Charles 也可以用于分析第三方应用的通讯协议。配合 Charles 的 SSL 功能,Charles 还可以分析 Https 协议。 可以模拟弱网 使用本地数据模拟接口、断点连接。 https://juejin.cn/post/6844903665304600589
3.stetho
可以查看设备的数据库 、网络请求、 https://github.com/facebook/stetho
implementation 'com.facebook.stetho:stetho:1.6.0'
public class MyApplication extends Application {
public void onCreate() {
super.onCreate();
Stetho.initializeWithDefaults(this);
}
}
在chrome里 输入 chrome://inspect/#devices :
连接设备就可以查看了
2.精准获取流量
设置–流量管理 抓包工具:只允许APP联网
1 NetworkStatsManager (推荐)
NetworkStatsManager Api 23 以后监测流量的方案. 可以指定时间间隔内的流量信息,可以线上使用。 不同网络类型下的消耗。
@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;
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();
}
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 Api18以上使用,重启以来的流量数据,以前的数据会被删除,了解即可 不能获取某个时间段内的流量消耗。
2.后台流量检测方案
后台定时任务—获取间隔内流量–记录前后台–分别计算–上报APM后台–流量处理
3.数据缓存
给okhttp 添加cache拦截器。在无网络的情况下,缓存上次的数据。
4.数据压缩
post请求body使用Gzip压缩 请求头压缩
5.图片压缩上传
luban 第三方库 https://github.com/Curzibn/Luban
implementation 'top.zibin:Luban:1.1.8'
load 传入原图 filter 设置开启压缩条件 ignoreBy 不压缩的阈值,单位为K setFocusAlpha 设置是否保留透明通道 setTargetDir 缓存压缩图片路径 setCompressListener 压缩回调接口 setRenameListener 压缩前重命名接口
Luban.with(holder.imageView.getContext())
.load(Environment.getExternalStorageDirectory()+"/Android/1.jpg")
.setTargetDir(Environment.getExternalStorageDirectory()+"/Android")
.launch();
6.网络质量差 (DNS)
请求成功率 请求速度快
请求到达运营商DNS相关 (DNS被劫持,DNS解析慢) HttpDNS 绕过运营商域名解析过程。 降低访问平均时长。
使用阿里云提供DNS服务
compile ('com.aliyun.ams:alicloud-android-httpdns:1.1.7@aar') {
transitive true
}
public class OkHttpDNS implements Dns {
private HttpDnsService dnsService;
private static OkHttpDNS instance = null;
private OkHttpDNS(Context context) {
dnsService = HttpDns.getService(context, "");
}
public static OkHttpDNS getIns(Context context) {
if (instance == null) {
synchronized (OkHttpDNS.class) {
if (instance == null) {
instance = new OkHttpDNS(context);
}
}
}
return instance;
}
@Override
public List<InetAddress> lookup(String hostname) throws UnknownHostException {
String ip = dnsService.getIpByHostAsync(hostname);
if(ip != null){
List<InetAddress> inetAddresses = Arrays.asList(InetAddress.getAllByName(ip));
return inetAddresses;
}
return Dns.SYSTEM.lookup(hostname);
}
}
okhttpClientBuilder.dns(OkHttpDNS.getIns(PerformanceApp.getApplication())).build();
7.监控每次发生请求的时间
继承okhttp里的EventListener,来监听每个请求的多个动作。
public class OkHttpEventListener extends EventListener {
public static final Factory FACTORY = new Factory() {
@Override
public EventListener create(Call call) {
return new OkHttpEventListener();
}
};
OkHttpEvent okHttpEvent;
public OkHttpEventListener() {
super();
okHttpEvent = new OkHttpEvent();
}
@Override
public void callStart(Call call) {
super.callStart(call);
Log.i("lz","callStart");
}
@Override
public void dnsStart(Call call, String domainName) {
super.dnsStart(call, domainName);
okHttpEvent.dnsStartTime = System.currentTimeMillis();
}
@Override
public void dnsEnd(Call call, String domainName, List<InetAddress> inetAddressList) {
super.dnsEnd(call, domainName, inetAddressList);
okHttpEvent.dnsEndTime = System.currentTimeMillis();
}
@Override
public void connectStart(Call call, InetSocketAddress inetSocketAddress, Proxy proxy) {
super.connectStart(call, inetSocketAddress, proxy);
}
@Override
public void secureConnectStart(Call call) {
super.secureConnectStart(call);
}
@Override
public void secureConnectEnd(Call call, @Nullable Handshake handshake) {
super.secureConnectEnd(call, handshake);
}
@Override
public void connectEnd(Call call, InetSocketAddress inetSocketAddress, Proxy proxy, @Nullable Protocol protocol) {
super.connectEnd(call, inetSocketAddress, proxy, protocol);
}
@Override
public void connectFailed(Call call, InetSocketAddress inetSocketAddress, Proxy proxy, @Nullable Protocol protocol, IOException ioe) {
super.connectFailed(call, inetSocketAddress, proxy, protocol, ioe);
}
@Override
public void connectionAcquired(Call call, Connection connection) {
super.connectionAcquired(call, connection);
}
@Override
public void connectionReleased(Call call, Connection connection) {
super.connectionReleased(call, connection);
}
@Override
public void requestHeadersStart(Call call) {
super.requestHeadersStart(call);
}
@Override
public void requestHeadersEnd(Call call, Request request) {
super.requestHeadersEnd(call, request);
}
@Override
public void requestBodyStart(Call call) {
super.requestBodyStart(call);
}
@Override
public void requestBodyEnd(Call call, long byteCount) {
super.requestBodyEnd(call, byteCount);
}
@Override
public void responseHeadersStart(Call call) {
super.responseHeadersStart(call);
}
@Override
public void responseHeadersEnd(Call call, Response response) {
super.responseHeadersEnd(call, response);
}
@Override
public void responseBodyStart(Call call) {
super.responseBodyStart(call);
}
@Override
public void responseBodyEnd(Call call, long byteCount) {
super.responseBodyEnd(call, byteCount);
okHttpEvent.responseBodySize = byteCount;
}
@Override
public void callEnd(Call call) {
super.callEnd(call);
okHttpEvent.apiSuccess = true;
}
@Override
public void callFailed(Call call, IOException ioe) {
Log.i("lz","callFailed ");
super.callFailed(call, ioe);
okHttpEvent.apiSuccess = false;
okHttpEvent.errorReason = Log.getStackTraceString(ioe);
Log.i("lz","reason "+okHttpEvent.errorReason);
}
}
使用
okhttpclientbuilder.eventListenerFactory(OkHttpEventListener.FACTORY).
|