大家好,大概有一個多月沒有更新博客了,我是干什么去了呢?很明顯,程序員當然要加班……這一次跟大家分享一下新項目的一些心得。
監聽網絡變化在開發中是經常用到的,例如我們斷網有一些友好的提示,或者根據不同的網絡更改一些加載策略,例如wifi看視頻,非wifi則會有一個提示,還有極個別更惡心的偷摸的在后台給你下各種安裝包,是誰我就不一一列舉了。
在5.0以前,我們都是廣播BroadcastReceiver,注冊跟網絡變化相關的廣播,然后判斷是連接還是斷開,這種做法非常方便,但是隨着安卓的版本迭代,在權限上越來越謹慎,廣播的方式就顯得不太優雅。
打個比方,之前就是拿個大喇叭,在大街上各種喊,就好像逛地攤,各種商品的吆喝聲混在一起,需要你自己去分辨哪些是你想要的信息,而且又顯得很不安全,萬一賣的商品比較隱私呢,大家都是很低調的人。
所以在安卓5.0以上終於對網絡的監聽進行了優化,那就是通過Callback回調的方式,這種開發模式是不是很常用?例如監聽下載進度,我只需要三個回調:下載成功,下載失敗,下載的進度變化,這種回調方式針對性強,耦合性低,非常方便,和廣播相比,就好像我們是一個訂購了服務,需要的東西自動上門,very good。
廢話鋪墊了這么多,下面就是一個實戰demo。
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); // 請注意這里會有一個版本適配bug,所以請在這里添加非空判斷 if (connectivityManager != null) { connectivityManager.requestNetwork(new NetworkRequest.Builder().build(), new ConnectivityManager.NetworkCallback() { /** * 網絡可用的回調 * */ @Override public void onAvailable(Network network) { super.onAvailable(network); Log.e("lzp", "onAvailable"); } /** * 網絡丟失的回調 * */ @Override public void onLost(Network network) { super.onLost(network); Log.e("lzp", "onLost"); } /** * 當建立網絡連接時,回調連接的屬性 * */ @Override public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) { super.onLinkPropertiesChanged(network, linkProperties); Log.e("lzp", "onLinkPropertiesChanged"); } /** * 按照官方的字面意思是,當我們的網絡的某個能力發生了變化回調,那么也就是說可能會回調多次 * * 之后在仔細的研究 * */ @Override public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) { super.onCapabilitiesChanged(network, networkCapabilities); Log.e("lzp", "onCapabilitiesChanged"); } /** * 在網絡失去連接的時候回調,但是如果是一個生硬的斷開,他可能不回調 * */ @Override public void onLosing(Network network, int maxMsToLive) { super.onLosing(network, maxMsToLive); Log.e("lzp", "onLosing"); } /** * 按照官方注釋的解釋,是指如果在超時時間內都沒有找到可用的網絡時進行回調 * */ @Override public void onUnavailable() { super.onUnavailable(); Log.e("lzp", "onUnavailable"); } }); } } } }
這就是今天的全部代碼了,上面已經有了響應的注釋,但是還是不夠便於我們理解,接下來就仔細的研究一下:
1、首先我們打開app,此時網絡是連接的狀態:

一打開demo,我們立刻就得到了onAvailable的回調,意思就是網絡目前可用,這一點比廣播強多了,因為我們已啟動還要單獨處理一次,而通過回調的方式,可以立刻得到當前的狀態。
2、然后我們手動關閉網絡:

哎?沒有onLosing的回調,只看到了onLost,說明我們手動關閉網絡連接是一個很粗暴的行為,就像官方注釋上寫的,如果是一個生硬的斷開,他可能不回調。
3、最后我們再次連接網絡:

這次的回調就比較多了,首先是onAvailable,顯示網絡可用,然后是onCapabilitiesChanged,說此時網絡的連接能力發生了第一次變化,估計是連接中把,再然后是onLinkPropertiesChanged,說明連接的屬性已經發生了變化,此時應該獲得了ip地址等信息,最后又回調了onCapabilitiesChanged,那么應該是網絡進度到可用的狀態。
#總結#
我沒有模擬出onLosing和onUnavailable的場景,至少說明他倆的出現的概率現在已經不高了,我們已經通過注釋簡單理解了他倆的場景,這里就不做深入研究了。
通過剛才的實驗,我們得出了一下結論:
1、要想監聽網絡的連接和斷開,應該在onAvailable和onLost中,他們一定會成對出現。
2、其他的幾個回調使用場景會少一點,並且onCapabilitiesChanged會回調多次,所以使用它時我們要慎重,避免重復的操作,但是可以保證最后一次回調,網絡的連接一定是連接成功的。
OK,從這個小小的變化,我們看到了安卓在慢慢變得更好,使用起來更簡潔更優雅,這也加大了某些素質低的廠商想盡辦法后台干點壞事的行為。
今天就到這里,有什么問題大家一起留言討論~
#補充#
1、記得申請權限:
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.WRITE_SETTINGS" />
尤其是WRITE_SETTINGS,這個需要手動申請,千萬別忘了。
