androidfluttergradlehuawei-mobile-servicesappgallery-connect

Huawei AGCP plugin cannot be applied


I'm well aware of other questions (eg. com.huawei.agconnect plugin not found) but they don't currently apply. Sadly, this is a moving target, old answers are not necessarily true any more.

I'm trying to move a Flutter app to the newer, plugin block based Gradle approach. AGCP doesn't allow us to do away with the old buildscript yet completely. Also, the app has two flavors, one Google and one Huawei and, sadly, as per the requirements of both actual stores, I have to make sure nothing from the opposing code remains in the executable (they don't accept an app with the competitor's libraries, even if they're unused based on runtime conditions). It all worked until about a year ago when Huawei started to lag behind times and I can't completely fix it now, either.

Basically, settings.gradle has the usual resolution approach:

pluginManagement {
  [...]

  repositories {
    google()
    mavenCentral()
    maven { url "https://developer.huawei.com/repo/" }
    gradlePluginPortal()
  }

  resolutionStrategy {
    eachPlugin {
      if (requested.id.id == "com.huawei.agconnect") {
        useModule("com.huawei.agconnect:agcp:1.9.1.303")
      }
    }
  }
}

plugins {
  id "dev.flutter.flutter-plugin-loader" version "1.0.0"
  id "com.android.application" version "7.3.1" apply false
  id "org.jetbrains.kotlin.android" version "1.9.22" apply false
  id "com.huawei.agconnect" version "1.9.1.303" apply false
}

The project build.gradle seems irrelevant, the well reduced code as dictated by the new Gradle approach. The app build.gradle has the remnants of the buildscript, with the difference that it only specifies the dependencies conditionally. It also calls the apply plugin conditionally.

buildscript {
  repositories {
    maven { url 'https://developer.huawei.com/repo/' }
  }

  dependencies {
    if (getGradle().getStartParameter().getTaskRequests().toString().toLowerCase().contains("huawei")) {
      classpath 'com.android.tools.build:gradle:7.3.1'
      classpath 'com.huawei.agconnect:agcp:1.9.1.303'
    }
  }
}

[...]

    each { flavor ->
      if (getGradle().getStartParameter().getTaskRequests().toString().toLowerCase().contains("huawei")) {
        apply plugin: "com.huawei.agconnect"
      }
    }

The current error message is No such property: rootProject for class: com.huawei.agconnect.agcp.AGCProcess. Without applying the plugin, the app compiles but will be non-functional because running this plugin would be required to store the entries of agconnect-services.json for the app to use at runtime and without those, the actual ad serving is missing.

One of the answers linked above mentions that, theoretically, 1.9.1.300+ is already compatible with Gradle 8 out of the box (bumping up com.android.application to 8.1.1 or similar and adjusting the gradle-wrapper version number). This is a promising remark and would certainly be the way ahead but, unfortunately, doesn't seem to work for now. This newer Gradle expects a namespace in the android block and while that can be added easily in one's own app and plugins, already upgraded community plugins are few and far between, so in most cases, building will stop on referenced plugins without a namespace.

Update

As an alternative approach, I tried to move my Huawei gradle settings back to the internal module (I have both a Google and a Huawei one and use them accordingly, it was documented in the answer to Is Huawei HMS tolerated on Google Play Store? if anybody is still in the same shoes). At first, I wasn't aware of the fact that you can have module specific gradle files even if you don't have actual Android code, in other words, your internal module is a package rather than a plugin (as you don't tend to have an android folder at all in this case).

Basically, the module would have its own android folder with the three usual files. settings.gradle receives the plugin management with the resolution strategy, local.properties has nothing else but the previously missing root project name and build.gradle houses the buildscript without the need for conditional execution. At the app level, those could be removed, as well as the conditional apply plugin because this is now covered at the module's level.

Only problem that it doesn't work... Although it compiles without error, this is clearly wrong because agconnect-services.json isn't processed (two ways to check it, first, I can put a syntax error into the file and see that nobody complains, second, some Huawei docs describe that resources.arsc should receive string resources starting with agc_ in the resulting APK). Also, the app running reports that the JSON wasn't located and consequently, there are no ads displayed. As an alternative, we could provide appid and cpid in the app manifest but while Huawei IAP seems to be content with that, Ads is not.


Solution

  • It turned out to be a regression. Stick to 1.9.0 until Huawei fixes it. I reported it in the plugins's issue queue.