Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: DeepLinks not redirect back to App #3255

Closed
SheppardX opened this issue Jul 14, 2020 · 27 comments
Closed

bug: DeepLinks not redirect back to App #3255

SheppardX opened this issue Jul 14, 2020 · 27 comments

Comments

@SheppardX
Copy link

Bug Report

Capacitor Version

💊   Capacitor Doctor  💊 

Latest Dependencies:

  @capacitor/cli: 2.2.1

  @capacitor/core: 2.2.1

  @capacitor/android: 2.2.1

  @capacitor/electron: 2.2.1

  @capacitor/ios: 2.2.1

Installed Dependencies:

  @capacitor/electron not installed


  @capacitor/cli 2.2.0

  @capacitor/core 2.2.0

  @capacitor/ios 2.2.0

  @capacitor/android 2.2.0

[success] Android looking great! 👌
  Found 5 Capacitor plugins for ios:
    cordova-plugin-browsertab (0.2.0)
    cordova-plugin-compat (1.2.0)
    cordova-plugin-deeplinks (1.1.1)
    cordova-plugin-inappbrowser (4.0.0)
    ionic-plugin-deeplinks (1.0.20)
[success] iOS looking great! 👌

Platform(s)

IOS

Current Behavior

We are using cmotion/ionic-keycloak-auth.
Opens Keycloak in BrowserTab for redirecting its Using DeepLinks.
After Login Success it should close the browser and save the token in the storage.
Android works perfect.
In Ios the DeepLink is not fired, **App.addListener('appUrlOpen' ** gets called.

i have setup all URL Scheme`s if i delete them Safari tells me about unknown URL.

Expected Behavior

Browser Close after Successfull login

Code Reproduction

Install cmotion/ionic-keycloak-auth and try to login with IOS

Other Technical Details

npm --version output: 6.14.6

node --version output: v12.11.0

pod --version output (iOS issues only): 1.9.3

Additional Context

I already posted directly in cmotion github but doesnt get an answer
vymalo/ionic-keycloak#8

@thoechtl
Copy link

We have a similar issue on iOS and Android. On iOS we can reproduce it when using stored passwords. Sometimes after auto-filling the inputs the form is automatically submitted, in this case 'appUrlOpen' is not fired for the redirected deep link. When submitting the form manually, everything works.

@SheppardX
Copy link
Author

i wa sable to get it work but i needed to change your code,

i added the appUrlOpen for IOS devices in your service and called the functions and teverything worked fine maybe i could show u the solution and u could adept it or help me to do it correctly

@telpat0298
Copy link

If u still have this issue, i can provide a fully working example using capacitors Browser and (Community)Http Plugins. I haven't tested it yet on iOS but it is working on Android and in theory it should work to on iOS too.

@thoechtl
Copy link

Because deep link event 'appUrlOpen' did not fire in some special cases as described above we now use cordova-plugin-inappbrowser:

With InAppBrowser you can clear the cache on each session, hide the URL bar, customize colors and more. You could even remove deep links completely: InAppBrowser provides the possibility to read the current URL with the 'loadstop' event, where you can process the Keycloak login redirect URL params. Since using InAppBrowser everything works like expected and setup without deep links is much simpler.

@telpat0298
Copy link

telpat0298 commented Sep 21, 2020

But the op did say he's using cordovas inappbrowser and not capacitors browser plugin. Maybe changing browser could affect this issue.

Yes, the setup and implementation with cordovas browser is simpler. For now, i still decided to go with capacitors Browser because the whole framework is newer/under heavy development and capacitor gets promoted by ionic in such way that i just can't imagine that they stop here (at least i hope that).

@thoechtl
Copy link

We had the problems when using Capacitor Browser and deep links configured as described here: https://capacitorjs.com/docs/guides/deep-links

I'd love to switch back to Capacitor Browser when it gets more flexible (hide URL bar, ...) and the issue is fixed. The easiest way to reproduce the issue for us was using stored passwords and let them pre-fill by iOS. Not always but in many cases 'appUrlOpen' did not fire. But the issue also affects Android.

@telpat0298
Copy link

telpat0298 commented Sep 21, 2020

Whats your deeplink configuration? I had http as scheme and on Android the deeplink didn't work when being redirected directly to the redirectUrl because of an already active keycloak session. I changed the scheme to app:// and it started working on redirect too.

@thoechtl
Copy link

We used a universal https:// link. Maybe app:// works, but I can't test in anymore.
https:// is the recommended scheme for "universal links" on iOS and "app links" on Android, so it should work in any case.

@telpat0298
Copy link

Ok, got it. Hopefully they fix this issue sooner or later

@KevinToala
Copy link

Hi.
I have the same problem. But with aws amplify and hosted cognito ui. In android appUrlOpen listener is working with custom url scheme. But in ios dont work and not close capacitor browser when redirect to universal link on ios.
is there any solution that not use cordova in app browser plugin ?

@KevinToala
Copy link

I found a temporary solution.

Do not use Browser.open with IOS and replace it with window.open (They are not good experience since the client exits the app and the browser opens, but it solves the problem),
For android if it works correctly Browser.open and redirection to the app once the deeplink is executed

@ep-mark
Copy link

ep-mark commented Feb 9, 2021

I found I could fix the problem of the appUrlOpen not firing by changing
App.addListener('appUrlOpen', (data: AppUrlOpen) => {
to
Capacitor.Plugins.App.addListener('appUrlOpen', (data: AppUrlOpen) => {

@abrahamtara
Copy link

I had the same problem with appUrlOpen not firing and successfully used the workaround above suggested by @ep-mark
-- however I've just updated to Capacitor 3 and the App.addListener('appUrlOpen', (data: AppUrlOpen) => { syntax is now working for me.

@damngamerz
Copy link

damngamerz commented Apr 27, 2021

This is a valid bug. For me as well in android everything works fine. For iOS same problem:
Once deeplink is clicked the browser doesn't close and goes to the app although the listener gets called. Is there a workaround I can use for now?

@SheppardX
Copy link
Author

SheppardX commented Apr 27, 2021 via email

@santekotturi
Copy link

santekotturi commented Apr 28, 2021

I followed the guide: https://capacitorjs.com/docs/guides/deep-links#ios-configuration

And cannot get deep links working. Here's my app association file:
https://revillager.com/.well-known/apple-app-site-association

Xcode settings:
image

open https://revillager.com/tabs/home and nada. Website loads normally. Nothing in Xcode fires.

Here's my app.component.ts with the recommended and the open event listener:

initializeApp() {
    this.platform.ready().then(() => {
      console.log(
        '[APP] Connected to database: ',
        environment.firebase.projectId
      );
      this.statusBar.styleDefault();
      SplashScreen.hide();
      this.foregroundSvc.init();
      this.analytics.init();

      App.addListener('open', (data: any) => {
        console.log('[DEEP LINK ALT], ', data);
      })
  
      App.addListener('appUrlOpen', (data: any) => {
        this.zone.run(() => {
          console.log('[DEEP LINK] caught: ', data, data.url);
          // Example url: https://revillager.com/tabs/tab2
          // slug = /tabs/tab2
          const slug = data.url.split('.com').pop();
          console.log('[DEEP LINK] slug: ', slug);
          if (slug) {
            this.router.navigateByUrl(slug);
          }
          // If no match, do nothing - let regular routing
          // logic take over
        });
      });
    });
  }

[EDIT] The workaround above worked:

import { Plugins, Capacitor } from '@capacitor/core';

...
    Capacitor.Plugins.App.addListener('appUrlOpen', (data: any) => {
      this.zone.run(() => {
        console.log('[DEEP LINK] caught: ', data, data.url);
        // Example url: https://revillager.com/tabs/tab2
        // slug = /tabs/tab2
        const slug = data.url.split('.com').pop();
        console.log('[DEEP LINK] slug: ', slug);
        if (slug) {
          this.router.navigateByUrl(slug);
        }
        // If no match, do nothing - let regular routing
        // logic take over
      });
    });

why does this work?

@SheppardX
Copy link
Author

SheppardX commented Apr 28, 2021 via email

@SheppardX
Copy link
Author

SheppardX commented Apr 28, 2021 via email

@damngamerz
Copy link

@SheppardX
Im using this for oauth process.
Yes I im getting the data to the listener for ios so my universal link is setup correctly. but the in-app-browser (safari) is not closing automatically/taking me back to the app.
Is it the same for you?

@SheppardX
Copy link
Author

SheppardX commented Apr 29, 2021 via email

@damngamerz
Copy link

damngamerz commented Apr 29, 2021

Okay I see.
Browser of capacitor uses Safari View Controller btw.
https://github.com/ionic-team/capacitor-plugins/blob/main/browser/ios/Plugin/Browser.swift#L9

I just get this opinion that universal links for ios in general has alot of problems. Hmm I would love to solve this and even contribute to the plugin. But atm I have no idea what could be going wrong.

@SheppardX

@theresaknapp
Copy link

Hi @SheppardX,
I have the same issue with ios...
Maybe u could show your modifications to get this work at the cmotion/ionic-keycloak-auth plugin?

i wa sable to get it work but i needed to change your code,

i added the appUrlOpen for IOS devices in your service and called the functions and teverything worked fine maybe i could show u the solution and u could adept it or help me to do it correctly

@SheppardX
Copy link
Author

Hi @SheppardX,
I have the same issue with ios...
Maybe u could show your modifications to get this work at the cmotion/ionic-keycloak-auth plugin?

i wa sable to get it work but i needed to change your code,
i added the appUrlOpen for IOS devices in your service and called the functions and teverything worked fine maybe i could show u the solution and u could adept it or help me to do it correctly

yeah hier is from keycloak sevice

 private async beginLoginAndGetCode(options: KeycloakLoginOptions): Promise<KeycloakLoginResponse> {
    const { redirectUri, ...optionData } = options;
    const path = `${ this.appPrefix }/${ options.redirectUri }`;
    this.authService.setToken(null);
    (optionData as KeycloakLoginOptions).redirectUri = path;
    const url = this.keycloakInstance.createLoginUrl(optionData);

    this.browserTab.isAvailable().then(available => {
      if (available) {
        this.browserTab.openUrl(url);
      } else {
        Browser.open({ url });  <--- Changed to this from Plugins(capacitor), it caused problems on Redmi phones and ios
      }
    });
    
    return new Promise<KeycloakLoginResponse>((resolve, reject) => {
      const sub = this.deepLinkService
        .params()
        .subscribe(code => {
          resolve({ code, redirectUri: path });
          sub.unsubscribe();
        }, error => {
          reject(error);
          sub.unsubscribe();
        });
    });
  }

and in the deeplink service i added

  public init() {
    this.deepLinks
      .route({}).subscribe(
      (match: DeeplinkMatch) => {
        this.extractData(match.$link);
      },
      (nomatch: DeeplinkMatch) => {
        this.extractData(nomatch.$link);
      }
    );
    this.listenToAppUrlOpen(); <-- i added this listener
  }

// this is the reason why it works on ios, the ios 
  public listenToAppUrlOpen() { 
    App.addListener('appUrlOpen', ({ url: fragment }) => {
      const decodeURI = decodeURIComponent(fragment);
      this.zone.run(() => {
        const token = this.authService.getToken();
        const deepLinkingScheme = this.infrastructurConfig?.environment?.deepLinkingScheme || 'SOME SCHEME';
        const extractedRoute = this.deconstructUrl(decodeURI);
        if (!decodeURI.includes(`${ deepLinkingScheme }://app`)) {
          if (token || extractedRoute.path.includes('SOME SPECIAL ROUTE')) {
            ***SOME ROUTING***
          }
        } else {
          this.extractData({ fragment });
        }
      });
    });
  }

@jcesarmobile
Copy link
Member

App plugin is now a separate package.
Going to close since it went off-topic and there is a mix of errors here and I can't reproduce the original one.
If you still face the issue, create a new issue on https://github.com/ionic-team/capacitor-plugins/issues and provide a sample app.

For the "Browser does not close on iOS" issue, that's how iOS works, when a deep link opens your app, it opens it in the current status, so if you had a browser of other window present, it will be there. Capacitor's browser plugin offers a "close" method you can use to close the browser window, other plugins might have similar methods.
Unlike Android where the deep links launch a new intent to your app, which cancels/closes any presented intent such as the browser window.

@timeisgolden
Copy link

I followed the guide: https://capacitorjs.com/docs/guides/deep-links#ios-configuration

And cannot get deep links working. Here's my app association file: https://revillager.com/.well-known/apple-app-site-association

Xcode settings: image

open https://revillager.com/tabs/home and nada. Website loads normally. Nothing in Xcode fires.

Here's my app.component.ts with the recommended and the open event listener:

initializeApp() {
    this.platform.ready().then(() => {
      console.log(
        '[APP] Connected to database: ',
        environment.firebase.projectId
      );
      this.statusBar.styleDefault();
      SplashScreen.hide();
      this.foregroundSvc.init();
      this.analytics.init();

      App.addListener('open', (data: any) => {
        console.log('[DEEP LINK ALT], ', data);
      })
  
      App.addListener('appUrlOpen', (data: any) => {
        this.zone.run(() => {
          console.log('[DEEP LINK] caught: ', data, data.url);
          // Example url: https://revillager.com/tabs/tab2
          // slug = /tabs/tab2
          const slug = data.url.split('.com').pop();
          console.log('[DEEP LINK] slug: ', slug);
          if (slug) {
            this.router.navigateByUrl(slug);
          }
          // If no match, do nothing - let regular routing
          // logic take over
        });
      });
    });
  }

[EDIT] The workaround above worked:

import { Plugins, Capacitor } from '@capacitor/core';

...
    Capacitor.Plugins.App.addListener('appUrlOpen', (data: any) => {
      this.zone.run(() => {
        console.log('[DEEP LINK] caught: ', data, data.url);
        // Example url: https://revillager.com/tabs/tab2
        // slug = /tabs/tab2
        const slug = data.url.split('.com').pop();
        console.log('[DEEP LINK] slug: ', slug);
        if (slug) {
          this.router.navigateByUrl(slug);
        }
        // If no match, do nothing - let regular routing
        // logic take over
      });
    });

why does this work?

Hello
Did you solve this?

@DaSchTour
Copy link

I followed the guide: https://capacitorjs.com/docs/guides/deep-links#ios-configuration
And cannot get deep links working. Here's my app association file: https://revillager.com/.well-known/apple-app-site-association
Xcode settings: image
open https://revillager.com/tabs/home and nada. Website loads normally. Nothing in Xcode fires.
Here's my app.component.ts with the recommended and the open event listener:

initializeApp() {
    this.platform.ready().then(() => {
      console.log(
        '[APP] Connected to database: ',
        environment.firebase.projectId
      );
      this.statusBar.styleDefault();
      SplashScreen.hide();
      this.foregroundSvc.init();
      this.analytics.init();

      App.addListener('open', (data: any) => {
        console.log('[DEEP LINK ALT], ', data);
      })
  
      App.addListener('appUrlOpen', (data: any) => {
        this.zone.run(() => {
          console.log('[DEEP LINK] caught: ', data, data.url);
          // Example url: https://revillager.com/tabs/tab2
          // slug = /tabs/tab2
          const slug = data.url.split('.com').pop();
          console.log('[DEEP LINK] slug: ', slug);
          if (slug) {
            this.router.navigateByUrl(slug);
          }
          // If no match, do nothing - let regular routing
          // logic take over
        });
      });
    });
  }

[EDIT] The workaround above worked:

import { Plugins, Capacitor } from '@capacitor/core';

...
    Capacitor.Plugins.App.addListener('appUrlOpen', (data: any) => {
      this.zone.run(() => {
        console.log('[DEEP LINK] caught: ', data, data.url);
        // Example url: https://revillager.com/tabs/tab2
        // slug = /tabs/tab2
        const slug = data.url.split('.com').pop();
        console.log('[DEEP LINK] slug: ', slug);
        if (slug) {
          this.router.navigateByUrl(slug);
        }
        // If no match, do nothing - let regular routing
        // logic take over
      });
    });

why does this work?

Hello Did you solve this?

I'm also curious, as I have exact the same issue. Although I have https links associated and for example when opening in the notes application I get redirected to the app, but inside the InAppBrowser the website is loaded and no redirect to the app happens.

@ionitron-bot
Copy link

ionitron-bot bot commented Nov 10, 2022

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Capacitor, please create a new issue and ensure the template is fully filled out.

@ionitron-bot ionitron-bot bot locked and limited conversation to collaborators Nov 10, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests