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 Report - onAdLoaded Not Triggering on Android #690

Open
1 task done
bitsatom-frontend-expert opened this issue Jan 16, 2025 · 2 comments
Open
1 task done
Labels
help wanted Extra attention is needed

Comments

@bitsatom-frontend-expert

What happened?

Description - The onAdLoaded callback in react-native-google-mobile-ads does not behave consistently on Android. While it triggers with a slight delay on iOS (1-2 seconds or milliseconds), it never gets triggered in certain instances on Android. This inconsistency makes it difficult to manage states like loading indicators reliably.
P.S: We are using Banner Ads and FLUID.

Platform
• Android: onAdLoaded is unreliable and sometimes does not trigger.
• iOS: onAdLoaded works, albeit with a slight delay.

Steps to Reproduce
1. Implement a GAMBannerAd component with the onAdLoaded callback.
2. Use the following configuration for the ad:
- Ad unit ID: /3865/ddm.people.app(any id can be used)
- Sizes: ['FLUID', '300x250', '300x600']
Example :
<GAMBannerAd requestOptions={{ networkExtras: {}, customTargeting: { type: 'app', slot: props.id, sceneIndex:${props.activeIndex}, frameWidth: ${adWidth}, frameHeight: ${adHeight}, }, }} unitId={adUnitId} sizes={sizes} onAdFailedToLoad={() => console.log('Ad failed to load')} onAdLoaded={handleAdLoaded} />
3. Test the ad on both Android and iOS devices.

Platforms

Only on Android

React Native Info

info Fetching system and libraries information...
System:
  OS: macOS 15.2
  CPU: (8) arm64 Apple M1
  Memory: 317.58 MB / 16.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 20.18.1
    path: ~/.nvm/versions/node/v20.18.1/bin/node
  Yarn:
    version: 1.22.22
    path: ~/people-moonshot/node_modules/.bin/yarn
  npm:
    version: 10.8.2
    path: ~/.nvm/versions/node/v20.18.1/bin/npm
  Watchman: Not Found
Managers:
  CocoaPods:
    version: 1.16.2
    path: /opt/homebrew/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 24.2
      - iOS 18.2
      - macOS 15.2
      - tvOS 18.2
      - visionOS 2.2
      - watchOS 11.2
  Android SDK:
    API Levels:
      - "33"
      - "34"
    Build Tools:
      - 34.0.0
      - 35.0.0
    System Images:
      - android-35 | Google APIs ARM 64 v8a
      - android-35 | Google Play ARM 64 v8a
    Android NDK: Not Found
IDEs:
  Android Studio: 2024.2 AI-242.23339.11.2421.12700392
  Xcode:
    version: 16.2/16C5032a
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.13
    path: /opt/homebrew/opt/openjdk@17/bin/javac
  Ruby:
    version: 2.6.10
    path: /usr/bin/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react: Not Found
  react-native: Not Found
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: Not found
  newArchEnabled: Not found
iOS:
  hermesEnabled: Not found
  newArchEnabled: false

info React Native v0.76.6 is now available (your project is running on v0.74.2).
info Changelog: https://github.com/facebook/react-native/releases/tag/v0.76.6
info Diff: https://react-native-community.github.io/upgrade-helper/?from=0.74.2
info For more info, check out "https://reactnative.dev/docs/upgrading?os=macos".

Are your using Typescript?

  • My project is using Typescript

package.json

{
  "name": "moonshot",
  "version": "0.0.1",
  "private": true,
  "lint-staged": {
    "*.{ts,tsx,js,jsx}": [
      "eslint"
    ]
  },
  "rnpm": {
    "assets": [
      "assets/fonts"
    ]
  },
  "scripts": {
    "pod-install": "pod install --project-directory=./ios",
    "android": "react-native run-android --active-arch-only",
    "android:clean": "cd android && ./gradlew clean",
    "android:build": "cd android && ./gradlew assembleRelease",
    "iphone14": "react-native run-ios --simulator=\"iPhone 14\"",
    "iphone15": "react-native run-ios --simulator=\"iPhone 15\"",
    "ios": "react-native run-ios",
    "lint": "eslint --ext .ts ./src",
    "lint-fix": "eslint --fix --ext .ts ./src",
    "start": "react-native start",
    "lint-staged": "lint-staged",
    "metro": "yarn start --reset-cache",
    "patch-package": "patch-package",
    "husky-install": "husky",
    "postinstall": "run-s husky-install patch-package",
    "test": "exit 0",
    "fastlane": "bundle exec fastlane",
    "fastlane:ios": "bundle exec fastlane ios",
    "fastlane:android": "bundle exec fastlane android",
    "fastlane:release": "bundle exec fastlane release",
    "generate-feed-schema": "typescript-json-schema tsconfig.json FeedData --out src/schemas/feedSchema.json --required",
    "web": "webpack serve",
    "web:build": "webpack --mode production"
  },
  "dependencies": {
    "@aws-crypto/sha256-js": "^5.2.0",
    "@babel/preset-react": "^7.25.9",
    "@babel/preset-typescript": "^7.26.0",
    "@gorhom/bottom-sheet": "^5.0.0-alpha.11",
    "@react-native-async-storage/async-storage": "^2.1.0",
    "@react-native-community/blur": "^4.4.0",
    "@react-native-firebase/analytics": "^20.5.0",
    "@react-native-firebase/app": "^20.5.0",
    "@react-native-firebase/app-check": "^20.5.0",
    "@react-native-firebase/crashlytics": "^20.5.0",
    "@react-native-firebase/functions": "^20.5.0",
    "@react-navigation/bottom-tabs": "^7.0.1",
    "@react-navigation/native": "^7.0.0",
    "@react-navigation/stack": "^7.0.18",
    "@reduxjs/toolkit": "^2.2.5",
    "@shopify/flash-list": "^1.7.1",
    "@tradle/react-native-http": "^2.0.1",
    "@types/json-stable-stringify": "^1.0.36",
    "@types/react-native": "^0.73.0",
    "add": "^2.0.6",
    "ajv": "^8.17.1",
    "assert": "^1.5.1",
    "asyncstorage-down": "^4.2.0",
    "axios": "^1.7.7",
    "axios-retry": "^4.5.0",
    "babel-loader": "^9.2.1",
    "babel-plugin-module-resolver": "^5.0.2",
    "browserify-zlib": "^0.1.4",
    "console-browserify": "^1.2.0",
    "constants-browserify": "^1.0.0",
    "dns.js": "^1.0.1",
    "domain-browser": "^1.2.0",
    "events": "^1.1.1",
    "file-loader": "^6.2.0",
    "hls.js": "^1.5.17",
    "html-webpack-plugin": "^5.6.3",
    "https-browserify": "^0.0.1",
    "i18next": "^24.0.2",
    "json-stable-stringify": "^1.1.1",
    "lru-cache": "10",
    "path-browserify": "^0.0.0",
    "process": "^0.11.10",
    "punycode": "^1.4.1",
    "querystring-es3": "^0.2.1",
    "react": "18.2.0",
    "react-dom": "^18.3.1",
    "react-i18next": "^15.1.3",
    "react-icons": "^5.4.0",
    "react-intersection-observer-hook": "^3.0.1",
    "react-native": "0.74.2",
    "react-native-blasted-image": "^1.0.3",
    "react-native-crypto": "^2.2.0",
    "react-native-device-info": "^11.1.0",
    "react-native-fs": "^2.20.0",
    "react-native-gesture-handler": "^2.18.1",
    "react-native-get-random-values": "^1.11.0",
    "react-native-google-mobile-ads": "14.2.0",
    "react-native-haptic-feedback": "^2.3.3",
    "react-native-ios-appattest": "^1.0.0",
    "react-native-level-fs": "^3.0.1",
    "react-native-linear-gradient": "^2.8.3",
    "react-native-localize": "^3.3.0",
    "react-native-mmkv": "^2.12.2",
    "react-native-quick-crypto": "^0.7.3",
    "react-native-randombytes": "^3.6.1",
    "react-native-reanimated": "3.16.3",
    "react-native-safe-area-context": "^4.14.0",
    "react-native-screens": "^3.35.0",
    "react-native-share": "^11.1.0",
    "react-native-splash-screen": "^3.3.0",
    "react-native-toast-message": "^2.2.1",
    "react-native-vector-icons": "^10.2.0",
    "react-native-video": "6.7.0",
    "react-native-volume-manager": "^1.10.0",
    "react-native-web": "^0.19.13",
    "react-native-webview": "^13.12.3",
    "react-redux": "^9.1.2",
    "react-router-dom": "^7.0.1",
    "reactotron-core-client": "^2.9.3",
    "readable-stream": "^1.0.33",
    "redux": "^5.0.1",
    "rn-nodeify": "^10.3.0",
    "stream": "^0.0.3",
    "stream-browserify": "^1.0.0",
    "string_decoder": "^0.10.31",
    "timers-browserify": "^1.4.2",
    "tty-browserify": "^0.0.0",
    "url": "^0.10.3",
    "url-loader": "^4.1.1",
    "util": "^0.12.5",
    "uuidv4": "^6.2.13",
    "vm-browserify": "^0.0.4",
    "webpack": "^5.96.1",
    "webpack-cli": "^5.1.4",
    "webpack-dev-server": "^5.1.0",
    "yarn": "^1.22.22"
  },
  "devDependencies": {
    "@babel/core": "^7.26.0",
    "@babel/preset-env": "^7.26.0",
    "@babel/runtime": "^7.20.0",
    "@react-native/babel-preset": "0.74.84",
    "@react-native/eslint-config": "0.74.84",
    "@react-native/metro-config": "0.74.84",
    "@react-native/typescript-config": "0.74.84",
    "@tsconfig/react-native": "^3.0.5",
    "@types/react": "^19.0.1",
    "@types/react-native-vector-icons": "^6.4.18",
    "@types/react-native-video": "^5.0.20",
    "@types/react-test-renderer": "^18.0.0",
    "@typescript-eslint/eslint-plugin": "^7.16.0",
    "@typescript-eslint/parser": "^7.0.0",
    "@welldone-software/why-did-you-render": "^8.0.3",
    "babel-jest": "^29.6.3",
    "eslint": "^8.57.0",
    "eslint-plugin-import": "^2.31.0",
    "eslint-plugin-react": "^7.34.3",
    "husky": "^9.1.6",
    "jest": "^29.6.3",
    "lint-staged": "^15.2.10",
    "npm-run-all": "^4.1.5",
    "patch-package": "^8.0.0",
    "postinstall-postinstall": "^2.1.0",
    "prettier": "2.8.8",
    "react-test-renderer": "18.2.0",
    "reactotron-react-native": "^5.1.7",
    "reactotron-redux": "^3.1.9",
    "typescript": "5.0.4",
    "typescript-json-schema": "^0.65.1"
  },
  "engines": {
    "node": ">=18"
  },
  "react-native": {
    "zlib": "browserify-zlib",
    "console": "console-browserify",
    "constants": "constants-browserify",
    "crypto": "react-native-crypto",
    "dns": "dns.js",
    "domain": "domain-browser",
    "http": "@tradle/react-native-http",
    "https": "https-browserify",
    "path": "path-browserify",
    "querystring": "querystring-es3",
    "fs": "react-native-level-fs",
    "_stream_transform": "readable-stream/transform",
    "_stream_readable": "readable-stream/readable",
    "_stream_writable": "readable-stream/writable",
    "_stream_duplex": "readable-stream/duplex",
    "_stream_passthrough": "readable-stream/passthrough",
    "stream": "stream-browserify",
    "timers": "timers-browserify",
    "tty": "tty-browserify",
    "vm": "vm-browserify",
    "tls": false
  },
  "browser": {
    "zlib": "browserify-zlib",
    "console": "console-browserify",
    "constants": "constants-browserify",
    "crypto": "react-native-crypto",
    "dns": "dns.js",
    "domain": "domain-browser",
    "http": "@tradle/react-native-http",
    "https": "https-browserify",
    "path": "path-browserify",
    "querystring": "querystring-es3",
    "fs": "react-native-level-fs",
    "_stream_transform": "readable-stream/transform",
    "_stream_readable": "readable-stream/readable",
    "_stream_writable": "readable-stream/writable",
    "_stream_duplex": "readable-stream/duplex",
    "_stream_passthrough": "readable-stream/passthrough",
    "stream": "stream-browserify",
    "timers": "timers-browserify",
    "tty": "tty-browserify",
    "vm": "vm-browserify",
    "tls": false
  },
  "packageManager": "[email protected]+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}

app.json

{
  "name": "moonshot",
  "displayName": "Moonshot",
  "icon": "./src/assets/icon.png",
  "react-native-google-mobile-ads": {
    "android_app_id": "ca-app-pub-6983307289689206~5151727358",
    "ios_app_id": "ca-app-pub-6983307289689206~2589143196"
  }
}

ios/Podfile

require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

# Resolve react_native_pods.rb with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
  'require.resolve(
    "react-native/scripts/react_native_pods.rb",
    {paths: [process.argv[1]]},
  )', __dir__]).strip

platform :ios, '16.0'
prepare_react_native_project!

linkage = ENV['USE_FRAMEWORKS']
if linkage != nil
  Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
  use_frameworks! :linkage => linkage.to_sym
end

target 'moonshot' do
  config = use_native_modules!

  pod 'Firebase', :modular_headers => true
  pod 'FirebaseCore', :modular_headers => true
  pod 'GoogleUtilities', :modular_headers => true
  pod 'FirebaseAppCheck', :modular_headers => true
  pod 'RNFS', :path => '../node_modules/react-native-fs'
  use_frameworks! :linkage => :static
  $RNFirebaseAsStaticFramework = true

  use_react_native!(
    :path => config[:reactNativePath],
    # An absolute path to your application root.
    :app_path => "#{Pod::Config.instance.installation_root}/.."
  )

  target 'moonshotTests' do
    inherit! :complete
    # Pods for testing
  end

  post_install do |installer|
    # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
    react_native_post_install(
      installer,
      config[:reactNativePath],
      :mac_catalyst_enabled => false,
      # :ccache_enabled => true
    )
  end
end

android/build.gradle

buildscript {
    ext {
        buildToolsVersion = "34.0.0"
        minSdkVersion = 23
        compileSdkVersion = 34
        targetSdkVersion = 34
        ndkVersion = "26.1.10909125"
        kotlinVersion = "1.9.22"
    }
    repositories {
        google()
        mavenCentral()
    }
    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")
        classpath 'com.google.firebase:firebase-crashlytics-gradle:3.0.2'
    }
}

apply plugin: "com.facebook.react.rootproject"

allprojects {
    repositories {
        google()
        mavenCentral()
    }
}

android/app/build.gradle

apply plugin: "com.android.application"
apply plugin: "org.jetbrains.kotlin.android"
apply plugin: "com.facebook.react"
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'

apply from: file("../../node_modules/react-native-vector-icons/fonts.gradle")

/**
 * This is the configuration block to customize your React Native Android app.
 * By default you don't need to apply any configuration, just uncomment the lines you need.
 */
react {
    /* Folders */
    //   The root of your project, i.e. where "package.json" lives. Default is '..'
    // root = file("../")
    //   The folder where the react-native NPM package is. Default is ../node_modules/react-native
    // reactNativeDir = file("../node_modules/react-native")
    //   The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen
    // codegenDir = file("../node_modules/@react-native/codegen")
    //   The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js
    // cliFile = file("../node_modules/react-native/cli.js")

    /* Variants */
    //   The list of variants to that are debuggable. For those we're going to
    //   skip the bundling of the JS bundle and the assets. By default is just 'debug'.
    //   If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants.
    // debuggableVariants = ["liteDebug", "prodDebug"]

    /* Bundling */
    //   A list containing the node command and its flags. Default is just 'node'.
    // nodeExecutableAndArgs = ["node"]
    //
    //   The command to run when bundling. By default is 'bundle'
    // bundleCommand = "ram-bundle"
    //
    //   The path to the CLI configuration file. Default is empty.
    // bundleConfig = file(../rn-cli.config.js)
    //
    //   The name of the generated asset file containing your JS bundle
    // bundleAssetName = "MyApplication.android.bundle"
    //
    //   The entry file for bundle generation. Default is 'index.android.js' or 'index.js'
    // entryFile = file("../js/MyApplication.android.js")
    //
    //   A list of extra flags to pass to the 'bundle' commands.
    //   See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle
    // extraPackagerArgs = []

    /* Hermes Commands */
    //   The hermes compiler command to run. By default it is 'hermesc'
    // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc"
    //
    //   The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
    // hermesFlags = ["-O", "-output-source-map"]
}

/**
 * The preferred build flavor of JavaScriptCore (JSC)
 *
 * For example, to use the international variant, you can use:
 * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
 *
 * The international variant includes ICU i18n library and necessary data
 * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
 * give correct results when using with locales other than en-US. Note that
 * this variant is about 6MiB larger per architecture than default.
 */
def jscFlavor = 'org.webkit:android-jsc:+'

android {
    ndkVersion rootProject.ext.ndkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion
    compileSdk rootProject.ext.compileSdkVersion

    namespace "com.moonshot"
    defaultConfig {
        applicationId "com.moonshot"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 11
        versionName "0.1.0"
        multiDexEnabled true
    }
    signingConfigs {
        debug {
            storeFile file('debug.keystore')
            storePassword 'android'
            keyAlias 'androiddebugkey'
            keyPassword 'android'
        }

        release {
            storeFile file(peopleMoonshotStoreFile)
            storePassword peopleMoonshotStorePassword
            keyAlias peopleMoonshotKeyAlias
            keyPassword peopleMoonshotKeyPwd
        }
    }
    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.release
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"

            firebaseCrashlytics {
                nativeSymbolUploadEnabled true
                unstrippedNativeLibsDir 'build/intermediates/merged_native_libs/release/out/lib'
            }
        }
    }
}

dependencies {
    // The version of react-native is set by the React Native Gradle Plugin
    implementation("com.facebook.react:react-android")
    implementation ('com.facebook.fresco:animated-gif:3.1.3')
    implementation(platform("com.google.firebase:firebase-bom:33.3.0"))
    implementation("com.google.firebase:firebase-analytics")
    implementation("com.google.firebase:firebase-appcheck-playintegrity")
    implementation("com.google.firebase:firebase-appcheck-debug")
    implementation("com.google.firebase:firebase-appcheck")
    implementation 'com.facebook.fresco:animated-gif:3.2.0'
    implementation project(':react-native-share')

    if (hermesEnabled.toBoolean()) {
        implementation("com.facebook.react:hermes-android")
    } else {
        implementation jscFlavor
    }
}

apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)

android/settings.gradle

rootProject.name = 'moonshot'
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')
include ':react-native-share'
project(':react-native-share').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-share/android')

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
  <uses-permission android:name="android.permission.INTERNET"/>
  <!-- required for react-native-share base64 sharing -->
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.VIBRATE"/>
  <application
    android:name=".MainApplication"
    android:label="@string/app_name"
    android:icon="@mipmap/ic_launcher"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:allowBackup="false"
    android:theme="@style/AppTheme">
    <activity
      android:name=".MainActivity"
      android:label="@string/app_name"
      android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
      android:launchMode="singleTask"
      android:screenOrientation="portrait"
      android:windowSoftInputMode="adjustResize"
      android:exported="true">
      <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
      </intent-filter>
      <intent-filter>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <data android:scheme="peopleapp"/>
      </intent-filter>
    </activity>
  </application>
</manifest>
@bitsatom-frontend-expert bitsatom-frontend-expert added the help wanted Extra attention is needed label Jan 16, 2025
@mikehardy
Copy link
Collaborator

I believe I've seen this myself, however I haven't been able to pin it down either
I fear there may be some subtle native issue here which means this:

"react-native": "0.74.2",

...is somewhat problematic. I wouldn't want to go anywhere near troubleshooting this personally without knowing I was on the most up to date code everywhere. Otherwise I risk wasting time on an already fixed EventEmitter bug or similar, and that code does change semi-frequently, especially with all the new architecture work going on

Does this reproduce for you in the example app in this repo, with the most current react-native ?

@bitsatom-frontend-expert
Copy link
Author

Thanks @mikehardy for the quick response. I have one more question I need assistance with, What if I want to open a GAMBannerAd redirect URL(to which ad click will redirect to), to happen within the app(maybe in a web-view), Does GAMBanner Ad returns the redirect url to us in any callback?

Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants