App crashes with java.lang.IllegalAccessError, caused by admob

Ionic v3 app with Admob Free plugin used to work just fine on both iOS and Android, showing ads as expected. Suddenly, when testing the app on an Android phone, the app crashes with the following errors

name.ratson.cordova.admob.AdMob.buildAdRequest

java.lang.IllegalAccessError: com.google.android.gms.ads.internal.client.zze

It appears to crash within

admobFree.banner.prepare().then(()=>{…})

I even removed and reinstalled the Android platform, and removed/added admob-free plugin, but no luck.
I’ve been Googling all night but no luck. The app also uses FCM for messaging.

Any help is appreciated! Thanks.

Can you show the code??

Thanks for the prompt response. Here’s the code

  try {
      console.log("Setting the config. bannerid:", admobId); // This line shows. The admobId is set before
      this.platform.ready().then(()=>{
        const bannerConfig: AdMobFreeBannerConfig = {
          id:admobId,
          isTesting: true,
          autoShow: true
      };
    this.admobFree.banner.config(bannerConfig);
    console.log("Calling prepare with admobId " + admobId); // this line shows with the right ID
    this.admobFree.banner.prepare()
      .then(() => {
          /* The crash happens somewhere here!*/
          console.log("showing admob banner ads free");// this line never shows
      }).catch((e) => console.log("Error preparing banner: ",e)); // doesn't show
    }).catch(err => console.log("Error showAdmobBannerAds: ", JSON.stringify(err))); // doesn't show
    } catch (error) {
      console.log("Error showAdmobBannerAds: ", JSON.stringify(error));
    }

None of the “catch” error logs show. I use HockeyApp to track crashes and it reported the errors.

Have you tried cleaning the project??

How do I clean it? I’ve already removed and readded the Android platform.
Is there a command to clean it?

yupp…

ionic cordova clean android

or

cordova clean

Thanks. Tried it but still crashes.

Here’s the full error log reported by HockeyApp…

java.lang.IllegalAccessError: com.google.android.gms.ads.internal.client.zze
	at com.google.android.gms.ads.internal.client.zzm.<init>(Unknown Source)
	at com.google.android.gms.ads.internal.client.zzm.<clinit>(Unknown Source)
	at com.google.android.gms.ads.internal.client.zzm.zzdQ(Unknown Source)
	at com.google.android.gms.ads.internal.client.zzad.<clinit>(Unknown Source)
	at com.google.android.gms.ads.AdRequest.<clinit>(Unknown Source)
	at com.google.android.gms.ads.AdRequest$Builder.<init>(Unknown Source)
	at name.ratson.cordova.admob.AdMob.buildAdRequest(AdMob.java:152)
	at name.ratson.cordova.admob.banner.BannerExecutor$1.run(BannerExecutor.java:80)
	at android.os.Handler.handleCallback(Handler.java:739)
	at android.os.Handler.dispatchMessage(Handler.java:95)
	at android.os.Looper.loop(Looper.java:135)
	at android.app.ActivityThread.main(ActivityThread.java:5286)
	at java.lang.reflect.Method.invoke(Native Method)
	at java.lang.reflect.Method.invoke(Method.java:372)
	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1384)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1179)

Did you try it in test mode?? I mean the docs code??

Do you mean if AdMob is in test mode? Yes.
If not, can you explain how to do test mode?

I mean the way it is given on the official docs the few lines of code… Does those give the same error when you run them.

Yes I’ve followed the example in the docs here https://ionicframework.com/docs/native/admob-free/ . That’s what the above code is based off of. It’s weird that the crash isn’t shown on the debug console, but is a Java error that shows after a crash.

It’s worked perfectly the past few months, but after building it via XCode and submitting to Apple, the Android version is crashing like this, and I don’t know why. Now I’m getting this error…

java.lang.NoClassDefFoundError: com.google.android.gms.ads.internal.client.zze

Could you please post your

build.gradle app
&
build.gradle project

build.gradle

/*
       Licensed to the Apache Software Foundation (ASF) under one
       or more contributor license agreements.  See the NOTICE file
       distributed with this work for additional information
       regarding copyright ownership.  The ASF licenses this file
       to you under the Apache License, Version 2.0 (the
       "License"); you may not use this file except in compliance
       with the License.  You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

       Unless required by applicable law or agreed to in writing,
       software distributed under the License is distributed on an
       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
       KIND, either express or implied.  See the License for the
       specific language governing permissions and limitations
       under the License.
*/

apply plugin: 'com.android.application'

buildscript {
    repositories {
        jcenter()
        maven {
            url "https://maven.google.com"
        }
    }

    // Switch the Android Gradle plugin version requirement depending on the
    // installed version of Gradle. This dependency is documented at
    // http://tools.android.com/tech-docs/new-build-system/version-compatibility
    // and https://issues.apache.org/jira/browse/CB-8143
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.3'
    }
}

// Allow plugins to declare Maven dependencies via build-extras.gradle.
allprojects {
    repositories {
        jcenter()
        maven {
            url "https://maven.google.com"
        }
    }
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.14.1'
}

// Configuration properties. Set these via environment variables, build-extras.gradle, or gradle.properties.
// Refer to: http://www.gradle.org/docs/current/userguide/tutorial_this_and_that.html
ext {
    apply from: 'CordovaLib/cordova.gradle'
    // The value for android.compileSdkVersion.
    if (!project.hasProperty('cdvCompileSdkVersion')) {
        cdvCompileSdkVersion = null;
    }
    // The value for android.buildToolsVersion.
    if (!project.hasProperty('cdvBuildToolsVersion')) {
        cdvBuildToolsVersion = null;
    }
    // Sets the versionCode to the given value.
    if (!project.hasProperty('cdvVersionCode')) {
        cdvVersionCode = null
    }
    // Sets the minSdkVersion to the given value.
    if (!project.hasProperty('cdvMinSdkVersion')) {
        cdvMinSdkVersion = null
    }
    // Whether to build architecture-specific APKs.
    if (!project.hasProperty('cdvBuildMultipleApks')) {
        cdvBuildMultipleApks = null
    }
    // .properties files to use for release signing.
    if (!project.hasProperty('cdvReleaseSigningPropertiesFile')) {
        cdvReleaseSigningPropertiesFile = null
    }
    // .properties files to use for debug signing.
    if (!project.hasProperty('cdvDebugSigningPropertiesFile')) {
        cdvDebugSigningPropertiesFile = null
    }
    // Set by build.js script.
    if (!project.hasProperty('cdvBuildArch')) {
        cdvBuildArch = null
    }

    // Plugin gradle extensions can append to this to have code run at the end.
    cdvPluginPostBuildExtras = []
}

// PLUGIN GRADLE EXTENSIONS START
apply from: "card.io.cordova.mobilesdk/servicefinder-build.gradle"
apply from: "com.paypal.cordova.mobilesdk/servicefinder-build.gradle"
apply from: "cordova-plugin-fcm/servicefinder-FCMPlugin.gradle"
apply from: "cordova-plugin-hockeyapp/servicefinder-build.gradle"
// PLUGIN GRADLE EXTENSIONS END

def hasBuildExtras = file('build-extras.gradle').exists()
if (hasBuildExtras) {
    apply from: 'build-extras.gradle'
}

// Set property defaults after extension .gradle files.
if (ext.cdvCompileSdkVersion == null) {
    ext.cdvCompileSdkVersion = privateHelpers.getProjectTarget()
}
if (ext.cdvBuildToolsVersion == null) {
    ext.cdvBuildToolsVersion = privateHelpers.findLatestInstalledBuildTools()
}
if (ext.cdvDebugSigningPropertiesFile == null && file('debug-signing.properties').exists()) {
    ext.cdvDebugSigningPropertiesFile = 'debug-signing.properties'
}
if (ext.cdvReleaseSigningPropertiesFile == null && file('release-signing.properties').exists()) {
    ext.cdvReleaseSigningPropertiesFile = 'release-signing.properties'
}

// Cast to appropriate types.
ext.cdvBuildMultipleApks = cdvBuildMultipleApks == null ? false : cdvBuildMultipleApks.toBoolean();
ext.cdvMinSdkVersion = cdvMinSdkVersion == null ? null : Integer.parseInt('' + cdvMinSdkVersion)
ext.cdvVersionCode = cdvVersionCode == null ? null : Integer.parseInt('' + cdvVersionCode)

def computeBuildTargetName(debugBuild) {
    def ret = 'assemble'
    if (cdvBuildMultipleApks && cdvBuildArch) {
        def arch = cdvBuildArch == 'arm' ? 'armv7' : cdvBuildArch
        ret += '' + arch.toUpperCase().charAt(0) + arch.substring(1);
    }
    return ret + (debugBuild ? 'Debug' : 'Release')
}

// Make cdvBuild a task that depends on the debug/arch-sepecific task.
task cdvBuildDebug
cdvBuildDebug.dependsOn {
    return computeBuildTargetName(true)
}

task cdvBuildRelease
cdvBuildRelease.dependsOn {
    return computeBuildTargetName(false)
}

task cdvPrintProps << {
    println('cdvCompileSdkVersion=' + cdvCompileSdkVersion)
    println('cdvBuildToolsVersion=' + cdvBuildToolsVersion)
    println('cdvVersionCode=' + cdvVersionCode)
    println('cdvMinSdkVersion=' + cdvMinSdkVersion)
    println('cdvBuildMultipleApks=' + cdvBuildMultipleApks)
    println('cdvReleaseSigningPropertiesFile=' + cdvReleaseSigningPropertiesFile)
    println('cdvDebugSigningPropertiesFile=' + cdvDebugSigningPropertiesFile)
    println('cdvBuildArch=' + cdvBuildArch)
    println('computedVersionCode=' + android.defaultConfig.versionCode)
    android.productFlavors.each { flavor ->
        println('computed' + flavor.name.capitalize() + 'VersionCode=' + flavor.versionCode)
    }
}

android {
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
            jniLibs.srcDirs = ['libs']
        }
    }

    defaultConfig {
        versionCode cdvVersionCode ?: new BigInteger("" + privateHelpers.extractIntFromManifest("versionCode"))
        applicationId privateHelpers.extractStringFromManifest("package")

        if (cdvMinSdkVersion != null) {
            minSdkVersion cdvMinSdkVersion
        }
    }

    lintOptions {
      abortOnError false;
    }

    compileSdkVersion cdvCompileSdkVersion
    buildToolsVersion cdvBuildToolsVersion

    if (Boolean.valueOf(cdvBuildMultipleApks)) {
        productFlavors {
            armv7 {
                versionCode defaultConfig.versionCode*10 + 2
                ndk {
                    abiFilters "armeabi-v7a", ""
                }
            }
            x86 {
                versionCode defaultConfig.versionCode*10 + 4
                ndk {
                    abiFilters "x86", ""
                }
            }
            all {
                ndk {
                    abiFilters "all", ""
                }
            }
        }
    }
    /*

    ELSE NOTHING! DON'T MESS WITH THE VERSION CODE IF YOU DON'T HAVE TO!

    else if (!cdvVersionCode) {
      def minSdkVersion = cdvMinSdkVersion ?: privateHelpers.extractIntFromManifest("minSdkVersion")
      // Vary versionCode by the two most common API levels:
      // 14 is ICS, which is the lowest API level for many apps.
      // 20 is Lollipop, which is the lowest API level for the updatable system webview.
      if (minSdkVersion >= 20) {
        defaultConfig.versionCode += 9
      } else if (minSdkVersion >= 14) {
        defaultConfig.versionCode += 8
      }
    }
    */

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_6
        targetCompatibility JavaVersion.VERSION_1_6
    }

    if (cdvReleaseSigningPropertiesFile) {
        signingConfigs {
            release {
                // These must be set or Gradle will complain (even if they are overridden).
                keyAlias = ""
                keyPassword = "__unset" // And these must be set to non-empty in order to have the signing step added to the task graph.
                storeFile = null
                storePassword = "__unset"
            }
        }
        buildTypes {
            release {
                signingConfig signingConfigs.release
            }
        }
        addSigningProps(cdvReleaseSigningPropertiesFile, signingConfigs.release)
    }
    if (cdvDebugSigningPropertiesFile) {
        addSigningProps(cdvDebugSigningPropertiesFile, signingConfigs.debug)
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: '*.jar')
    // SUB-PROJECT DEPENDENCIES START
    debugCompile(project(path: "CordovaLib", configuration: "debug"))
    releaseCompile(project(path: "CordovaLib", configuration: "release"))
    compile "com.google.android.gms:play-services-base:9.0.0"
    compile "com.google.android.gms:play-services-ads:9.0.0"
    compile "com.android.support:support-v4:24.1.1+"
    compile "com.facebook.android:facebook-android-sdk:4.+"
    compile "com.google.firebase:firebase-core:+"
    compile "com.google.firebase:firebase-messaging:+"
    compile "com.stripe:stripe-android:4.1.2"
    compile "com.google.android.gms:play-services-auth:9.0.0"
    compile "com.google.android.gms:play-services-identity:9.0.0"
    // SUB-PROJECT DEPENDENCIES END
}

def promptForReleaseKeyPassword() {
    if (!cdvReleaseSigningPropertiesFile) {
        return;
    }
    if ('__unset'.equals(android.signingConfigs.release.storePassword)) {
        android.signingConfigs.release.storePassword = privateHelpers.promptForPassword('Enter key store password: ')
    }
    if ('__unset'.equals(android.signingConfigs.release.keyPassword)) {
        android.signingConfigs.release.keyPassword = privateHelpers.promptForPassword('Enter key password: ');
    }
}

gradle.taskGraph.whenReady { taskGraph ->
    taskGraph.getAllTasks().each() { task ->
        if (task.name == 'validateReleaseSigning' || task.name == 'validateSigningRelease') {
            promptForReleaseKeyPassword()
        }
    }
}

def addSigningProps(propsFilePath, signingConfig) {
    def propsFile = file(propsFilePath)
    def props = new Properties()
    propsFile.withReader { reader ->
        props.load(reader)
    }

    def storeFile = new File(props.get('key.store') ?: privateHelpers.ensureValueExists(propsFilePath, props, 'storeFile'))
    if (!storeFile.isAbsolute()) {
        storeFile = RelativePath.parse(true, storeFile.toString()).getFile(propsFile.getParentFile())
    }
    if (!storeFile.exists()) {
        throw new FileNotFoundException('Keystore file does not exist: ' + storeFile.getAbsolutePath())
    }
    signingConfig.keyAlias = props.get('key.alias') ?: privateHelpers.ensureValueExists(propsFilePath, props, 'keyAlias')
    signingConfig.keyPassword = props.get('keyPassword', props.get('key.alias.password', signingConfig.keyPassword))
    signingConfig.storeFile = storeFile
    signingConfig.storePassword = props.get('storePassword', props.get('key.store.password', signingConfig.storePassword))
    def storeType = props.get('storeType', props.get('key.store.type', ''))
    if (!storeType) {
        def filename = storeFile.getName().toLowerCase();
        if (filename.endsWith('.p12') || filename.endsWith('.pfx')) {
            storeType = 'pkcs12'
        } else {
            storeType = signingConfig.storeType // "jks"
        }
    }
    signingConfig.storeType = storeType
}

for (def func : cdvPluginPostBuildExtras) {
    func()
}

// This can be defined within build-extras.gradle as:
//     ext.postBuildExtras = { ... code here ... }
if (hasProperty('postBuildExtras')) {
    postBuildExtras()
}

project.properties

# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-26
android.library.reference.1=CordovaLib
cordova.gradle.include.1=card.io.cordova.mobilesdk/servicefinder-build.gradle
cordova.gradle.include.2=com.paypal.cordova.mobilesdk/servicefinder-build.gradle
cordova.system.library.1=com.google.android.gms:play-services-base:9.0.0
cordova.system.library.2=com.google.android.gms:play-services-ads:9.0.0
cordova.system.library.3=com.android.support:support-v4:24.1.1+
cordova.system.library.4=com.facebook.android:facebook-android-sdk:4.+
cordova.system.library.5=com.google.firebase:firebase-core:+
cordova.system.library.6=com.google.firebase:firebase-messaging:+
cordova.gradle.include.3=cordova-plugin-fcm/servicefinder-FCMPlugin.gradle
cordova.system.library.7=com.stripe:stripe-android:4.1.2
cordova.gradle.include.4=cordova-plugin-hockeyapp/servicefinder-build.gradle
cordova.system.library.8=com.google.android.gms:play-services-auth:9.0.0
cordova.system.library.9=com.google.android.gms:play-services-identity:9.0.0

It may be a case of multidex as you have clashing bundles.
check this link it may help:

Link 1

And please create a backup of your project before doing any changes.

Thanks.
I ended up removing Android platform, iOS platform, and the Google Plus, Admob and FCM plugins, and adding all again, and after a few hiccups, it’s all working now, no errors.

Thanks again.