J'ai besoin de détecter quand j'ai une connectivité réseau via WIFI. Quelle émission est envoyée pour établir qu'une connexion réseau valide a été établie. J'ai besoin de valider l'existence d'une connexion réseau valide pour HTTP. Qu'est-ce que je devrais écouter et quels tests supplémentaires dois-je effectuer pour savoir qu'une connexion valide existe.
Vous pouvez enregistrer un BroadcastReceiver
pour être averti lorsqu'une connexion WiFi est établie (ou si la connexion a été modifiée).
Enregistrez le BroadcastReceiver
:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
registerReceiver(broadcastReceiver, intentFilter);
Et ensuite, dans votre BroadcastReceiver
, faites quelque chose comme ceci:
@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
}
}
}
Pour plus d'informations, voir la documentation sur BroadcastReceiver
et WifiManager
Vous devez bien sûr vérifier si le périphérique est déjà connecté au WiFi auparavant.
EDIT: Grâce à ban-geoengineering, voici une méthode pour vérifier si le périphérique est déjà connecté:
private boolean isConnectedViaWifi() {
ConnectivityManager connectivityManager = (ConnectivityManager) appObj.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
return mWifi.isConnected();
}
Le meilleur qui a fonctionné pour moi:
<receiver Android:name="com.AEDesign.communication.WifiReceiver" >
<intent-filter Android:priority="100">
<action Android:name="Android.net.wifi.STATE_CHANGE" />
</intent-filter>
</receiver>
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"/>
Pour moi seulement WifiManager.NETWORK_STATE_CHANGED_ACTION
fonctionne.
Enregistrer un récepteur de diffusion:
_IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
registerReceiver(broadcastReceiver, intentFilter);
_
et recevez:
_@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
}
}
_
Les réponses données par l'utilisateur @JPM et @usman sont vraiment très utiles. Cela fonctionne bien, mais dans mon cas, il s'agit de onReceive
plusieurs fois dans mon cas 4 fois, de sorte que mon code est exécuté plusieurs fois.
Je fais quelques modifications et fais selon mes besoins et maintenant il vient seulement 1 fois
Voici la classe Java pour la diffusion.
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 ----- ");
}
}
}
}
dans 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"/>
Vous pouvez établir une connexion Wi-Fi si vous donnez à l'utilisateur le choix de remplacer le comportement normal de demander à chaque fois.
J'ai choisi d'utiliser trois méthodes ...
public boolean isOnline()
{
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
return (networkInfo != null && networkInfo.isConnected());
}
Il s’agit d’une vérification rapide s’il existe une connexion Internet Wifi ou CellData. De là, vous pouvez choisir l'action que vous voulez entreprendre. Est-ce en mode avion doit être vérifié aussi.
Sur un fil séparé. J'ai mis une variable IpAddress à = "" et interroge jusqu'à ce que j'ai une adresse IP valide.
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);
Un autre extrait de code ... S'il n'est pas activé, activez-le (avec l'autorisation préalable des utilisateurs).
if(wifi.isWifiEnabled()!=true)wifi.setWifiEnabled(true);
Pour détecter l’état de la connexion WIFI, j’ai utilisé CONNECTIVITY_ACTION de la classe ConnectivityManager pour:
IntentFilter filter=new IntentFilter();
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(receiver, filter);
et de votre 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: fonctionne bien pour moi :)
Ce code ne nécessite aucune autorisation. Il est limité aux changements d'état de la connectivité du réseau Wi-Fi (aucun autre réseau n'est pris en compte). Le récepteur est publié de manière statique dans le fichier AndroidManifest.xml et n'a pas besoin d'être exporté car il sera appelé par le système protected broadcast
, NETWORK_STATE_CHANGED_ACTION
=, à chaque changement d'état de connectivité réseau.
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>
_
Classe 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();
}
}
}
_
Autorisations:
_None
_
Android O a supprimé la possibilité de recevoir les émissions implicites en cas de changement d'état Wi-Fi. Donc, si votre application est fermée, vous ne pourrez pas les recevoir. Le nouveau WorkManager
a la capacité de fonctionner lorsque votre application est fermée. Je l'ai donc expérimenté un peu et cela semble fonctionner assez bien:
Ajoutez ceci à vos dépendances:
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()
}
}
N'oubliez pas qu'il s'agissait simplement d'un test rapide pour une notification ponctuelle. Il reste encore beaucoup à faire pour toujours être averti lorsque le WiFi est activé ou désactivé.
PS: Lorsque l'application est force quit, le travailleur n'est pas démarré, il semble que WorkManager
annule les demandes à ce moment-là.
Voici un exemple de mon code, qui prend en compte la préférence des utilisateurs de n'autoriser que les communications lorsque connecté au Wifi.
J'appelle ce code de l'intérieur d'un IntentService
avant d'essayer de télécharger des fichiers.
Notez que NetworkInfo
sera null
s'il n'y a aucune connexion réseau.
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;
}
J'ai deux méthodes pour détecter une connexion WIFI recevant le contexte de l'application:
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;
}
public boolean isConnectedWifi(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
return networkInfo.isConnected();
}
J'ai utilisé ce code:
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
}
}
}
};
}
1) J'ai également essayé l'approche Récepteur de diffusion même si je sais que CONNECTIVITY_ACTION/CONNECTIVITY_CHANGE est obsolète dans l'API 28 et n'est pas recommandé. Egalement lié à l'utilisation d'un registre explicite, il écoute tant que l'application est en cours d'exécution.
2) J'ai aussi essayé Firebase Dispatcher qui fonctionne, mais pas au-delà de l'application tuée.
3) La solution recommandée est WorkManager pour garantir l'exécution au-delà du processus tué et en interne à l'aide de registerNetworkRequest ()
La plus grande preuve en faveur de l'approche n ° 3 est renvoyée par doc Android lui-même. Surtout pour les applications en arrière-plan.
Aussi ici
Dans Android 7.0, nous supprimons trois diffusions implicites couramment utilisées - CONNECTIVITY_ACTION, ACTION_NEW_PICTURE et ACTION_NEW_VIDEO - car elles permettent de réactiver les processus d'arrière-plan de plusieurs applications à la fois, d'alléger la mémoire et la batterie. Si votre application les reçoit, utilisez plutôt Android 7.0 pour migrer vers JobScheduler et les API associées.
Jusqu'à présent, cela fonctionne très bien pour nous en utilisant une requête Periodic WorkManager.
Mise à jour: j'ai fini par écrire 2 séries post moyen à ce sujet.
Pour tous ceux qui profitent de CONNECTIVITY_CHANGE diffusion, veuillez noter que l'application n'est plus déclenchée lorsque l'application est en arrière-plan dans Android O.
https://developer.Android.com/about/versions/o/background.html