如何检测何时在 Android 中建立 WIFI 连接?

我需要检测当我有 WIFI 网络连接。发送广播以确定已建立有效的网络连接。我需要验证 HTTP 的有效网络连接是否存在。我应该监听什么以及需要进行哪些额外的测试才能知道存在有效的连接。

173221 次浏览

您可以注册一个 BroadcastReceiver,以便在 WiFi 连接建立时(或者如果连接发生变化时)得到通知。

注册 BroadcastReceiver:

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
registerReceiver(broadcastReceiver, intentFilter);

然后在你的 BroadcastReceiver中做这样的动作:

@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
if (intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false)) {
//do stuff
} else {
// wifi connection was lost
}
}
}

有关更多信息,请参见 BroadcastReceiverWifiManager的文档

当然,在此之前,您应该检查设备是否已经连接到 WiFi。

编辑: 由于禁止地球工程,这里有一个方法来检查设备是否已经连接:

private boolean isConnectedViaWifi() {
ConnectivityManager connectivityManager = (ConnectivityManager) appObj.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
return mWifi.isConnected();
}

如果您给用户一个选择来覆盖每次询问的正常行为,那么 可以将启动 wifi 连接。

我选择用三种方法。

public boolean isOnline()
{
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
return (networkInfo != null && networkInfo.isConnected());
}

这是一个快速检查,如果有一个互联网连接无线或蜂窝数据。从这里你可以选择你想采取什么行动。是否处于飞机模式也需要检查。

在另一条线上。 我将变量 IpAddress 设置为 = “” 和轮询,直到我有一个有效的 IP 地址。

  WifiManager wifi;
wifi = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifi.getConnectionInfo();
int ipAddress = wifiInfo.getIpAddress();
String ip = null;
ip = String.format("%d.%d.%d.%d",
(ipAddress & 0xff),
(ipAddress >> 8 & 0xff),
(ipAddress >> 16 & 0xff),
(ipAddress >> 24 & 0xff));
Log.e(" >>IP number Begin ",ip);

另一个代码片段... 如果它没有打开,打开它(用户事先许可)

   if(wifi.isWifiEnabled()!=true)wifi.setWifiEnabled(true);

这里是我的代码的一个例子,它考虑到用户的偏好,只允许通信时连接到 Wifi。

在我尝试下载东西之前,我从 IntentService内部调用这个代码。

请注意,如果没有任何类型的网络连接,则 NetworkInfo将为 null

private boolean canConnect()
{
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);


boolean canConnect = false;
boolean wifiOnly = SharedPreferencesUtils.wifiOnly();


NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if(networkInfo != null)
{
if(networkInfo.isConnected())
{
if((networkInfo.getType() == ConnectivityManager.TYPE_WIFI) ||
(networkInfo.getType() != ConnectivityManager.TYPE_WIFI && !wifiOnly))
{
canConnect = true;
}
}
}


return canConnect;
}

对我来说,只有 WifiManager.NETWORK_STATE_CHANGED_ACTION工程。

登记广播接收机:

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
registerReceiver(broadcastReceiver, intentFilter);

并接收:

@Override
public void onReceive(Context context, Intent intent) {


final String action = intent.getAction();


if(action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)){
NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
boolean connected = info.isConnected();


//call your method
}
}

我用了这个代码:

public class MainActivity extends Activity
{
.
.
.
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
.
.
.
}


@Override
protected void onResume()
{
super.onResume();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
registerReceiver(broadcastReceiver, intentFilter);
}


@Override
protected void onPause()
{
super.onPause();
unregisterReceiver(broadcastReceiver);
}


private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
final String action = intent.getAction();
if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION))
{
if (intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false))
{
// wifi is enabled
}
else
{
// wifi is disabled
}
}
}
};
}

对我最有效的方法是:

机器人清单

<receiver android:name="com.AEDesign.communication.WifiReceiver" >
<intent-filter android:priority="100">
<action android:name="android.net.wifi.STATE_CHANGE" />
</intent-filter>
</receiver>

BroadcastReceiver 类

public class WifiReceiver extends BroadcastReceiver {


@Override
public void onReceive(Context context, Intent intent) {


NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if(info != null && info.isConnected()) {
// Do your work.


// e.g. To check the Network Name or other info:
WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
String ssid = wifiInfo.getSSID();
}
}
}

许可

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

我有两种方法来检测接收应用程序上下文的 WIFI 连接:

1)我的老方法

public boolean isConnectedWifi1(Context context) {
try {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if (networkInfo != null) {
NetworkInfo[] netInfo = connectivityManager.getAllNetworkInfo();
for (NetworkInfo ni : netInfo) {
if ((ni.getTypeName().equalsIgnoreCase("WIFI"))
&& ni.isConnected()) {
return true;
}
}
}
return false;
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
return false;
}

2)我的新方法(我正在使用这个方法) :

public boolean isConnectedWifi(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
return networkInfo.isConnected();
}

为了检测 WIFI 连接状态,我使用了 ConnectivityManager 类中的 CONNECTIVITY _ ACTION,以便:

    IntentFilter filter=new IntentFilter();
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(receiver, filter);

以及你的 BroadCastReceiver:

    if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
int networkType = intent.getIntExtra(
android.net.ConnectivityManager.EXTRA_NETWORK_TYPE, -1);
if (ConnectivityManager.TYPE_WIFI == networkType) {
NetworkInfo networkInfo = (NetworkInfo) intent
.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if (networkInfo != null) {
if (networkInfo.isConnected()) {


// TODO: wifi is connected
} else {
// TODO: wifi is not connected
}
}
}


}

对我来说挺好的

用户@JPM 和@usman 给出的答案非常有用。它工作良好,但在我的情况下,它来在 onReceive多次在我的情况下 四次,所以我的代码执行多次。

我做了一些修改,并根据我的要求,现在它来只有1次

下面是用于 Broadcast 的 java 类。

public class WifiReceiver extends BroadcastReceiver {


String TAG = getClass().getSimpleName();
private Context mContext;


@Override
public void onReceive(Context context, Intent intent) {


mContext = context;




if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {


ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = cm.getActiveNetworkInfo();


if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI &&
networkInfo.isConnected()) {
// Wifi is connected
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
String ssid = wifiInfo.getSSID();


Log.e(TAG, " -- Wifi connected --- " + " SSID " + ssid );


}
}
else if (intent.getAction().equalsIgnoreCase(WifiManager.WIFI_STATE_CHANGED_ACTION))
{
int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN);
if (wifiState == WifiManager.WIFI_STATE_DISABLED)
{
Log.e(TAG, " ----- Wifi  Disconnected ----- ");
}


}
}
}

在机器人清单里

<receiver android:name=".util.WifiReceiver" android:enabled="true">
<intent-filter>
<action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>




<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

此代码根本不需要权限。它仅限于 Wi-Fi 网络连接状态的改变(不考虑任何其他网络)。接收器静态地发布在 AndroidManifest.xml 文件中,不需要导出,因为它将在每次网络连接状态更改时由系统 protected broadcastNETWORK_STATE_CHANGED_ACTION调用。

Android 宣言:

<receiver
android:name=".WifiReceiver"
android:enabled="true"
android:exported="false">


<intent-filter>
<!--protected-broadcast: Special broadcast that only the system can send-->
<!--Corresponds to: android.net.wifi.WifiManager.NETWORK_STATE_CHANGED_ACTION-->
<action android:name="android.net.wifi.STATE_CHANGE" />
</intent-filter>


</receiver>

BroadcastReceiver 类:

public class WifiReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
/*
Tested (I didn't test with the WPS "Wi-Fi Protected Setup" standard):
In API15 (ICE_CREAM_SANDWICH) this method is called when the new Wi-Fi network state is:
DISCONNECTED, OBTAINING_IPADDR, CONNECTED or SCANNING


In API19 (KITKAT) this method is called when the new Wi-Fi network state is:
DISCONNECTED (twice), OBTAINING_IPADDR, VERIFYING_POOR_LINK, CAPTIVE_PORTAL_CHECK
or CONNECTED


(Those states can be obtained as NetworkInfo.DetailedState objects by calling
the NetworkInfo object method: "networkInfo.getDetailedState()")
*/
/*
* NetworkInfo object associated with the Wi-Fi network.
* It won't be null when "android.net.wifi.STATE_CHANGE" action intent arrives.
*/
NetworkInfo networkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);


if (networkInfo != null && networkInfo.isConnected()) {
// TODO: Place the work here, like retrieving the access point's SSID


/*
* WifiInfo object giving information about the access point we are connected to.
* It shouldn't be null when the new Wi-Fi network state is CONNECTED, but it got
* null sometimes when connecting to a "virtualized Wi-Fi router" in API15.
*/
WifiInfo wifiInfo = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
String ssid = wifiInfo.getSSID();
}
}
}

许可:

None

对于所有那些喜欢 连通性 _ 变化广播的人,请注意,当应用程序在 Android O 的后台时,这不会再被解雇。

Https://developer.android.com/about/versions/o/background.html

Android O 移除了接收 wifi 状态改变的隐式广播的可能性。因此,如果你的应用程序是关闭的,你将无法接收他们。新的 WorkManager可以在应用程序关闭时运行,所以我对它做了一些实验,它似乎运行得很好:

将此添加到您的依赖项中:

implementation "android.arch.work:work-runtime:1.0.0-alpha08"

WifiConnectWorker.kt

class WifiConnectWorker : Worker() {


override fun doWork(): Result {
Log.i(TAG, "I think we connected to a wifi")
return Result.SUCCESS
}
}

主要活动

class MainActivity : AppCompatActivity() {


override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main_activity)


val workManager = WorkManager.getInstance()


// Add constraint to start the worker when connecting to WiFi
val request = OneTimeWorkRequest.Builder(WifiConnectWorker::class.java)
.setConstraints(Constraints.Builder()
.setRequiredNetworkType(UNMETERED)
.build())
.build()


// The worker should be started, even if your app is closed
workManager.beginUniqueWork("watch_wifi", REPLACE, request).enqueue()
}
}

请记住,这只是一次性通知的快速测试。有更多的工作要做,以始终得到通知时,WiFi 是打开和关闭。

附注: 当应用程序是 强制退出,工人没有启动,似乎 WorkManager是取消请求,然后。

1)我也尝试了广播接收器的方法,尽管我知道 连接性 _ Action/连接性 _ Change在 API 28中是不被推荐的。同样使用显式寄存器,只要应用程序运行,它就会监听。

2)我还尝试了 Firebase Dispatcher,它工作,但不超过应用程序关闭。

3)推荐的方法是 WorkManager 保证执行超过进程杀死和内部使用 RegisterNetworkRequest ()

支持第三种方法的最大证据是 安卓文档本身,特别是对于后台应用程序。

还有 给你

在 Android 7.0中,我们删除了三个常用的隐式广播(CONNECTIVITY _ ACTION,ACTION _ NEW _ PICTURE 和 ACTION _ NEW _ VIDEO) ,因为这些广播可以同时唤醒多个应用的后台进程,并且会使内存和电池变得紧张。如果您的应用程序正在接收这些信息,请利用 Android 7.0来迁移到 JobScheduler 和相关 API。

到目前为止,它工作良好,我们使用周期性工作管理器请求。

更新: 我最终写了关于它的2系列 中柱中柱

2020年11月:

我已经处理了太多被谷歌否定的项目。最后,我找到了一个解决方案,我的特殊需求使用“ registerNetworkCallback”,谷歌目前建议。

我需要的是一个简单的方法来检测我的设备有一个在 WIFI 分配的 IPv4。 (我还没有尝试过其他案例,我的要求非常具体,但也许这种方法,没有过时的元素,将作为其他案例的基础)。

在 API 23、24和26(物理设备)以及 API 28和29(模拟设备)上进行了测试。

    ConnectivityManager cm
= (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder builder = new NetworkRequest.Builder();


cm.registerNetworkCallback
(
builder.build(),
new ConnectivityManager.NetworkCallback()
{
@Override
public void onAvailable(Network network)
{
//Actions to take with Wifi available.
}
@Override
public void onLost(Network network)
{
//Actions to take with lost Wifi.
}
}


);

(在“ MainActivity. Oncreate”中实现)

注意: 在清单中需要“ android.permission. ACCESS _ NETWORK _ STATE”

可以使用带滤镜的广播

 <receiver
android:name=".receivers.ConnectionType"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
</intent-filter>
</receiver>

在此之后,您可以监听这样返回的值

  @Override
public void onReceive(Context context, Intent intent) {


int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN);
if(wifiState==WifiManager.WIFI_STATE_ENABLED){
Toast.makeText(context, "WIFI on", Toast.LENGTH_SHORT).show();


}else if(wifiState==WifiManager.WIFI_STATE_DISABLED) {
Toast.makeText(context, "WIFI OFF", Toast.LENGTH_SHORT).show();
}




}

每次启用或禁用 WIFI 时都会触发