5

i am working with ionic 2 RC1 and using sublime as text editor. i need to check if the network connection is connected or not. so for this purpose i am using ionic native Network for this purpose. but i am facing problem with the Network.onDisconnect() Observable. I have edited initializeApp() method in which i check for network connection and show alert if connection got disconnected. the I have the following code written in app.component.ts

  showAlert(title, msg) {
    let alert = this.alertCtrl.create({
      title: title,
      subTitle: msg,
      buttons: ['OK']
    });
    alert.present();
  }

  initializeApp() {
    this.platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      let disconnectSubscription = Network.onDisconnect().subscribe(() => {
        this.showAlert("Error", "No internet connection");
      });
      StatusBar.styleDefault();
    });
  }

The problem i am facing is that alert is shown twice if application get disconnected from internet. I have found similar issue in this post but it got unanswered. Any help on this regard will be much appreciated. Thanks in advance !

sebaferreras
  • 44,206
  • 11
  • 116
  • 134
M. Habib
  • 623
  • 1
  • 9
  • 15

5 Answers5

9

In order to avoid that, you can filter the events, and just do something when the state changes from online to offline, or from offline to online (and not every time the event is being fired by the plugin). So basically you can create a service to handle all this logic like this:

import { Injectable } from '@angular/core';
import { Network } from 'ionic-native';
import { Events } from 'ionic-angular';

export enum ConnectionStatusEnum {
    Online,
    Offline
}

@Injectable()
export class NetworkService {

    private previousStatus;

    constructor(private eventCtrl: Events) {
        this.previousStatus = ConnectionStatusEnum.Online;
    }

    public initializeNetworkEvents(): void {
        Network.onDisconnect().subscribe(() => {
            if (this.previousStatus === ConnectionStatusEnum.Online) {
                this.eventCtrl.publish('network:offline');
            }
            this.previousStatus = ConnectionStatusEnum.Offline;
        });
        Network.onConnect().subscribe(() => {
            if (this.previousStatus === ConnectionStatusEnum.Offline) {
                this.eventCtrl.publish('network:online');
            }
            this.previousStatus = ConnectionStatusEnum.Online;
        });
    }
}

So our custom events (network:offline and network:online) will only be fired when the connection truly changes (fixing the scenario when multiple online or offline events are fired by the plugin when the connection state hasn't changed at all).

Then, in your app.component file you just need to subscribe to our custom events:

// Offline event
this.eventCtrl.subscribe('network:offline', () => {
  // ...            
});

// Online event
this.eventCtrl.subscribe('network:online', () => {
  // ...            
});
sebaferreras
  • 44,206
  • 11
  • 116
  • 134
  • This still fires twice for me – Mike Aug 22 '17 at 09:52
  • 1
    There are many of these types of solutions provided as answers to this question in many posts online. This is definitely the most elegant answer. However, it will not work like the other solutions dont work (I've tried them). The event seems to fire multiple times simultaneously or fire faster than above code can execute and filter the superfluous events of the network. – JurgenW Dec 05 '17 at 08:41
  • Hmm... I use the code above in a few apps and never faced that issue. If there's only one instance of the `NetworkService` even if the plugin event is triggered very fast it should be handled by the service logic @JurgenW. – sebaferreras Dec 05 '17 at 10:19
  • I didnt try your code. It indeed depends on having a single instance running code when going off or online, see my answer. – JurgenW Dec 05 '17 at 10:40
1

i think you should use below code to avoid that problem.

import { Network } from 'ionic-native';

    @Injectable()
    export class NetworkService {
    previousStatus:any
        constructor() {

        }       

    showAlert(title, msg) {
        let alert = this.alertCtrl.create({
          title: title,
          subTitle: msg,
          buttons: ['OK']
        });
        alert.present();
      }        
          this.initializeApp();
          this.network.onDisconnect().subscribe( () => {
                if (this.previousStatus === Online) {
                    this.showAlert("Error", "No internet connection");
                }
                this.previousStatus = Offline;
            });
            Network.onConnect().subscribe(() => {
                if (this.previousStatus === Offline) {
                 this.showAlert("Alert", "Network was connected");
                }
                this.previousStatus = Online;
            });
        }
    }
Sandip Moradiya
  • 706
  • 1
  • 11
  • 30
0

I have solved this issue. The real problem that people are having is that in a lot of cases multiple instances of Ionic pages are created. So if you register an event receiver on a page and then start navigating back and forth through the App, the event receiver will be registered multiple times. The solution is to add the event receiver in app.component.ts 's intializeApp method, like so:

// top of page 
import { Observable } from 'rxjs/Observable';

initializeApp() {
    this.platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      this.statusBar.styleDefault();
      this.splashScreen.hide();

      var offline = Observable.fromEvent(window, "offline");
      var online = Observable.fromEvent(window, "online");

      offline.subscribe(() => {          
          console.log('Offline event was detected.');
      });

      online.subscribe(() => {
          console.log('Online event was detected.');        
      })
    });
  }

Both log messages will only be triggered once when you go online/offline respectively no matter how much you navigate within the App.

JurgenW
  • 307
  • 2
  • 4
  • 18
  • *So if you register an event receiver on a page and then start navigating back and forth through the App, the event receiver will be registered multiple times* That's only true if users don't unsubscribe from the events when leaving the page (which is wrong, but it has nothing to do with the plugin). Handling this in the `app.component.ts` file or in a shared service is recommended, but it should work properly if you **do things correctly** in any page of the app. – sebaferreras Dec 05 '17 at 10:22
  • this only work in browser, doesn't work in real device! – Snowbases Jun 03 '21 at 17:38
0

Your real problem is, that you don't use an binded constructor in your actual class! If you want to call that for example in app.component.ts then just add the parameter to your

constructor(public network: Network)

and use is besides Network directly! so call: this.network.... then the best would be to control that with a static variable like:

static checkedState: boolean = false;

after you wrote your OnConnect statement set the checkedState to true and catch that with an if statement on both: OnDisconnect and OnConnect and you should only get once a message. By the way: i had that behavior also with eventsCtrl and I don't know If Ionic is handling these things better with other contro mechanism's.

Greets Rebar

Rebar
  • 1,076
  • 10
  • 19
0
this.network.onDisconnect().subscribe(() => {
    if(this.status == true){
      console.log("no need to call again")
      alert("no need to call again")
    }
    else{
      this.status = true;
      console.log(this.status)
      console.log('network was disconnected :-(');
      // alert('network was disconnected :-(');
      // this.prompt.ShowAlert('Connection Problem','Please check your internet connection and try again.')

      let modal = this.modalCtrl.create('NoInternetPage');
      modal.present();

      modal.onDidDismiss((info) => {
        console.log("on modal dismiss")
      });
    }



  });

  this.network.onConnect().subscribe(() => {
    this.status = false;
  })

you can try this simple trick