Android - How to disable captive portal detection? How to remove exclamation mark on Wi-Fi or signal icon in Lollipop?

It's simple. In the terminal (requires root), or in adb shell (does not require root), issue the command

settings put global captive_portal_detection_enabled 0

and reboot. It should be disabled. The existing state can also be verified via the command

settings get global captive_portal_detection_enabled

A response of "null" indicates the global key value has not been set and Android will fall back to default of being on and performing the detection. If the detection is disabled the response of "0" will be received.

More info: Android : How to remove “captive portal” detection on android 4.2.2 and 4.3

It also works in 5.

In the Android M Developer Preview for Shamu (Nexus 6), and possibly other builds of this OS, the captive_portal_server global is used by the OS regardless of the state of captive_portal_detection_enabled in order to determine health of a WiFi network.

For WiFi networks, it will not only draw an exclamation mark on the strength icon, it will blacklist that SSID from auto-reconnecting if it does not successfully curl the URL specified in the the captive_portal_server global via that SSID. Manual reconnection is allowed but will only remain connected if you have captive_portal_detection_enabled and choose "Use This Network As-Is" manually, each time you connect to that WiFi SSID. This override is temporary.

For mobile provider networks, the captive_portal_server is only used to draw an exclamation mark on the strength icon but will remain connected, and traffic will flow if the connection is functional.

On your rooted device, the solution is to re-enable captive_portal_detection_enabled if you have disabled it, connect to that WiFi network, select "Use This Network As-Is" from the drop down menu in the captive portal pop-up, disable your mobile network data to focus on determining a website that can be retrieved via your Wifi network by logging in to your captive portal and then use a browser to find one that works. After that, you can disable captive_portal_detection_enabled to prevent the annoying pop-up.

To reenable your captive_portal_detection, if you previously disabled it, issue the command:

settings put global captive_portal_detection_enabled 1

Disable your Mobile Network (under Settings - Data Usage - Mobile Data - Off), to force the phone to use the WiFi network for all traffic, temporarily. This will not be required once you have all of your settings where they need to be.

Android M seems to require a website that loads successfully and does not actively return a 204 (no content).

A couple of options include but are not limited to
the network router
localhost (if you have an onboard simple HTTP server)
and the list goes on...

After finding one that works for your WiFi Network (often requires more imagination and attempts behind corporate web gateway proxies that do not like HTTPS traffic prior to authentication), you can save the server.

Save the server by running this in your root enabled terminal app, replacing the example URL with the one you are hoping will work:

settings put global captive_portal_server

Restart your device. Try it out. Once you are happy with the behavior of the Exclamation Marks on the icons, the final step is to disable the captive portal pop-up, which is one of the most unfortunate inventions of this decade.

Issue command:

settings put global captive_portal_detection_enabled 0

If you find yourself in a different country or WiFi situation where issues arise, unfortunately you will need to repeat the above from the beginning, reenabling captive_portal_detection_enabled, restarting, finding the right server and then disabling the portal detection afterwards.