Ionic 3 network connectivity check how to implement for all pages (components)?


#23

Add

getNetworkStatus(): Observable

:wink:

import { Injectable } from '@angular/core';

import { Events } from 'ionic-angular'

import { Network } from '@ionic-native/network'

import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';

export enum ConnectionStatus {
    Online,
    Offline
}

@Injectable()
export class NetworkService {

    public status: ConnectionStatus;
    private _status: BehaviorSubject<ConnectionStatus> = new BehaviorSubject(null);

    constructor(
        public network: Network,
        public events: Events
    ) {
        this.status = ConnectionStatus.Online;
    }

    public initializeNetworkEvents(): void {

        /* OFFLINE */
        this.network.onDisconnect().subscribe(() => {
            if (this.status === ConnectionStatus.Online) {
                this.setStatus(ConnectionStatus.Offline);
            }
        })

        /* ONLINE */
        this.network.onConnect().subscribe(() => {
            if (this.status === ConnectionStatus.Offline) {
                this.setStatus(ConnectionStatus.Online);
            }
        })

    }

    public getNetworkType(): string {
        return this.network.type
    }

    public getNetworkStatus(): Observable<ConnectionStatus> {
        return this._status.asObservable();
    }
    
    private setStatus(status: ConnectionStatus) {
        this.status = status;
        this._status.next(this.status);
    }
}


Binding to service property needs page refreshing!
#24

Will test this as soon as I get my hands on it again. Thanks!


#25

Congrats, best practice…


#26

Dear Friends, I have an Error: StaticInjectorError(AppModule)[NetworkProvider -> Network]:
StaticInjectorError(Platform: core)[NetworkProvider -> Network]:
NullInjectorError: No provider for Network!

Thanking you


#27

Hope this will help


#28

It’s a nice solution! Thanks!
But i have a problem when i need to check network status on app boot, it’s always returns null.

Here is my code:

import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
import { NetworkProvider } from '../providers/network/network';
import { NgZone } from '@angular/core';

@Component({
  templateUrl: 'app.html'
})
export class MyApp {
  rootPage: any = 'LoginPage';
  isOffline: boolean;

  constructor(
    platform: Platform,
    statusBar: StatusBar,
    splashScreen: SplashScreen,
    public networkProvider: NetworkProvider,
    public ngZone: NgZone
  ) {
    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.
      statusBar.styleDefault();
      splashScreen.hide();
      statusBar.backgroundColorByHexString('#f6f6f6');
      this.networkProvider.initializeNetworkEvents();
      this.checkNetwork();
    });
  }

  showOfflineAlert(data) {
    this.ngZone.run(() => {
      this.isOffline = !!data;
    });
  }

  checkNetwork() {
    this.networkProvider.getNetworkStatus().subscribe(data => {
      console.log('platform ready', data);
      this.showOfflineAlert(data);
    });
  }
}

Any thoughts guys? =D


#29

Cute code for sure. Unfortunately doesn’t work at all for me. Never enters subscription events whenever I close or open my wifi connection on my PC. I’m running Windows 10.

UPDATE : this works perfectly fine on an Android device. Just not in a Chrome browser in Windows 10.

Ionic infos :

ionic (Ionic CLI) : 4.1.2
Ionic Framework : ionic-angular 3.9.2
@ionic/app-scripts : 3.2.0
cordova (Cordova CLI) : 8.1.1 (cordova-lib@8.1.0)
Cordova Platforms : none
Cordova Plugins : no whitelisted plugins (1 plugins total)
NodeJS : v10.9.0
npm : 6.2.0
OS : Windows 10

Here’s my code (after applying latest suggestions in the thread) :

networkService.ts

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

export enum ConnectionStatus {
    Online,
    Offline
}

@Injectable()
export class NetworkService {

    public status: ConnectionStatus;
    private _status: BehaviorSubject<ConnectionStatus> = new BehaviorSubject(null);

    constructor(
        public network: Network,
        public events: Events
    ) {
        this.status = ConnectionStatus.Online;
    }

    public initializeNetworkEvents(): void {

        console.log('Subscribe to onDisconnect events');
        /* OFFLINE */
        this.network.onDisconnect().subscribe(() => {
            if (this.status === ConnectionStatus.Online) {
                this.setStatus(ConnectionStatus.Offline);
            }
        })

        console.log('Subscribe to onConnect events');
        /* ONLINE */
        this.network.onConnect().subscribe(() => {
            if (this.status === ConnectionStatus.Offline) {
                this.setStatus(ConnectionStatus.Online);
            }
        })

    }

    public getNetworkType(): string {
        return this.network.type
    }

    public getNetworkStatus(): Observable<ConnectionStatus> {
        return this._status.asObservable();
    }

    private setStatus(status: ConnectionStatus) {
        this.status = status;
        this._status.next(this.status);
    }
}

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';
import { Network } from '@ionic-native/network';

import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { NetworkService } from './providers/networkService';

@NgModule({
  declarations: [
    MyApp,
    HomePage
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [
    Network,
    NetworkService,
    StatusBar,
    SplashScreen,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}

app.components.ts

import { Component } from '@angular/core';
import { Platform, ToastController } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';

import { HomePage } from '../pages/home/home';
import { NetworkService } from './providers/networkService';

@Component({
  templateUrl: 'app.html'
})

export class MyApp {
  rootPage:any = HomePage;

  constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen,
    public networkService: NetworkService,
    public toast: ToastController,) {
      
    platform.ready().then(() => {

      this.initializeApp();

      statusBar.styleDefault();
      splashScreen.hide();
    });
  }

  initializeApp(): void {

    this.networkService.initializeNetworkEvents();

    this.networkService.getNetworkStatus().subscribe(data => {
      console.log('platform ready', data);
      this.toast.create ({
        message: data + ' ' +  this.networkService.getNetworkType(),
        duration: 3000,
      }).present();;
    });
  }

}

I debug with Chrome and see the network subscription inside the provider (onConnect() and onDisconnect()) but they never get raised. Any idea why ?


#30

Application reference allows

  • allows to invoke application-wide change detection by calling appRef.tick()
  • it allows to add/remove views to be included in or excluded from change detection using attachView() and detachView()
  • provides a list of registered components and component types using componentTypes and components and some other change detection related information

Use the following code works perfectly fine for me. I have created a shared provider which is accessed by all the pages in the app.
Step 1: Import the

import { Component, ViewChild,ApplicationRef } from '@angular/core';

Application Ref
Step 2:
public applicationRef: ApplicationRef, in the constructor
Step 3: Run the following function when platform ready

   {
       this.network.onDisconnect().subscribe(() => {
      this.connectedToInternet = false;
     // this.isConnectedObserver.next(this.connectedToInternet);
        this.applicationRef.tick();
      // alert("INTERNET DISCONNECTED");
        console.log("INTERNET DISCONNECTED", this.connectedToInternet);
        
    });

    this.network.onConnect().subscribe(() => {
        
     this.connectedToInternet=true;
   // this.isConnectedObserver.next(this.connectedToInternet);
    this.applicationRef.tick();
    // alert("INTERNET CONNECTED.Please wait...INITIALIZING...Please upload the unsaved local data if any. ");
    // window.location.reload();
      console.log("INTERNET  CONNECTED", this.connectedToInternet);

     });
   }

#31

Worked For me Thank You


#32

Hi,Here i have attached github link for Check InterNet connection,You refer this coding but you can add some coding for condition check and push some page or sow msg something…i have attached sample application only.May be its work correctly,please try it.


Please refer this coding and try it.


#33

This is the best I came up with, works for browser and for devices, uses RxJs 6, please be aware of that.
Just inject the server where you need to check, or if you wish to check on app.html inject in the app.component.ts:

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

import {
  Platform
} from 'ionic-angular';

import {
  Observable,
  fromEvent,
  merge,
  of
} from 'rxjs';

import {
  mapTo
} from 'rxjs/operators';

@Injectable()
export class NetworkService {

  private online$: Observable < boolean > = null;

  constructor(private network: Network, private platform: Platform) {
    this.online$ = Observable.create(observer => {
      observer.next(true);
    }).pipe(mapTo(true));
    
    if (this.platform.is('cordova')) {
      // on Device
      this.online$ = merge(
        this.network.onConnect().pipe(mapTo(true)),
        this.network.onDisconnect().pipe(mapTo(false)));
    } else {
      // on Browser
      this.online$ = merge( of (navigator.onLine),
        fromEvent(window, 'online').pipe(mapTo(true)),
        fromEvent(window, 'offline').pipe(mapTo(false))
      );
    }
  }

  public getNetworkType(): string {
    return this.network.type
  }

  public getNetworkStatus(): Observable < boolean > {
    return this.online$;
  }

}

Then on your component you do something like this:

...
public isConnected:boolean = true;
...
constructor(public networkService: NetworkService){
    this.networkService.getNetworkStatus().subscribe((connected: boolean) => {
      this.isConnected = connected;
    });

}

I hope this can help someone.


#34

I have the network plugin working perfect I’m the devapp but nothing fires in a real ipa build. What version of ionic and the plugin are you using? Thanks


#35

This is the perfect solution. As some users mention, network.ondisconnect or onconnect method subscribe is not triggered in chrome browser. this solution takes care of that issue. thanks for the post.


#36

Your observation is perfect. in this thread you can see one more solution, which checks for the platform and then do the connection check. if its browser do the connection check differently.


#37

It did help me. Thanks :slight_smile:


#38

your solution is working only when app running stage network change but not working when app launching without internet connection.Can you help resolve this???


#39

Hi, this technique allows to detect the network change even when the application is running on background ?
I also see that code must to be change with latest rxjs 6.4.0 & angular 7…


#40

Absolutely, once it keeps subscribing all the time the status is updated even the app is in background.


#41

Hi Franz, i’ve code to last rxjs 6.4.0 but i still have an error… this is the code:

import { Injectable } from '@angular/core';
import { Network} from '@ionic-native/network/ngx';
import { Platform } from 'ionic-angular';
import { Observable } from 'rxjs/Observable'
import { merge, mapTo } from 'rxjs/operators'
import { of, fromEvent } from 'rxjs'
  
  @Injectable()
  export class NetworkService {
  
    private online$: Observable < boolean > = null;
  
    constructor(private network: Network, private platform: Platform) {
      this.online$ = Observable.create(observer => {
        observer.next(true);
      }).pipe(mapTo(true));
      
      if (this.platform.is('cordova')) {
        // on Device
        
        this.online$ = merge(
          this.network.onConnect().pipe(mapTo(true)),
          this.network.onDisconnect().pipe(mapTo(false)));
      } else {
        // on Browser
        this.online$ = merge( of (navigator.onLine),
          fromEvent(window, 'online').pipe(mapTo(true)),
          fromEvent(window, 'offline').pipe(mapTo(false))
        );
      }
    }
  
    public getNetworkType(): string {
      return this.network.type
    }
  
    public getNetworkStatus(): Observable < boolean > {
      return this.online$;
    }
  
  }

this is the errors:

can you help me ? :smile: i’m new on rxjs…
thanks


#42

Try importing the Observable from the rxjs directly.

import {
  Observable,
  fromEvent,
  merge,
  of
} from 'rxjs';