Je construis une application VoIP. Pendant un appel VoIP lorsque l'utilisateur bascule entre Wi-Fi et données mobiles, j'ai un problème à gérer le scénario.
Dans mon activité d’écran d’appel, je me suis inscrit pour le récepteur, ce qui m’aide à recevoir des informations sur les scénarios de changement de réseau.
C’est le code que j’utilise pour détecter les changements de réseaux dans la méthode onRecieve.
conn_name est une variable de niveau de classe privée contenant le nom de la connexion précédente.
ConnectivityManager connectivity_mgr = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE));
NetworkInfo net_info = connectivity_mgr.getActiveNetworkInfo();
if (net_info != null && net_info.isConnectedOrConnecting() && !conn_name.equalsIgnoreCase("")) {
new_con = net_info.getExtraInfo();
if (new_con != null && !new_con.equalsIgnoreCase(conn_name))
network_changed = true;
conn_name = (new_con == null) ? "" : new_con;
connectionStatus ="connected";
} else {
if (net_info != null && conn_name.equalsIgnoreCase("")){
conn_name = net_info.getExtraInfo();
connectionStatus ="connected";
network_changed = true;
}else if(!new_con.equals(conn_name)) {
conn_name = "";
connectionStatus ="disconnected";
network_changed = true;
}
}
Donc, en utilisant la méthode ci-dessus, je suis capable de détecter les changements de réseau. Mais une chose particulière se produit lorsque je suis connecté au WiFi.
Lorsque mon application démarre initialement, elle est connectée aux données mobiles. Lorsque l'utilisateur entre dans sa zone WiFi connue, il se connecte à son réseau WiFi connu. Comme le Wi-Fi est toujours choisi comme itinéraire par défaut, Android passe au Wi-Fi et je reçois la notification réseau l'informant que le Wi-Fi a été activé.Par conséquent, je mets à jour l'adresse IP de mes applications en adresse IP WiFi.Aucun problème ici. dans le même temps, mais getActiveNetworkInfo () me dit que je suis clairement connecté au WiFi même si j'étais connecté tôt aux données mobiles.
Le problème survient lorsque l'utilisateur éteint le bouton WiFi et que les données mobiles sont toujours connectées mais que je reçois toujours la notification de désactivation du Wi-Fi . Cela m'indique que le réseau est déconnecté même lorsque mon téléphone est toujours connecté à données mobiles . Mais après une seconde je reçois une notification que les données mobiles sont connectées . Mais une fois que je reçois le réseau déconnecté, j'ai fermé mon appel VoIP . Donc, quand je reçois une notification pour WiFi commuté comment puis-je m'assurer que les données mobiles sont toujours connectées . J'ai essayé getActiveNetworkInfo (), mais il est nul lorsque je reçois une notification pour le WiFi désactivé.Alors aidez-moi à résoudre ce problème.
J'ai suivi ces liens.
Appel de l'API Android pour déterminer le paramètre utilisateur "Données activées"
Comment savoir si les "données de réseau mobile" sont activées ou non (même si elles sont connectées par WiFi)?
En utilisant le lien ci-dessus, je suis en mesure de détecter que le bouton de données mobiles a été activé lorsque l'utilisateur s'est connecté à mobiledata.it, ce qui est vrai. Mais le problème se produit lorsque ce cas particulier se produit.
"Maintenant, lorsque le wifi est désactivé, je reçois une notification, mais cela indique que les données mobiles sont désactivées, même lorsque mes données mobiles sont activées. Je ne suis pas en mesure de gérer cette situation car je déconnecte mes appels lorsque je reçois ma notification déconnectée"
Vous pouvez utiliser les API de ConnectivityManager
: particulièrement dans votre cas d'utilisation vous êtes intéressé par registerDefaultNetworkCallback()
:
public class TestActivity extends AppCompatActivity {
private ConnectivityManager manager;
private final ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
super.onAvailable(network);
// this ternary operation is not quite true, because non-metered doesn't yet mean, that it's wifi
// nevertheless, for simplicity let's assume that's true
Log.i("vvv", "connected to " + (manager.isActiveNetworkMetered() ? "LTE" : "WIFI"));
}
@Override
public void onLost(Network network) {
super.onLost(network);
Log.i("vvv", "losing active connection");
}
};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
manager.registerDefaultNetworkCallback(networkCallback);
}
@Override
protected void onDestroy() {
super.onDestroy();
manager.unregisterNetworkCallback(networkCallback);
}
}
Mon appareil se connecte à LTE en environ une demi-seconde.
Cela signifie que vous ne pouvez pas savoir à l'avance si l'appareil se connectera éventuellement à LTE ou s'il ne le fera pas à ce moment-là, lorsque le WIFI sera déconnecté. Ainsi, vous pouvez adopter l'approche suivante: poster une action sur un gestionnaire pour qu'elle se produise dans une seconde et, dans cette action, annuler l'appel. Si la connexion apparaît bientôt - annulez l'action déjà postée. Si vous vous retrouvez dans un code Runnable
, la connexion n’est pas établie rapidement, ce qui signifie que vous devez mettre fin à l’appel.
public class TestActivity extends AppCompatActivity {
private ConnectivityManager manager;
private final Handler handler = new Handler();
private final ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
super.onAvailable(network);
Log.i("vvv", "connected to " + (manager.isActiveNetworkMetered() ? "LTE" : "WIFI"));
// we've got a connection, remove callbacks (if we have posted any)
handler.removeCallbacks(endCall);
}
@Override
public void onLost(Network network) {
super.onLost(network);
Log.i("vvv", "losing active connection");
// Schedule an event to take place in a second
handler.postDelayed(endCall, 1000);
}
};
private final Runnable endCall = new Runnable() {
@Override
public void run() {
// if execution has reached here - feel free to cancel the call
// because no connection was established in a second
}
};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
manager.registerDefaultNetworkCallback(networkCallback);
}
@Override
protected void onDestroy() {
super.onDestroy();
manager.unregisterNetworkCallback(networkCallback);
handler.removeCallbacks(endCall);
}
}
L'inconvénient de cette approche est que registerDefaultNetworkCallback()
est disponible à partir de l'API 24. Il n'existe pas d'alternative dans ConnectivityManagerCompat
non plus. Au lieu de cela, vous pouvez utiliser registerNetworkCallback()
qui est disponible à partir de l’API 21.
Vous pouvez utiliser BroadcastReceiver
et enregistrer NETWORK_STATE_CHANGED_ACTION
& WIFI_STATE_CHANGED_ACTION
.
private boolean isConnected;
final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent == null || intent.getAction() == null)
return;
switch (intent.getAction()){
case WifiManager.NETWORK_STATE_CHANGED_ACTION :
case WifiManager.WIFI_STATE_CHANGED_ACTION :
if (!isConnected && isOnline(BaseActivity.this)) {
isConnected = true;
// do stuff when connected
Log.i("Network status: ","Connected");
}else{
isConnected = isOnline(BaseActivity.this);
Log.i("Network status: ","Disconnected");
}
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
isConnected = isOnline(this);
final IntentFilter filters = new IntentFilter();
filters.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
filters.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
registerReceiver(broadcastReceiver, filters);
}
public static boolean isOnline(Context ctx) {
ConnectivityManager cm = (ConnectivityManager) ctx
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm != null
? cm.getActiveNetworkInfo()
: null;
return netInfo != null && netInfo.isConnectedOrConnecting();
}
Mise à jour N'oubliez pas de désenregistrer le destinataire BroadcastReceiver
onDestroy
@Override
protected void onDestroy() {
unregisterReceiver(broadcastReceiver);
super.onDestroy();
}
La réponse que vous recherchez est une BroadcastReceiver
. Vérifiez le lien ci-dessous.
BroadcastReceiver lorsque l'état du réseau wifi ou 3G est modifié
J'espère que cela vous aidera à résoudre votre problème et, le cas échéant, envisagez de clore votre question.