此篇存在的主要意義在于解決用戶使用app中網(wǎng)絡(luò)狀態(tài)發(fā)生了變化,需要我們?nèi)?dòng)態(tài)監(jiān)聽網(wǎng)絡(luò)連接狀態(tài)(有網(wǎng)、無(wú)網(wǎng))、網(wǎng)絡(luò)類型 (包括wifi、移動(dòng)網(wǎng)絡(luò) -> 3G、4G等等)
門前授課
關(guān)于網(wǎng)絡(luò)狀態(tài)的監(jiān)聽,主要是基于 Android 廣播 - BroadcaseReceiver組件
~
同時(shí)關(guān)于廣播的注冊(cè)方面,從Android7.0開始已經(jīng)初步進(jìn)行限制,所以盡可能采用動(dòng)態(tài)注冊(cè),獻(xiàn)文如下:
Apps targeting Android 7.0 (API level 24) and higher do not receive this
broadcast if they declare the broadcast receiver in their manifest. Apps
will still receive broadcasts if they register their BroadcastReceiver with
Context.registerReceiver() and that context is still valid.
直譯如下
針對(duì)Android 7.0
(API級(jí)別24)或更高的應(yīng)用程序,如果它們?cè)谄鋗anifest中聲明廣播接收器,則不會(huì)接收此廣播。如果應(yīng)用程序?qū)⑵銪roadcastReceiver注冊(cè)為context
. registerreceiver()并且該context仍然有效,那么應(yīng)用程序仍然會(huì)接收廣播
Google在Android7.0時(shí)雖已對(duì)廣播添加了限制,但是Android8.0后基于安全原因又一次加強(qiáng)了限制,且已聲明:應(yīng)用無(wú)法使用其清單的大部分隱式廣播(即,并非專門針對(duì)此應(yīng)用的廣播)
針對(duì)于此我們?cè)诒酒褂脛?dòng)態(tài)注冊(cè)廣播,稍微科普一下,廣播的兩種注冊(cè)方式 ~
Here:不論使用哪種注冊(cè)方式均需在AndroidMainest清單文件里面進(jìn)行注冊(cè)
-
靜態(tài)注冊(cè)
也就是說(shuō)在AndroidManifest文件中對(duì)BroadcastReceiver進(jìn)行注冊(cè),通常還會(huì)加上action用來(lái)過(guò)濾;此注冊(cè)方式即使退出應(yīng)用后,仍然能夠收到相應(yīng)的廣播 -
動(dòng)態(tài)注冊(cè)
調(diào)用Context中的registerReceiver對(duì)廣播進(jìn)行動(dòng)態(tài)注冊(cè),使用unRegisterReceiver方法對(duì)廣播進(jìn)行取消注冊(cè)的操作;故此注冊(cè)方式一般都是隨著所在的Activity或者應(yīng)用銷毀以后,不會(huì)再收到該廣播
動(dòng)態(tài)廣播提示:廣播注冊(cè)是一個(gè)創(chuàng)建的過(guò)程,那么必然也要有一個(gè)銷毀的過(guò)程,從而防止內(nèi)存泄露,那么銷毀就在是onDestroy中unregisterReceiver廣播 ~
Activity/Fragment - 注銷廣播
?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-693821.html
java
@Override
protected void onDestroy() {
super.onDestroy();
//netWorkReceiver 之前已注冊(cè)的廣播
if (netWorkReceiver != null) {
unregisterReceiver(netWorkReceiver);
}
具體實(shí)現(xiàn)
此處就是本文的核心內(nèi)容了,網(wǎng)絡(luò)的實(shí)時(shí)動(dòng)態(tài)監(jiān)聽指的是全局實(shí)時(shí)監(jiān)聽網(wǎng)絡(luò)狀態(tài),針對(duì)的對(duì)象非一個(gè)事件而是整個(gè)APP應(yīng)用項(xiàng)目 ~
AndroidMainfests - 添加權(quán)限
?
java
<!-- 網(wǎng)絡(luò)狀態(tài) -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
創(chuàng)建 - 廣播接受者
- 基礎(chǔ)版
這里主要實(shí)時(shí)判斷網(wǎng)絡(luò)連接狀態(tài),同時(shí)判斷網(wǎng)絡(luò)類型 ~
為何說(shuō)是基礎(chǔ)版,因?yàn)檫@里雖然實(shí)現(xiàn)了功能,但是會(huì)重復(fù)收到網(wǎng)絡(luò)變動(dòng)的廣播,太影響業(yè)務(wù)邏輯了!很有可能導(dǎo)致其他并發(fā)情況!
監(jiān)聽效果
監(jiān)聽實(shí)現(xiàn) - NetworkReceiver(廣播接收者)
?
java
package nk.com.networklinstener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
/**
* @author MrLiu
* @date 2020/5/11
* desc 廣播接收者
*/
public class NetworkReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 監(jiān)聽網(wǎng)絡(luò)連接,包括wifi和移動(dòng)數(shù)據(jù)的打開和關(guān)閉,以及連接上可用的連接都會(huì)接到監(jiān)聽
// 特殊注意:如果if條件生效,那么證明當(dāng)前是有連接wifi或移動(dòng)網(wǎng)絡(luò)的,如果有業(yè)務(wù)邏輯最好把esle場(chǎng)景酌情考慮進(jìn)去!
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
//獲取聯(lián)網(wǎng)狀態(tài)的NetworkInfo對(duì)象
NetworkInfo info = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
if (info != null) {
//如果當(dāng)前的網(wǎng)絡(luò)連接成功并且網(wǎng)絡(luò)連接可用
if (NetworkInfo.State.CONNECTED == info.getState() && info.isAvailable()) {
if (info.getType() == ConnectivityManager.TYPE_WIFI || info.getType() == ConnectivityManager.TYPE_MOBILE) {
Log.e("TAG", getConnectionType(info.getType()) + "已連接");
}
} else {
Log.e("TAG", getConnectionType(info.getType()) + "已斷開");
}
}
}
}
/**
* 獲取連接類型
* @param type
* @return
*/
private String getConnectionType(int type) {
String connType = "";
if (type == ConnectivityManager.TYPE_MOBILE) {
connType = "3-4G網(wǎng)絡(luò)數(shù)據(jù)";
} else if (type == ConnectivityManager.TYPE_WIFI) {
connType = "WIFI網(wǎng)絡(luò)";
}
return connType;
}
}
- 優(yōu)化版(推薦)
這里在判斷網(wǎng)絡(luò)連接狀態(tài)的同時(shí)主要防止收到多條網(wǎng)絡(luò)連接回調(diào),從而導(dǎo)致邏輯錯(cuò)亂,所以采用時(shí)間校驗(yàn)實(shí)現(xiàn)類似同步鎖的效果
監(jiān)聽效果
監(jiān)聽實(shí)現(xiàn) - NetworkReceiver(廣播接收者)
?
java
package com.nk.machine.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
import com.nk.machine.base.MainActivity;
import java.text.SimpleDateFormat;
/**
* @author MrLiu
* @date 2020/5/15
* desc 廣播接收者
*/
public class NetWorkReceiver extends BroadcastReceiver {
private static long WIFI_TIME = 0;
private static long ETHERNET_TIME = 0;
private static long NONE_TIME = 0;
private static int LAST_TYPE = -3;
private static String TAG = "TAG";
@Override
public void onReceive(Context context, Intent intent) {
// 監(jiān)聽網(wǎng)絡(luò)連接,包括wifi和移動(dòng)數(shù)據(jù)的打開和關(guān)閉,以及連接上可用的連接都會(huì)接到監(jiān)聽
// 特殊注意:如果if條件生效,那么證明當(dāng)前是有連接wifi或移動(dòng)網(wǎng)絡(luò)的,如果有業(yè)務(wù)邏輯最好把esle場(chǎng)景酌情考慮進(jìn)去!
if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
long time = getTime();
if (time != WIFI_TIME && time != ETHERNET_TIME && time != NONE_TIME) {
final int netWorkState = getNetWorkState(context);
if (netWorkState == 0 && LAST_TYPE != 0) {
WIFI_TIME = time;
LAST_TYPE = netWorkState;
Log.e(TAG, "wifi:" + time);
} else if (netWorkState == 1 && LAST_TYPE != 1) {
ETHERNET_TIME = time;
LAST_TYPE = netWorkState;
Log.e(TAG, "數(shù)據(jù)網(wǎng)絡(luò):" + time);
} else if (netWorkState == -1 && LAST_TYPE != -1) {
NONE_TIME = time;
LAST_TYPE = netWorkState;
Log.e(TAG, "無(wú)網(wǎng)絡(luò):" + time);
}
}
}
}
public long getTime() {
SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyyMMddhhmmss");
String date = sDateFormat.format(new java.util.Date());
return Long.valueOf(date);
}
private static final int NETWORK_NONE = -1; //無(wú)網(wǎng)絡(luò)連接
private static final int NETWORK_WIFI = 0; //wifi
private static final int NETWORK_MOBILE = 1; //數(shù)據(jù)網(wǎng)絡(luò)
//判斷網(wǎng)絡(luò)狀態(tài)與類型
public static int getNetWorkState(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
if (activeNetworkInfo != null && activeNetworkInfo.isConnected()) {
if (activeNetworkInfo.getType() == (ConnectivityManager.TYPE_WIFI)) {
return NETWORK_WIFI;
} else if (activeNetworkInfo.getType() == (ConnectivityManager.TYPE_MOBILE)) {
return NETWORK_MOBILE;
}
} else {
return NETWORK_NONE;
}
return NETWORK_NONE;
}
}
MainActivity - 動(dòng)態(tài)注冊(cè)廣播
?
java
package nk.com.networklinstener;
import android.annotation.SuppressLint;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
private NetworkReceiver netWorkReceiver;
@SuppressLint("SetJavaScriptEnabled")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//注冊(cè)網(wǎng)絡(luò)狀態(tài)監(jiān)聽廣播
netWorkReceiver = new NetworkReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(netWorkReceiver, filter);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (netWorkReceiver != null) {
unregisterReceiver(netWorkReceiver);
}
}
}
異常場(chǎng)景
首先AndroidManifest加入以下權(quán)限
?
java
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
此異常場(chǎng)景指的是app在運(yùn)行時(shí)有崩潰異常 - SecurityException,錯(cuò)誤如下 ~
?
java
java.lang.SecurityException: com.xxx.xxx was not granted either of these permissions: android.permission.CHANGE_NETWORK_STATE, android.permission.WRITE_SETTINGS.
at android.os.Parcel.readException(Parcel.java:1602)
at android.os.Parcel.readException(Parcel.java:1555)
at android.net.IConnectivityManager$Stub$Proxy.requestNetwork(IConnectivityManager.java:2064)
at android.net.ConnectivityManager.sendRequestForNetwork(ConnectivityManager.java:2470)
at android.net.ConnectivityManager.requestNetwork(ConnectivityManager.java:2509)
at com.superrtc.call.NetworkMonitorAutoDetect$ConnectivityManagerDelegate.requestMobileNetwork(NetworkMonitorAutoDetect.java)
at com.superrtc.call.NetworkMonitorAutoDetect.<init>(NetworkMonitorAutoDetect.java)
at com.superrtc.mediamanager.XReachability.setAutoDetectConnectivityStateInternal(XReachability.java)
at com.superrtc.mediamanager.XReachability.startMonitoring(XReachability.java)
at com.superrtc.mediamanager.EMediaManager$7.run(EMediaManager.java)
at android.os.Handler.handleCallback(Handler.java:743)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:150)
at com.superrtc.util.LooperExecutor.run(LooperExecutor.java)
按理說(shuō)android.permission.CHANGE_NETWORK_STATE這一個(gè)權(quán)限,是普通權(quán)限,只在Manifest中聲明就可以獲取。
出現(xiàn)這個(gè)問(wèn)題很不科學(xué)啊,再仔細(xì)去看看錯(cuò)誤日志,發(fā)現(xiàn)報(bào)錯(cuò)只發(fā)生在6.0這個(gè)版本和部分6.0.1版本中。
那問(wèn)題應(yīng)該是出在6.0
版本中,之后去查資料后發(fā)現(xiàn),在6.0版本中這個(gè)權(quán)限默認(rèn)是被拒絕,無(wú)法獲取這個(gè)權(quán)限。所以,在需要個(gè)權(quán)限的時(shí)候會(huì)出現(xiàn)權(quán)限問(wèn)題導(dǎo)致應(yīng)用因?yàn)闄?quán)限問(wèn)題崩潰。這個(gè)在stackoverflow中有人討論過(guò)了,去看看
知道問(wèn)題的原因之后的解決方案就簡(jiǎn)單了,既然CHANGE_NETWORK_STATE權(quán)限獲取不到,那只好想辦法打開WRITE_SETTINGS這個(gè)權(quán)限了。
跳轉(zhuǎn)到應(yīng)用程序設(shè)置頁(yè)打開WRITE_SETTINGS這個(gè)權(quán)限:
?
java
Intent goToSettings = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
goToSettings.setData(Uri.parse("package:" + getPackageName()));
startActivity(goToSettings);
興趣擴(kuò)展
網(wǎng)絡(luò)廣播Actiion的三種類型
WifiManager.WIFI_STATE_CHANGED_ACTION
這個(gè)監(jiān)聽wifi的打開與關(guān)閉,與wifi的連接無(wú)關(guān);示例如下,主要查看一下 wifi連接 - 關(guān)閉過(guò)程
監(jiān)聽效果
示例代碼
?
java
package nk.com.networklinstener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.WifiManager;
import android.util.Log;
/**
* @author MrLiu
* @date 2020/5/11
* desc wifi連接/斷開過(guò)程
*/
public class NetworkReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 監(jiān)聽wifi的打開與關(guān)閉,與wifi的連接無(wú)關(guān)
if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(intent.getAction())) {
int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 0);
Log.e("TAG", "wifiState:" + wifiState);
switch (wifiState) {
case WifiManager.WIFI_STATE_ENABLING:
Log.e("TAG", "wifi狀態(tài):打開中");
break;
case WifiManager.WIFI_STATE_ENABLED://主用:打開狀態(tài)
Log.e("TAG", "wifi狀態(tài):已打開");
break;
case WifiManager.WIFI_STATE_DISABLING:
Log.e("TAG", "wifi狀態(tài):關(guān)閉中");
break;
case WifiManager.WIFI_STATE_DISABLED://主用:關(guān)閉狀態(tài)
Log.e("TAG", "wifi狀態(tài):已關(guān)閉");
break;
case WifiManager.WIFI_STATE_UNKNOWN:
Log.e("TAG", "wifi狀態(tài):無(wú)法識(shí)別");
break;
default:
Log.e("TAG", "wifi狀態(tài):未知");
break;
}
}
}
}
WifiManager.NETWORK_STATE_CHANGED_ACTION
這個(gè)監(jiān)聽wifi的連接狀態(tài)即是否連上了一個(gè)有效無(wú)線路由,當(dāng)上邊廣播的狀態(tài)是WifiManager.WIFI_STATE_DISABLING(wifi
關(guān)閉中)、WIFI_STATE_DISABLED(wifi 已關(guān)閉)的時(shí)候,根本不會(huì)接到這個(gè)廣播。
在上邊廣播接到廣播是WifiManager.WIFI_STATE_ENABLED(wifi
已打開)狀態(tài)的同時(shí)也會(huì)接到這個(gè)廣播,當(dāng)然剛打開wifi肯定還沒(méi)有連接到有效的無(wú)線
示例代碼
?
java
package nk.com.networklinstener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.WifiManager;
import android.util.Log;
/**
* @author MrLiu
* @date 2020/5/11
* desc wifi連接/斷開過(guò)程
*/
public class NetworkReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 這個(gè)監(jiān)聽wifi的連接狀態(tài)即是否連上了一個(gè)有效無(wú)線路由,具體如上所述
if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(intent.getAction())) {
Parcelable parcelableExtra = intent
.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if (null != parcelableExtra) {
NetworkInfo networkInfo = (NetworkInfo) parcelableExtra;
State state = networkInfo.getState();
// 當(dāng)然,這邊可以更精確的確定狀態(tài)
boolean isConnected = state == State.CONNECTED;
Log.e(TAG1, "isConnected" + isConnected);
if (isConnected) {
APP.getInstance().setWifi(true);
} else {
APP.getInstance().setWifi(false);
}
}
}
}
}
ConnectivityManager.CONNECTIVITY_ACTION
這個(gè)監(jiān)聽網(wǎng)絡(luò)連接的設(shè)置,包括wifi和移動(dòng)數(shù)據(jù)的打開和關(guān)閉;
此監(jiān)聽的作用范圍最大!不論wifi的打開、關(guān)閉,或是連接上可用的鏈接都會(huì)接到監(jiān)聽;當(dāng)然有利必有弊,那就是因?yàn)榉秶珡V,所以效率相比上方的倆個(gè)監(jiān)聽要慢一些!
如果上方的倆個(gè)監(jiān)聽需求可用滿足我們的業(yè)務(wù)需求,那么可以優(yōu)先適用上方倆種監(jiān)聽方式搭配使用;但個(gè)人建議如果業(yè)務(wù)需求上面?zhèn)z個(gè)監(jiān)聽滿足不了的話,還是可以采用懶人方式直接用此監(jiān)聽!
Of Course :這里所謂的示例代碼,就是最早看到的動(dòng)態(tài)監(jiān)聽的實(shí)現(xiàn)部分了!
監(jiān)聽常用
此處主要借鑒與此
-
獲取ConnectivityManager對(duì)象
java
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context
.CONNECTIVITY_SERVICE); -
獲取 NetworkInfo對(duì)象
java
//但是這個(gè)方法已經(jīng)過(guò)時(shí),官網(wǎng)的解釋如下:This method was deprecated in API level 23. This method does not support multiple connected networks of the same type. Use getAllNetworks() and
getNetworkInfo(int networkType)
getNetworkInfo(android.net.Network) instead.
getNetworkInfo(Network network)
getActiveNetwork()
Returns a Network object corresponding to the currently active default data network.
getActiveNetworkInfo(),Returns details about the currently active default data network.
//這個(gè)方法已經(jīng)過(guò)時(shí),Use getAllNetworks() and getNetworkInfo(android.net.Network) instead.
getAllNetworkInfo() -
綜上所述,我們?nèi)绻喇?dāng)前Mobile網(wǎng)絡(luò)或者WiFi網(wǎng)絡(luò)是否已經(jīng)連接上,總共有兩種方法
方法一:API23時(shí)已過(guò)時(shí)
?
java
//猜測(cè):APP.getInstance()應(yīng)該是一個(gè)關(guān)于網(wǎng)絡(luò)相關(guān)的單例模式,主要用于app其他地方使用
void getNetwork(Context context){
State wifiState = null;
State mobileState = null;
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context
.CONNECTIVITY_SERVICE);
wifiState = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState();
mobileState = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState();
Log.d(TAG1,"wifi狀態(tài):" + wifiState + "\n mobile狀態(tài):" + mobileState);
// 手機(jī)網(wǎng)絡(luò)連接成功
if (wifiState != null && mobileState != null
&& State.CONNECTED != wifiState
&& State.CONNECTED == mobileState) {
Log.d("tag", "手機(jī)2g/3g/4g網(wǎng)絡(luò)連接成功");
APP.getInstance().setMobile(true);
APP.getInstance().setWifi(false);
APP.getInstance().setConnected(true);
}
// 無(wú)線網(wǎng)絡(luò)連接成功
else if (wifiState != null && State.CONNECTED == wifiState) {
Log.d("tag", "無(wú)線網(wǎng)絡(luò)連接成功");
APP.getInstance().setMobile(false);
APP.getInstance().setWifi(true);
APP.getInstance().setConnected(true);
}
// 手機(jī)沒(méi)有任何的網(wǎng)絡(luò)
else if (wifiState != null && mobileState != null
&& State.CONNECTED != wifiState
&& State.CONNECTED != mobileState) {
Log.d("tag", "手機(jī)沒(méi)有任何的網(wǎng)絡(luò)");
APP.getInstance().setMobile(false);
APP.getInstance().setWifi(false);
APP.getInstance().setConnected(false);
}
}
方法二:此處和我在上方的網(wǎng)絡(luò)實(shí)時(shí)監(jiān)聽大致相同
?
java
//猜測(cè):APP.getInstance()應(yīng)該是一個(gè)關(guān)于網(wǎng)絡(luò)相關(guān)的單例模式,主要用于app其他地方使用
void getNetwork(Context context) {
ConnectivityManager manager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
Log.i("tag", "CONNECTIVITY_ACTION");
NetworkInfo activeNetwork = manager.getActiveNetworkInfo();
// connected to the internet
if (activeNetwork != null) {
if (activeNetwork.isConnected()) {
if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
// connected to wifi
APP.getInstance().setWifi(true);
Log.e("tag", "當(dāng)前WiFi連接可用 ");
} else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
// connected to the mobile provider's data plan
APP.getInstance().setMobile(true);
Log.e("tag", "當(dāng)前移動(dòng)網(wǎng)絡(luò)連接可用 ");
}
} else {
Log.e("tag", "當(dāng)前沒(méi)有網(wǎng)絡(luò)連接,請(qǐng)確保你已經(jīng)打開網(wǎng)絡(luò) ");
}
} // not connected to the internet
else {
Log.e("tag", "當(dāng)前沒(méi)有網(wǎng)絡(luò)連接,請(qǐng)確保你已經(jīng)打開網(wǎng)絡(luò) ");
APP.getInstance().setWifi(false);
APP.getInstance().setMobile(false);
APP.getInstance().setConnected(false);
}
}
閑來(lái)無(wú)事正好看到了屏幕打開/關(guān)閉的的監(jiān)聽廣播,特此記錄一番
?
java
package nk.com.networklinstener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
/**
* @author MrLiu
* @date 2020/5/12
* desc 此時(shí)APP可以后臺(tái)運(yùn)行,廣播依然有效,但是如果被殺死則無(wú)法收到廣播。
*
*/
public class ScreenReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case Intent.ACTION_SCREEN_OFF:
Log.e("屏幕廣播","屏幕被關(guān)閉");
break;
case Intent.ACTION_SCREEN_ON:
Log.e("屏幕廣播","屏幕被打開");
break;
}
}
}
ConnectivityManager監(jiān)聽網(wǎng)絡(luò)更改
ConnectivityManager API 提供一個(gè)更強(qiáng)大的方法,用于僅在滿足指定的網(wǎng)絡(luò)條件時(shí)請(qǐng)求回調(diào)。首先我們獲取到系統(tǒng)的ConnectivityManager
服務(wù), 并且使用 registerNetworkCallback
將 NetworkRequest
對(duì)象傳遞給系統(tǒng),最終系統(tǒng)會(huì)通過(guò) ConnectivityManager.NetworkCallback
回調(diào),將網(wǎng)絡(luò)變更情況告知給應(yīng)用。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-693821.html
?
java
//獲取ConnectivityManager
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
//定義ConnectivityManager.NetworkCallback回調(diào)方法
callback = new ConnectivityManager.NetworkCallback() {
// 可用網(wǎng)絡(luò)接入
public void onCapabilitiesChanged(@NotNull Network network, @NotNull NetworkCapabilities networkCapabilities) {
super.onCapabilitiesChanged(network, networkCapabilities);
LogUtils.d("onCapabilitiesChanged");
checkNetworkCapabilities(networkCapabilities);
}
@Override
public void onLost(@NonNull Network network) {
super.onLost(network);
if (cm != null) {
Network activeNetwork = cm.getActiveNetwork();
if (activeNetwork == null) {
//連接不到可用網(wǎng)絡(luò)
return;
}
NetworkCapabilities networkCapabilities = cm.getNetworkCapabilities(activeNetwork);
checkNetworkCapabilities(networkCapabilities);
}
}
};
NetworkRequest.Builder builder = new NetworkRequest.Builder();
if (cm != null) {
cm.registerNetworkCallback(builder.build(), callback);
}
//判斷當(dāng)前網(wǎng)絡(luò)連接情況
private void checkNetworkCapabilities(NetworkCapabilities networkCapabilities) {
if (networkCapabilities == null) {
return;
}
// 表明網(wǎng)絡(luò)連接成功
if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI_AWARE)) {
// 使用WI-FI
LogUtils.d("WIFI network");
} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
// 使用蜂窩網(wǎng)絡(luò)
LogUtils.d("mobile network");
} else {
// 未知網(wǎng)絡(luò),包括藍(lán)牙、VPN、LoWPAN
LogUtils.d("unknown network");
}
} else {
//網(wǎng)絡(luò)連接失敗
}
}
到了這里,關(guān)于Android 監(jiān)聽網(wǎng)絡(luò)狀態(tài)變化的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!