ch4mp
ch4mp

Reputation: 12564

Deeplinks with Ionic / Capacitor

I'm trying to retrieve a request param from a deeplink to a Ionic 5 application using Deeplink plugin (authorization code provided by authorization server on successful authorization redirection).

Android intent filter seems correctly configured as the app is opening after successful authentication.

I keep having unmatched deeplinks with plugin_not_installed error.

app.module.ts:

import { HttpClientModule } from '@angular/common/http';
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';
import { Deeplinks } from '@ionic-native/deeplinks/ngx';
import { SQLitePorter } from '@ionic-native/sqlite-porter/ngx';
import { SQLite } from '@ionic-native/sqlite/ngx';
import { Vibration } from '@ionic-native/vibration/ngx';
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { IonicStorageModule } from '@ionic/storage';
import { ApiModule as NumeraApiModule } from '@lexi-clients/numera';
import { OidcUaaModule } from '@lexi/oidc-uaa';
import { AuthModule, OidcConfigService } from 'angular-auth-oidc-client';
import { environment } from '../environments/environment';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { SettingsService } from './settings/settings.service';

export function loadSettings(config: SettingsService) {
  return () => config.load();
}

export function configureAuth(oidcConfigService: OidcConfigService) {
  return () => oidcConfigService.withConfig(environment.authentication.angularAuthOidcClient);
}

@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [
    AuthModule.forRoot(),
    BrowserModule,
    HttpClientModule,
    IonicModule.forRoot(),
    IonicStorageModule.forRoot(),
    NumeraApiModule,
    OidcUaaModule,
    AppRoutingModule,
  ],
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: loadSettings,
      deps: [SettingsService],
      multi: true,
    },
    {
      provide: APP_INITIALIZER,
      useFactory: configureAuth,
      deps: [OidcConfigService],
      multi: true,
    },
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
    Deeplinks,
    OidcConfigService,
    SQLite,
    SQLitePorter,
    Vibration,
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}

app.component.ts:

import { AfterViewInit, Component, NgZone, OnDestroy, OnInit } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { App, Plugins, StatusBarStyle } from '@capacitor/core';
import { AppCenterCrashes } from '@ionic-native/app-center-crashes';
import { Deeplinks } from '@ionic-native/deeplinks/ngx';
import { NavController, Platform } from '@ionic/angular';
import { LexiUser, UaaService } from '@lexi/oidc-uaa';
import { Observable, Subscription } from 'rxjs';
import { SettingsPage } from './settings/settings.page';
import { SettingsService } from './settings/settings.service';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss'],
})
export class AppComponent implements AfterViewInit, OnInit, OnDestroy {

  constructor(
    private platform: Platform,
    private router: Router,
    private idService: UaaService,
    private settings: SettingsService,
    private navController: NavController,
    private deeplinks: Deeplinks,
    private zone: NgZone
  ) {
    this.platform.ready().then(async () => {
      if (this.platform.is('mobile')) {
        const { SplashScreen, StatusBar } = Plugins;
        StatusBar.setStyle({ style: StatusBarStyle.Light });
        SplashScreen.hide();
      }
    });
  }

  ngAfterViewInit() {
    if (this.platform.is('mobile')) {
      this.deeplinks.routeWithNavController(this.navController, { 'login-callback': SettingsPage }).subscribe(
        (match) => {
          console.log('Successfully matched route', match);
  
          // Create our internal Router path by hand
          const internalPath = '/settings';
  
          // Run the navigation in the Angular zone
          this.zone.run(() => {
            this.router.navigateByUrl(internalPath);
          });
        },
        (nomatch) => {
          // nomatch.$link - the full link data
          console.error("Got a deeplink that didn't match", nomatch);
        }
      );
    }
  }
}

Upvotes: 1

Views: 4520

Answers (1)

ch4mp
ch4mp

Reputation: 12564

I got it. My Ionic project is a module in an Angular multi-module project and plugin npm dependencies where added to root package.json.

Moving all Ionic-native related dependencies to package.json in Ionic project folder and running ionic cap sync again solved my problem.

Now the question is How to properly configure a Ionic module in an Angular mono-repo (aka multi-module project)?

Upvotes: 3

Related Questions