invertase / react-native-firebase

🔥 A well-tested feature-rich modular Firebase implementation for React Native. Supports both iOS & Android platforms for all Firebase services.
https://rnfirebase.io
Other
11.66k stars 2.21k forks source link

[🐛] Dynamic Links: Short Link is not being generated in firebase dynamic links #7834

Closed MdAbubakar closed 3 months ago

MdAbubakar commented 3 months ago

Issue

Describe your issue here

Actually, I'm trying to implement deep linking using the firebase dynamic link as my native app is already using it and the website is handling it perfectly so, first I tried with direct linking approach without using firebase dynamic links as it's going to be deprecated but the website is not redirecting to the app as it's already handling the dynamic links then I decided to go with the firebase dynamic links till it's deprecation and I tried so many things but I'm not able to generate the short link using the firebase dynamic links. And when I create the full link then I'm not getting the complete url which I shared to someone and instead of complete url I'm getting my website domain only and the same thing when I tried with my live app and generated the dynamic link and when I opened that link in my react native app then I'm getting complete url means the issue is with short link and full link and I'm not able to generate the short link I tried with so many versions of react-native-firebase/app and react-native-firebase/dynamic-links but every time I'm getting 400 error, which is:

code : "build-failed" message : "com.google.android.gms.common.api.apiexception: 400: "

I'm getting this every time when I try to generate the short link and when generate the full link then I'm not getting error but I need short url.

Please check my implementation for your reference:


 const shareOptions = async () => {
    try {
      const link = await dynamicLinks().buildShortLink(
        {
          link: shareUrl,
          domainUriPrefix: "https://f66tr.app.goo.gl/apps",
          android: {
            packageName: "com.etvwin.mobile",
          },
        },
        dynamicLinks.ShortLinkType.UNGUESSABLE,
      );

      console.log("link: ", link);
      const shareOptions = {
        title: title,
        failOnCancel: false,
        url: link,
      };

      await Share.open(shareOptions);
    } catch (error) {
      console.error("Error generating short link:", error);
    }
  };

useEffect(() => {
    // Handle incoming Dynamic Links
    const handleDynamicLink = async () => {
      const initialLink = await dynamicLinks().getInitialLink();
      console.log("Initial Dynamic Link:", initialLink);

      const unsubscribe = dynamicLinks().onLink(async link => {
        console.log("Dynamic Link:", link);
        try {
          const url = new URL(link.url);
          const seoUrl = url.searchParams.get("seoUrl");
          // Now you have the seoUrl parameter. Use it to navigate or perform actions.
          console.log("Extracted seoUrl:", seoUrl);
          // Your navigation logic using seoUrl here
        } catch (error) {
          console.error("Error parsing deep link:", error);
        }
      });

      return () => unsubscribe();
    };
    handleDynamicLink();
  }, []);

Project Files

Javascript

Click To Expand

#### `package.json`: ```json { "name": "etvwin.mobile", "version": "0.0.1", "private": true, "scripts": { "otron": "adb reverse tcp:9090 tcp:9090", "node:clean": "rm -rf node_modules&& npm cache clean", "android:bundle": "cd android && ENVFILE=.env ./gradlew bundleRelease", "android:apk": "cd android && ENVFILE=.env ./gradlew assembleRelease", "android:clean": "cd android && ./gradlew clean", "android": "react-native run-android", "bump-version:build": "npx react-native-version --never-amend --skip-tag", "bump-version:patch": "npm version patch", "ios": "react-native run-ios", "ios:clean": "cd ios && rm -rf ~/Library/Caches/CocoaPods && rm -rf Pods && rm -rf ~/Library/Developer/Xcode/DerivedData/* && npm ios:Pod:Reset", "lint": "eslint .", "start": "react-native start", "test": "jest", "postinstall": "patch-package", "postversion": "npx react-native-version --never-amend --skip-tag" }, "dependencies": { "@adrianso/react-native-device-brightness": "^1.2.7", "@config-plugins/react-native-google-cast": "^7.0.0", "@fawazahmed/react-native-read-more": "^3.0.3", "@react-native-async-storage/async-storage": "^1.23.1", "@react-native-clipboard/clipboard": "^1.13.2", "@react-native-community/blur": "^4.4.0", "@react-native-community/cli": "^13.6.3", "@react-native-community/netinfo": "^11.3.1", "@react-native-community/slider": "^4.5.0", "@react-native-firebase/analytics": "^20.1.0", "@react-native-firebase/app": "^20.1.0", "@react-native-firebase/auth": "^20.1.0", "@react-native-firebase/dynamic-links": "^20.1.0", "@react-native-firebase/messaging": "^20.1.0", "@react-native-masked-view/masked-view": "^0.3.1", "@react-navigation/bottom-tabs": "^6.5.20", "@react-navigation/native": "^6.1.17", "@react-navigation/stack": "^6.3.29", "@reduxjs/toolkit": "^2.2.4", "@rneui/base": "^4.0.0-rc.7", "@rneui/themed": "^4.0.0-rc.8", "@twotalltotems/react-native-otp-input": "^1.3.11", "axios": "^1.6.8", "deprecated-react-native-prop-types": "^5.0.0", "lodash": "^4.17.21", "lottie-react-native": "^6.7.0", "metro-minify-terser": "^0.80.7", "query-string": "^9.0.0", "react": "18.2.0", "react-dom": "^18.2.0", "react-native": "0.74.1", "react-native-background-downloader": "^2.3.4", "react-native-base64": "^0.2.1", "react-native-blob-util": "^0.19.8", "react-native-calendars": "^1.1304.1", "react-native-config": "^1.5.1", "react-native-create-thumbnail": "^2.0.0", "react-native-date-picker": "^5.0.0", "react-native-device-info": "^10.13.1", "react-native-elements": "^3.4.3", "react-native-fast-image": "^8.6.3", "react-native-fs": "^2.20.0", "react-native-gesture-handler": "^2.15.0", "react-native-google-cast": "^4.8.0", "react-native-htmlview": "^0.17.0", "react-native-image-size": "^1.1.6", "react-native-linear-gradient": "^2.8.3", "react-native-linear-gradient-text": "^1.2.8", "react-native-modal": "^13.0.1", "react-native-optimized-flatlist": "^1.0.4", "react-native-orientation-locker": "^1.6.0", "react-native-pager-view": "^6.2.3", "react-native-permissions": "^4.1.5", "react-native-pip-android": "^1.0.1", "react-native-progress": "^5.0.1", "react-native-quick-md5": "^3.0.6", "react-native-rate": "^1.2.12", "react-native-razorpay": "^2.3.0", "react-native-reanimated": "^3.11.0", "react-native-reanimated-carousel": "^3.5.1", "react-native-render-html": "^6.3.4", "react-native-safe-area-context": "^4.9.0", "react-native-screens": "^3.29.0", "react-native-share": "^10.1.0", "react-native-size-matters": "^0.4.2", "react-native-skeleton-placeholder": "^5.2.4", "react-native-snap-carousel": "^3.9.1", "react-native-splash-screen": "^3.3.0", "react-native-svg": "^15.1.0", "react-native-swipe-gestures": "^1.0.5", "react-native-swipe-up-down": "^1.2.0", "react-native-tab-view": "^3.5.2", "react-native-vector-icons": "^10.0.3", "react-native-version": "^4.0.0", "react-native-video": "^6.2.0", "react-native-volume-manager": "^1.10.0", "react-native-webview": "^13.8.2", "react-redux": "^9.1.2", "redux-persist": "^6.0.0", "rn-fetch-blob": "^0.12.0" }, "devDependencies": { "@babel/core": "^7.20.0", "@babel/preset-env": "^7.20.0", "@babel/runtime": "^7.20.0", "@react-native/babel-preset": "0.74.83", "@react-native/eslint-config": "0.74.83", "@react-native/metro-config": "0.74.83", "@react-native/typescript-config": "0.74.83", "@types/react": "^18.2.6", "@types/react-test-renderer": "^18.0.0", "babel-jest": "^29.6.3", "eslint": "^8.19.0", "jest": "^29.6.3", "patch-package": "^8.0.0", "prettier": "2.8.8", "react-test-renderer": "18.2.0", "reactotron-react-native": "^5.1.6", "typescript": "5.0.4" }, "engines": { "node": ">=18" } } ``` #### `firebase.json` for react-native-firebase v6: ```json # N/A ```

iOS

Click To Expand

#### `ios/Podfile`: - [ ] I'm not using Pods - [x] I'm using Pods and my Podfile looks like: ```ruby # N/A ``` #### `AppDelegate.m`: ```objc // N/A ```


Android

Click To Expand

#### Have you converted to AndroidX? - [ ] my application is an AndroidX application? - [ ] I am using `android/gradle.settings` `jetifier=true` for Android compatibility? - [ ] I am using the NPM package `jetifier` for react-native compatibility? #### `android/build.gradle`: ```groovy buildscript { ext { buildToolsVersion = "34.0.0" minSdkVersion = 23 compileSdkVersion = 34 targetSdkVersion = 34 ndkVersion = "26.1.10909125" kotlinVersion = "1.9.22" } repositories { google() mavenCentral() maven { url "https://jitpack.io" } } dependencies { classpath("com.android.tools.build:gradle") classpath("com.facebook.react:react-native-gradle-plugin") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") classpath('com.google.gms:google-services:4.4.2') } } apply plugin: "com.facebook.react.rootproject" ``` #### `android/app/build.gradle`: ```groovy apply plugin: "com.android.application" apply plugin: "org.jetbrains.kotlin.android" apply plugin: "com.facebook.react" apply plugin: 'com.google.gms.google-services' apply from: "../../node_modules/react-native-vector-icons/fonts.gradle" react { } def enableProguardInReleaseBuilds = false def jscFlavor = 'org.webkit:android-jsc:+' android { ndkVersion rootProject.ext.ndkVersion buildToolsVersion rootProject.ext.buildToolsVersion compileSdk rootProject.ext.compileSdkVersion namespace "com.etvwin.mobile" defaultConfig { applicationId "com.etvwin.mobile" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode 38 versionName "3.0.0" resValue "string", "build_config_package", "com.etvwin.mobile" } signingConfigs { debug { storeFile file('debug.keystore') storePassword 'android' keyAlias 'androiddebugkey' keyPassword 'android' } release { storeFile file('etvprod.keystore') storePassword 'etvkeystore' keyAlias 'etvkeystore' keyPassword 'etvkeystore' v1SigningEnabled true v2SigningEnabled true } } buildTypes { debug { signingConfig signingConfigs.debug } release { // Caution! In production, you need to generate your own keystore file. // see https://reactnative.dev/docs/signed-apk-android. signingConfig signingConfigs.debug minifyEnabled enableProguardInReleaseBuilds proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" } } } dependencies { // The version of react-native is set by the React Native Gradle Plugin implementation("com.facebook.react:react-android") implementation("com.google.android.gms:play-services-cast-framework:${safeExtGet('castFrameworkVersion', '+')}") if (hermesEnabled.toBoolean()) { implementation("com.facebook.react:hermes-android") } else { implementation jscFlavor } } def safeExtGet(prop, fallback) { rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback } apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle" apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) ``` #### `android/settings.gradle`: ```groovy rootProject.name = 'EtvWin' apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) include ':app' includeBuild('../node_modules/@react-native/gradle-plugin') ``` #### `MainApplication.java`: ```java // N/A ``` #### `AndroidManifest.xml`: ```xml ```


Environment

Click To Expand

**`react-native info` output:** ``` OUTPUT GOES HERE ``` - **Platform that you're experiencing the issue on**: - [ ] iOS - [x] Android - [ ] **iOS** but have not tested behavior on Android - [ ] **Android** but have not tested behavior on iOS - [ ] Both - **`react-native-firebase` version you're using that has this issue:** - `e.g. 5.4.3` - **`Firebase` module(s) you're using that has the issue:** - `e.g. Instance ID` - **Are you using `TypeScript`?** - `Y/N` & `VERSION`


MdAbubakar commented 3 months ago

Sir, please check as I found this in the native code of the library that's why I'm getting 400 error every time:


@ReactMethod
  public void buildShortLink(ReadableMap dynamicLinkMap, String shortLinkType, Promise promise) {
    Tasks.call(
            getExecutor(),
            () -> {
              DynamicLink.Builder builder = createDynamicLinkBuilder(dynamicLinkMap);
              if (SHORT_LINK_TYPE_SHORT.equals(shortLinkType)) {
                return Tasks.await(builder.buildShortDynamicLink(ShortDynamicLink.Suffix.SHORT));
              }

              if (SHORT_LINK_TYPE_UNGUESSABLE.equals(shortLinkType)) {
                return Tasks.await(
                    builder.buildShortDynamicLink(ShortDynamicLink.Suffix.UNGUESSABLE));
              }

              return Tasks.await(builder.buildShortDynamicLink());
            })
        .addOnCompleteListener(
            getExecutor(),
            (task) -> {
              if (task.isSuccessful()) {
                // TODO implement after v6
                // WritableMap shortLinkMap = Arguments.createMap();
                // WritableArray shortLinkWarnings = Arguments.createArray();
                // List<? extends ShortDynamicLink.Warning> warningsList =
                // task.getResult().getWarnings();
                // for (ShortDynamicLink.Warning warning : warningsList) {
                //   shortLinkWarnings.pushString(warning.getMessage());
                // }
                // shortLinkMap.putArray("warnings", shortLinkWarnings);
                // shortLinkMap.putString("link", task.getResult().getShortLink().toString());

                promise.resolve(task.getResult().getShortLink().toString());
              } else {
                Log.e(
                    TAG,
                    "RNFB: Unknown error while building Dynamic Link "
                        + task.getException().getMessage());
                rejectPromiseWithCodeAndMessage(
                    promise, "build-failed", task.getException().getMessage());
              }
            });
  }

Please suggest me something which can fix the issue

mikehardy commented 3 months ago

:wave: - @MdAbubakar you say:

Sir, please check as I found this in the native code of the library that's why I'm getting 400 error every time:

400 is an authorization failure code, so perhaps there is an API disabled in google cloud platform? Have you used adb logcat to see what's happening on the device? Have you tried logging the full stack trace of task.getException() by adding a little e.printStackTrace(System.err); in that java file and rebuilding to see what it says?

I'm happy to note that you do realize dynamic links is deprecated - it will be removed very soon now, and I must encourage you to use anything but dynamic links - if you are stuck on generating short links here you might consider another platform or implementation style immediately, in order to begin moving off dynamic links vs investing further in a system without a future

MdAbubakar commented 3 months ago

@mikehardy Yes, sir I fixed the issue. I removed the firebase dynamic links as it's deprecated for new projects.