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


140

我需要检测何时可以通过WIFI进行网络连接。发送什么广播以建立有效的网络连接。我需要验证是否存在用于HTTP的有效网络连接。我应该听什么以及需要进行哪些其他测试才能知道存在有效的连接。


这个问题的部分已经在这里找到答案,我发现:stackoverflow.com/questions/4238921/...
Androider

1
但是仍然存在何时检查这些条件的问题?
Androider 2011年

1
我想反馈一下是否会发生广播接收机可能捕获的广播?
Androider 2011年

1
我如何在Android O上执行此操作,因为不再允许在清单中注册像android.net.wifi.STATE_CHANGE之类的隐式广播接收器(请参阅developer.android.com/guide/components/…)。如果我们在应用程序活动中注册它(例如onCreate),则必须在onStop()中将其注销,并且我们将不再接收与wifi相关的事件
zafar142003

Answers:


126

您可以注册一个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。

编辑:感谢ban-geoengineering,这是一种检查设备是否已经连接的方法:

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

1
为什么选择SUPPLICANT_CONECTION_CHANGE_ACTION?我以为只是CONNECTION_CHANGE次更改广播。为什么选择SUPPLCANT ???谢谢
Androider

2
嗯?我看不到名为connection_change的操作...?我只看到wifi状态已更改,但是该操作仅指示wifi是否已启用(或启用/禁用),而不是是否已连接。
摩根大通

9
对我来说WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION在建立/丢失与已知wifi站的连接的情况下不起作用。但是WifiManager.NETWORK_STATE_CHANGED_ACTION确实可以工作。
2013年

1
“ android.net.wifi.STATE_CHANGE”为我工作。请在下面检查我的答案
M. Usman Khan 2014年

1
“当然,在此之前,您应该检查设备是否已经连接到WiFi。” -因此,要获取初始的Wi-Fi状态,您可以使用此方法...private boolean isConnectedViaWifi() { ConnectivityManager connectivityManager = (ConnectivityManager) appObj.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); return mWifi.isConnected(); }
ban-geoengineering 2014年

106

最适合我的:

Android清单

<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"/>

1
我认为这是专门针对wifi状态变化的最佳答案。谢谢
Mikel 2014年

4
为了将来方便参考,该硬编码操作为WifiManager.NETWORK_STATE_CHANGED_ACTION
Anonsage 2014年

3
if(info!= null && info.isConnected())=没有意大利面。
gswierczynski 2015年

1
我们需要编写任何代码来发送主要活动中的广播吗?
Nisari Balakrishnan 2016年

1
我如何在Android O上执行此操作,因为不再允许在清单中注册像android.net.wifi.STATE_CHANGE之类的隐式广播接收器(请参阅developer.android.com/guide/components/…)。如果我们在应用程序活动中注册它(例如onCreate),那么它将必须在onStop()中注销,并且我们将不再接收与wifi相关的事件。
zafar142003 '18

18

对我来说只有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
    }      
}

1
同样对我来说,只有WifiManager.NETWORK_STATE_CHANGED_ACTION可以工作,为什么只有这样可以解释?
benchuk 2015年

11

用户@JPM和@usman给出的答案确实非常有用。它工作正常,但就我而言,它是onReceive多次出现4次因此我的代码会多次执行。

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

这是广播的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 ----- ");
        }

    }
}
}

在AndroidManifest中

<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"/>

1
什么是wifiState?
behelit '16

1
还想知道wifiState是什么,它是如何生成的
Evan Parsons

1
@behelit现在,“ wifiState”已存在于已编辑的答案中。
Yog Guru

8

可以,如果你给用户一个选择,覆盖每一次询问的正常行为启动WiFi连接。

我选择使用三种方法...

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

这是快速检查是否有Internet连接Wifi或CellData。在这里,您可以选择要采取的措施。是否处于飞行模式也需要检查。

在单独的线程上。我将变量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);  

7

要检测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
                }
            }
        }

    }

ps:对我来说很好:)


1
仅供参考,使用Android 6,当您具有有效的单元数据连接时,wifi状态的更改不会触发CONNECTIVITY_ACTION。他们这样做的唯一原因是连接状态受到了影响,现在却没有。
Bruce

5

此代码完全不需要权限。仅限于Wi-Fi网络连接状态更改(不考虑任何其他网络)。接收机静态发布在AndroidManifest.xml文件中,并不需要被导出,因为它会被系统调用protected broadcastNETWORK_STATE_CHANGED_ACTION在每个网络连接状态的变化。

AndroidManifest:

<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

1
该作品可在运行<API 26的设备上运行。正如@Isham所建议的那样,Android O不再支持该操作
tiagocarvalho92

3

这是我的代码示例,其中考虑了用户在连接到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;
}

3

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
    }
}

MainActivity.kt

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时,还有更多工作要做以始终得到通知。

PS:当应用程序被强制退出时,工作程序尚未启动,似乎WorkManager正在取消请求。


即使我的应用程序处于强制状态,有什么方法可以启动工作程序。仅当打开应用程序时,工作管理器才使用.setRequiredNetworkType(UNMETERED)。有什么方法可以触发工作程序,即使应用程序处于终止状态(强制关闭状态)。因为隐式的广义转换接收器也有所限制。最佳选择是什么?
Suresh

2

我使用以下代码:

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
                    }
                }
            }
        };
    }

2

我有两种方法来检测接收到应用程序上下文的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();
}

我如何在Android O上执行此操作,因为不再允许在清单中注册像android.net.wifi.STATE_CHANGE之类的隐式广播接收器(请参阅developer.android.com/guide/components/…)。如果我们在应用程序活动中注册它(例如onCreate),则必须在onStop()中将其注销,并且我们将不再接收与wifi相关的事件
zafar142003


2

1)即使我知道CONNECTIVITY_ACTION / CONNECTIVITY_CHANGE,我也尝试了广播接收器方法在API 28中已弃用,也不推荐使用,。此外,还必须使用显式寄存器,只要应用程序正在运行,它就会监听。

2)我还尝试了Firebase Dispatcher,它可以运行,但不能被应用杀死。

3)找到的推荐方法是WorkManager,以确保在进程被杀死之前和内部使用registerNetworkRequest()来确保执行

支持Android 3的最大证据是Android文档本身。尤其适用于后台应用程序。

也在这里

在Android 7.0中,我们删除了三个常用的隐式广播(CONNECTIVITY_ACTION,ACTION_NEW_PICTURE和ACTION_NEW_VIDEO),因为它们可以立即唤醒多个应用程序的后台进程,并占用大量内存和电池。如果您的应用程序收到这些消息,请利用Android 7.0迁移到JobScheduler和相关的API。

到目前为止,使用Periodical WorkManager请求对我们而言效果很好。

更新:我最终写了2系列有关它的中篇文章

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.