invertase / react-native-google-mobile-ads

React Native Google Mobile Ads enables you to monetize your app with AdMob.
https://docs.page/invertase/react-native-google-mobile-ads
Other
674 stars 135 forks source link

🔥 test ads can no-fill on test devices, needs info in common no-fill causes doc #97

Closed evelant closed 1 year ago

evelant commented 2 years ago

Issue

After upgrading from "@invertase/react-native-google-ads": "^4.0.2", to "react-native-google-mobile-ads": "^5.0.0", test ads no longer work on Android. Attempting to play a test ad results in error 3 no-fill which AFAICT shouldn't be possible. Test ads work fine on iOS using the same code.


Project Files

Javascript

Click To Expand

#### `package.json`: ```json "react-native-google-mobile-ads": "^5.0.0", "react-native": "^0.67.3", ``` #### `admob.json`: ```json { "name": "MyApp", "displayName": "MyApp", "react-native-google-mobile-ads": { "android_app_id": "my_android_app_id_here", "ios_app_id": "my_ios_app_id_here", "delay_app_measurement_init": true, "user_tracking_usage_description": "This identifier will be used to deliver personalized ads to you. Viewing ads is entirely optional in this app." } } ```

iOS

Click To Expand

#### `ios/Podfile`: ```ruby # N/A ``` ---

Android

Click To Expand

#### `android/build.gradle`: ```groovy buildscript { ext { buildToolsVersion = "30.0.2" minSdkVersion = 21 compileSdkVersion = 31 targetSdkVersion = 31 ndkVersion = "21.4.7075529" } repositories { google() mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:4.2.2' //RNFirebase v6 setup https://rnfirebase.io/ classpath 'com.google.gms:google-services:4.3.10' classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1' //RNFirebase v6 perf https://rnfirebase.io/perf/usage classpath 'com.google.firebase:perf-plugin:1.4.1' //Auto-upload debug symbols to bugsnag https://docs.bugsnag.com/build-integrations/gradle/ classpath "com.bugsnag:bugsnag-android-gradle-plugin:5.+" } } allprojects { repositories { mavenLocal() maven { url("$rootDir/../node_modules/react-native/android") } maven { url("$rootDir/../node_modules/jsc-android/dist") } mavenCentral { content { excludeGroup "com.facebook.react" } } google() maven { url 'https://www.jitpack.io' } maven { url "$rootDir/../node_modules/@notifee/react-native/android/libs" } } ``` #### `android/app/build.gradle`: ```groovy apply plugin: "com.android.application" apply plugin: 'com.google.gms.google-services' // a auto-upload for native symbols https://docs.bugsnag.com/build-integrations/gradle/ apply plugin: "com.bugsnag.android.gradle" apply plugin: 'com.google.firebase.crashlytics' apply plugin: 'com.google.firebase.firebase-perf' import com.android.build.OutputFile project.ext.react = [ hermesFlagsRelease: ["-w", "-O", "-output-source-map"], hermesFlagsDebug: ["-w", "-O", "-output-source-map"], //entryFile: "index.js", //extraPackagerArgs: [ '--minify=false' ], //bundleAssetName: "index.android.bundle", //bundleInAlpha: true, //bundleInBeta: true, //bundleInDebug: true, //bundleInRelease: true, enableHermes: true, bundleInDebug: true, //jsBundleDirDebug: "$buildDir/intermediates/merged_assets/debug/mergeDebugAssets/out", //jsBundleDirRelease: "$buildDir/intermediates/merged_assets/release/mergeReleaseAssets/out", //devDisabledInRelease: true, //jsBundleDirDebug: "$buildDir/generated/assets/react/debug", //jsBundleDirRelease: "$buildDir/generated/assets/react/release", ] apply from: "../../node_modules/react-native/react.gradle" apply from: "../../node_modules/react-native-code-push/android/codepush.gradle" apply from: "../../node_modules/@bugsnag/react-native/bugsnag-react-native.gradle" /** * Set this to true to create two separate APKs instead of one: * - An APK that only works on ARM devices * - An APK that only works on x86 devices * The advantage is the size of the APK is reduced by about 4MB. * Upload all the APKs to the Play Store and people will download * the correct one based on the CPU architecture of their device. */ def enableSeparateBuildPerCPUArchitecture = true /** * Run Proguard to shrink the Java bytecode in release builds. */ def enableProguardInReleaseBuilds = true /** * The preferred build flavor of JavaScriptCore. * * 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:+' /** * Whether to enable the Hermes VM. * * This should be set on project.ext.react and mirrored here. If it is not set * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode * and the benefits of using Hermes will therefore be sharply reduced. */ def enableHermes = project.ext.react.get("enableHermes", false); def versionJson = file('../../../Shared/src/version_codes.json') def parsedJson = new groovy.json.JsonSlurper().parseText(versionJson.text) def appVersionCode = parsedJson.androidVersionCode def appVersionName = parsedJson.androidVersionName /** * Architectures to build native code for in debug. */ def nativeArchitectures = project.getProperties().get("reactNativeDebugArchitectures") android { ndkVersion rootProject.ext.ndkVersion compileSdkVersion rootProject.ext.compileSdkVersion defaultConfig { applicationId "com.my.app" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode appVersionCode versionName appVersionName multiDexEnabled true //generate debug symbols for crash reporting on play store https://developer.android.com/studio/build/shrink-code#native-crash-support //requires android gradle >= 4.1 which breaks other stuff for now buildTypes.release.ndk.debugSymbolLevel = "FULL" resValue 'string', "CODE_PUSH_APK_BUILD_TIME", String.format("\"%d\"", System.currentTimeMillis()) } splits { abi { reset() enable enableSeparateBuildPerCPUArchitecture universalApk false // If true, also generate a universal APK include "armeabi-v7a", "x86", "arm64-v8a", "x86_64" } } signingConfigs { release { if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) { storeFile file(MYAPP_RELEASE_STORE_FILE) storePassword MYAPP_RELEASE_STORE_PASSWORD keyAlias MYAPP_RELEASE_KEY_ALIAS keyPassword MYAPP_RELEASE_KEY_PASSWORD } } } buildTypes { debug { buildConfigField "String", "CODEPUSH_KEY", '""' packagingOptions { doNotStrip '**/*.so' } if (nativeArchitectures) { ndk { abiFilters nativeArchitectures.split(',') } } } releaseStaging { buildConfigField "String", "CODEPUSH_KEY", '"my_key"' applicationIdSuffix "staging" signingConfig signingConfigs.releaseStaging packagingOptions { doNotStrip '**/*.so' } // Note: It is a good idea to provide matchingFallbacks for the new buildType you create to prevent build issues // Add the following line if not already there matchingFallbacks = ['release'] proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" shrinkResources enableProguardInReleaseBuilds minifyEnabled enableProguardInReleaseBuilds } release { buildConfigField "String", "CODEPUSH_KEY", '"my_key"' shrinkResources enableProguardInReleaseBuilds minifyEnabled enableProguardInReleaseBuilds proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" signingConfig signingConfigs.release packagingOptions { doNotStrip '**/*.so' } //Capture native crashes with rnfirebase crashlytics v6 //https://rnfirebase.io/crashlytics/usage firebaseCrashlytics { nativeSymbolUploadEnabled true strippedNativeLibsDir 'build/intermediates/stripped_native_libs/release/out/lib' unstrippedNativeLibsDir 'build/intermediates/merged_native_libs/release/out/lib' } } } //release linter crashes for no reason https://stackoverflow.com/questions/49286268/error-execution-failed-for-task-app-lintvitalrelease-any-one-can-solve-it lintOptions { checkReleaseBuilds false abortOnError false } //Fix OOM exception on build https://stackoverflow.com/questions/33075646/getting-out-of-memory-issue-after-updating-buildtoolsversion-23-0-1-in-android dexOptions { javaMaxHeapSize "4g" } packagingOptions { doNotStrip '**/*.so' } // Remove Flipper for release build sourceSets { release { main { java { exclude '**/ReactNativeFlipper.java' } } } releaseStaging { main { java { exclude '**/ReactNativeFlipper.java' } } } } } dependencies { implementation fileTree(dir: "libs", include: ["*.jar"]) //noinspection GradleDynamicVersion implementation "com.facebook.react:react-native:+" // From node_modules implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0' debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") { exclude group:'com.facebook.fbjni' } debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { exclude group:'com.facebook.flipper' exclude group:'com.squareup.okhttp3', module:'okhttp' } debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") { exclude group:'com.facebook.flipper' } implementation project(':react-native-vector-icons') if (enableHermes) { def hermesPath = "../../node_modules/hermes-engine/android/"; debugImplementation files(hermesPath + "hermes-debug.aar") releaseImplementation files(hermesPath + "hermes-release.aar") releaseStagingImplementation files(hermesPath + "hermes-release.aar") } else { implementation jscFlavor } //clevertap deps implementation 'com.clevertap.android:clevertap-android-sdk:4.3.1' implementation 'com.android.installreferrer:installreferrer:2.2' implementation 'com.android.support:multidex:2.0.1' // For animated GIF support // implementation 'com.facebook.fresco:animated-gif:2.5.0' // For WebP support, including animated WebP implementation 'com.facebook.fresco:animated-webp:2.5.0' implementation 'com.facebook.fresco:webpsupport:2.5.0' } def nativeLibPaths = [ new File("app/build/intermediates/merged_native_libs/release/out"), new File("app/build/intermediates/native_debug_metadata/release/out"), ] bugsnag { // Disable bugsnag native support on dev builds // https://docs.bugsnag.com/build-integrations/gradle/ variantFilter { variant -> // disables plugin for all variants of the 'staging' productFlavor def name = variant.name.toLowerCase() if (name.contains("staging") || name.contains("debug")) { enabled = false } } sourceControl { repository = "https://github.com/evelant/MyApp" } //Attempt to give bugsnag NDK (native C level library) symbols //https://docs.bugsnag.com/build-integrations/gradle/#additional-configuration sharedObjectPaths = nativeLibPaths } //Print the version name task printVersionName { doLast { println android.defaultConfig.versionName } } task printVersionCode { doLast { println android.defaultConfig.versionCode } } // Run this once to be able to run the application with BUCK // puts all compile dependencies into folder libs for BUCK to use task copyDownloadableDepsToLibs(type: Copy) { from configurations.implementation into 'libs' } //import fonts for react native vector icons apply from: "../../node_modules/react-native-vector-icons/fonts.gradle" apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) ``` #### `android/settings.gradle`: ```groovy rootProject.name = 'MyApp' include ':react-native-vector-icons' project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android') apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) include ':app', ':react-native-code-push' project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app') ``` #### `AndroidManifest.xml`: ```xml ```


Environment

Click To Expand

**`react-native info` output:** ``` System: OS: macOS 12.2.1 CPU: (8) arm64 Apple M1 Memory: 104.47 MB / 16.00 GB Shell: 3.3.1 - /opt/homebrew/bin/fish Binaries: Node: 16.13.0 - /private/var/folders/gx/fwg565ys3177ht4tnx40wqv80000gn/T/xfs-916223e2/node Yarn: 3.1.1 - /private/var/folders/gx/fwg565ys3177ht4tnx40wqv80000gn/T/xfs-916223e2/yarn npm: 8.1.0 - /opt/homebrew/Cellar/node@16/16.13.0/bin/npm Watchman: 2021.11.15.00 - /opt/homebrew/bin/watchman Managers: CocoaPods: 1.11.2 - /opt/homebrew/bin/pod SDKs: iOS SDK: Platforms: DriverKit 21.4, iOS 15.4, macOS 12.3, tvOS 15.4, watchOS 8.5 Android SDK: Not Found IDEs: Android Studio: Bumblebee 2021.1.1 Patch 2 Bumblebee 2021.1.1 Patch 2 Xcode: 13.3/13E113 - /usr/bin/xcodebuild Languages: Java: 15.0.5 - /usr/bin/javac npmPackages: @react-native-community/cli: Not Found react: 17.0.2 => 17.0.2 react-native: ^0.67.3 => 0.67.3 react-native-macos: Not Found npmGlobalPackages: *react-native*: Not Found ``` - **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 - **Are you using `TypeScript`?** - `Y/N` & `VERSION` Y - 4.6.2


mikehardy commented 2 years ago

Quite strange! I can recall that I did check the example app here and I did get no-fills on ios but not on android. Have you tried the example and clicked in to the various ad types to see if they display?

There might be something about even the test ids that is throttled on IP or device or...unknown

Second thought: it could have something to do with all the consent library work, that was the main effort of v4 -> v5 and maybe that could result in a no-fill? That's an almost more vague thought than the first one though, and I wish I had something more concrete.

Either way, curious to hear your luck with the example on android emulator + android simulator + real android + real ios if at all possible

evelant commented 2 years ago

Hmm running the example app on the same device the test ad works. I don't know if you're already aware of this but you can't play the rewarded ad twice in the example, trying to play it a second time throws an error "The requested RewardedAd has not loaded and could not be shown".

Looking at logcat I see that it is correctly registered as a test device but neither the test ad unit or my real ad unit shows a test ad.

2022-03-16 20:28:15.270 26264-26264/com.my.app I/Ads: This request is sent from a test device.
2022-03-16 20:28:15.475 8771-11729/? I/Ads: SDK version: afma-sdk-a-v214106999.213806000.1
2022-03-16 20:28:15.476 8771-11729/? I/Ads: HTTP timeout: 60000 milliseconds.
2022-03-16 20:28:15.657 26264-26264/com.my.app I/Ads: Ad failed to load : 3

I guess I need to do some more digging and carefully compare my app to the example!

evelant commented 2 years ago

🤦 Turns out if your device is registered as test device then the test ad unit will not work and admob will unhelpfully return no-fill if you try to use it. Also turns out I thought I had tested with my real ad unit but had missed a conditional if(__DEV__) that was forcing it to always use the test ad unit, causing it to fail. Test ads work fine if I use my real ad unit id. Sorry for wasting your time with this one!

mikehardy commented 2 years ago

Actually, I think you've discovered a couple things - the module is from some old code with a pedigree but the example app and documentation can always use a polish.

I saw:

I don't know if you're already aware of this but you can't play the rewarded ad twice in the example, trying to play it a second time throws an error "The requested RewardedAd has not loaded and could not be shown".

So really the example app should handle that better - either document one-and-done or load multiple

Turns out if your device is registered as test device then the test ad unit will not work and admob will unhelpfully return no-fill if you try to use it.

This seems like something the module can help out on. At minimum, if it's not documented as a possible reason for no-fill, it could be, at maximum, we could potentially see if the device is registered as a test device, and do something helpful (from a console.log to a console.warn to maybe comparing known test ad unit ids and if you are a test device and load test ad id, throw an error perhaps ?

Currently this is not even documented, and a PR to the docs would be really helpful if you could hit the edit button here https://github.com/invertase/react-native-google-mobile-ads/blob/main/docs/common-reasons-for-ads-not-showing.mdx and add your experience

github-actions[bot] commented 1 year ago

Hello 👋, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.