厉害了!教你如何在手机连上WiFi时仍然使用移动网络

今日科技快讯

近日,京东以服务质量倒数第一为由,封杀了天天快递,并通知商家称:建议于7月底之前与服务质量好的京东物流、顺丰、中通、韵达、申通合作。对此,收购了天天快递的苏宁物流称:苏宁快递表示开放共享是行业大势,京东封杀快递公司的目的就是保护自己的物流。随后京东予以反击称:被苏宁收购后天天的加盟网点也是“炙手可热”,但至今并未派送过苏宁的订单,因为苏宁的家电属于高价货,而第三方快递高值货丢失时有发生。

作者简介

本篇来自 Trilen 的投稿,分享了多网络环境下使用指定网络连接服务器技术,希望对大家有所帮助!

Trilen 的博客地址:

http://blog.csdn.net/u010019468

正文

这个功能如标题所述:在 wifi 和 移动数据网络 同时开启之下,在 Android5.0之前 系统并没有很好地提供这样的 api 来实现这样的功能。现在需要 wifi 开着的情况下,强制通过 移动数据网络 发送网络请求,可能会觉得哪会有这样的蛋疼需求,认为只要能访问就行了,还要特地移动网络,那我只能讲你们的业务发展中没有这样的需求。好了废话不多说,实现如下:

Wifi下指定移动网络访问服务端

首先注意权限申请,需要如下权限才能切换:

<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<
uses-permission android:name="android.permission.WRITE_SETTINGS"/>

其中

builder.addCapability(NET_CAPABILITY_INTERNET);
//强制使用蜂窝数据网络-移动数据
builder.addTransportType(TRANSPORT_CELLULAR);

通过配置 TransportType 参数 TRANSPORT_CELLULAR 来指定移动网络,其值可以为 int 有如下几种:分别为 移动数据网络、wifi、蓝牙、以太网、Vpn 5种传输通道。这时就不论当前手机有多少网络是处于连接中,都可以指定单个。

上文中 addCapability(NET_CAPABILITY_INTERNET) 其参数配置也是固定范围可选的,不能乱配,共有19个参数可配:

其中有默认如下配置能力,故若要访问网络需要加上 NET_CAPABILITY_INTERNET

在 connectivityManager.requestNetwork 请求之后如果此次netWork是可以使用的,就会回调 ConnectivityManager.NetworkCallback中onAvailable(Network network) 函数,这时候利用返回的 Network 来进行http连接了 network.openConnection(url)。其源码如下:

可以看到 connectivityManager.requestNetwork()

requestNetwork(NetworkRequest request, NetworkCallback networkCallback)

又调用到

sendRequestForNetwork(request.networkCapabilities,networkCallback, timeoutMs, REQUEST,legacyType)

来实现请求,其源码可以看到 requestNetwork 的请求类型是 REQUEST,继而走到:

最后是通过 mService 这个是 aidl 进程通信的 IConnectivityManager.Sub 内部类 prox代理对象,通过 binder 机制通知远端进行 requestNetwork 方法。

最后不要忘记了注销监听 NetworkCallback:

mConnectivityManager.unregisterNetworkCallback(networkCallback);

适配问题

介绍使用以及原理就是这么多了,但是并不会实际中并不会就那么完美,首先想到就是适配情况

  • 适配机型问题

在多个品牌手机中oppo,小米,魅族几个机型中发现可用能够实现这个功能,但在华为p系列p7以及荣耀手机中可以在回调中 onAvailable(Network network) 正常返回 Network,也能进行连接,但读取网络结果时就一直出现超时。

解决办法:先检查是否有权限,特别注意oppo手机 wifi 第一次用户安装登录默认是没有数据网络权限的,所以总会导致接口访问失败超时,需要用户切换到移动数据网络连接状态下,让用户授权。

若权限存在的话,可以用下面提到的 startUsingNetworkFeature 低版本的兼容方法尝试,目前自测是可以的。区别在于这个不使用 NetWork,直接在打开的移动网络中进行连接访问。

  • 适配低版本

上述也提到在5.0之前要实现这样的功能呢,在低版本中可以使用 startUsingNetworkFeature(int networkType, String feature) 这个被抛弃方法实现,其实和上述实现原理差不多,只是使用起来性能以及效率问题,这个 老Api 在某些机型上不能立即采用移动网络进行请求,需要等待些时间重试。

继续看 requestNetworkForFeatureLocked(netCap) 实现

可以看到最终也走到 sendRequestForNetwork(netCap, l.networkCallback, 0,REQUEST, type) 这个方法和5.0之后的 requestNetwork(NetworkRequest request, NetworkCallback networkCallback) 是一个效果。

甚至有人可能会想到先断开wifi,再通过移动网络来访问,如下:

更多

每天学习累了,看些搞笑的段子放松一下吧。关注最具娱乐精神的公众号,每天都有好心情。

如果你有好的技术文章想和大家分享,欢迎向我的公众号投稿,投稿具体细节请在公众号主页点击“投稿”菜单查看。

欢迎长按下图 -> 识别图中二维码或者扫一扫关注我的公众号:

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值