ionic-team / capacitor

Build cross-platform Native Progressive Web Apps for iOS, Android, and the Web ⚡️
https://capacitorjs.com
MIT License
11.44k stars 977 forks source link

UrbanAirship on android : unable to find google-services.json & No matching client found for package name 'capacitor.android.plugins' #2511

Closed florianchevallier closed 4 years ago

florianchevallier commented 4 years ago

TL:DR : the step to reproduce the issue :

ionic start ua-test blank --type react --capacitor
cd ua-test
npx cap init ua-test com.ua.test.app --web-dir build --npm-client npm
npm install @ionic-native/core
npm install urbanairship-cordova
npm install @ionic-native/urbanairship
ionic cap sync
ionic cap add android
ionic cap open android

And the error :

Executing tasks: [:app:assembleDebug] in project /Users/florianchevallier/Projects/POC/ua-test/android

> Configure project :app
google-services.json not found, google-services plugin not applied. Push Notifications won't work

> Configure project :capacitor-android
WARNING: API 'variant.getJavaCompiler()' is obsolete and has been replaced with 'variant.getJavaCompileProvider()'.
It will be removed at the end of 2019.
For more information, see https://d.android.com/r/tools/task-configuration-avoidance.
To determine what is calling variant.getJavaCompiler(), use -Pandroid.debug.obsoleteApi=true on the command line to display a stack trace.
WARNING: API 'variantOutput.getPackageLibrary()' is obsolete and has been replaced with 'variant.getPackageLibraryProvider()'.
It will be removed at the end of 2019.
For more information, see https://d.android.com/r/tools/task-configuration-avoidance.
To determine what is calling variantOutput.getPackageLibrary(), use -Pandroid.debug.obsoleteApi=true on the command line to display a stack trace.

> Task :app:preBuild UP-TO-DATE
> Task :capacitor-android:preBuild UP-TO-DATE
> Task :capacitor-android:preDebugBuild UP-TO-DATE
> Task :capacitor-android:checkDebugManifest
> Task :capacitor-android:processDebugManifest
> Task :capacitor-cordova-android-plugins:preBuild UP-TO-DATE
> Task :capacitor-cordova-android-plugins:preDebugBuild UP-TO-DATE
> Task :capacitor-cordova-android-plugins:checkDebugManifest
> Task :capacitor-cordova-android-plugins:processDebugManifest
> Task :app:preDebugBuild
> Task :capacitor-android:compileDebugAidl NO-SOURCE
> Task :capacitor-cordova-android-plugins:compileDebugAidl NO-SOURCE
> Task :app:compileDebugAidl NO-SOURCE
> Task :capacitor-android:packageDebugRenderscript NO-SOURCE
> Task :capacitor-cordova-android-plugins:packageDebugRenderscript NO-SOURCE
> Task :app:compileDebugRenderscript
> Task :app:checkDebugManifest
> Task :app:generateDebugBuildConfig
> Task :app:prepareLintJar
> Task :app:generateDebugSources
> Task :capacitor-android:compileDebugRenderscript
> Task :capacitor-android:generateDebugBuildConfig
> Task :capacitor-android:generateDebugResValues
> Task :capacitor-android:generateDebugResources
> Task :capacitor-android:packageDebugResources
> Task :capacitor-android:generateDebugRFile
> Task :capacitor-android:prepareLintJar
> Task :capacitor-android:generateDebugSources
> Task :capacitor-android:javaPreCompileDebug

> Task :capacitor-android:compileDebugJavaWithJavac
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.

> Task :capacitor-android:processDebugJavaRes NO-SOURCE
> Task :capacitor-android:transformClassesAndResourcesWithPrepareIntermediateJarsForDebug
> Task :capacitor-cordova-android-plugins:compileDebugRenderscript
> Task :capacitor-cordova-android-plugins:generateDebugBuildConfig
> Task :capacitor-cordova-android-plugins:generateDebugResValues
> Task :capacitor-cordova-android-plugins:generateDebugResources
> Task :capacitor-cordova-android-plugins:processDebugGoogleServices FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':capacitor-cordova-android-plugins:processDebugGoogleServices'.
> File google-services.json is missing. The Google Services Plugin cannot function without it. 
   Searched Location: 
  /Users/florianchevallier/Projects/POC/ua-test/android/capacitor-cordova-android-plugins/src/nullnull/google-services.json
  /Users/florianchevallier/Projects/POC/ua-test/android/capacitor-cordova-android-plugins/src/debug/google-services.json
  /Users/florianchevallier/Projects/POC/ua-test/android/capacitor-cordova-android-plugins/src/nullnullDebug/google-services.json
  /Users/florianchevallier/Projects/POC/ua-test/android/capacitor-cordova-android-plugins/src/nullnull/debug/google-services.json
  /Users/florianchevallier/Projects/POC/ua-test/android/capacitor-cordova-android-plugins/src/debug/nullnull/google-services.json
  /Users/florianchevallier/Projects/POC/ua-test/android/capacitor-cordova-android-plugins/google-services.json

What I've tried so far

place a google-services.json in capacitor-cordova-android-plugins

If I place a google-services.json here :

/Users/florianchevallier/Projects/POC/ua-test/android/capacitor-cordova-android-plugins/google-services.json

I get a different error :

> Task :capacitor-cordova-android-plugins:processDebugGoogleServices FAILED
Parsing json file: /Users/florianchevallier/Projects/POC/ua-test/android/capacitor-cordova-android-plugins/google-services.json

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':capacitor-cordova-android-plugins:processDebugGoogleServices'.
> No matching client found for package name 'capacitor.android.plugins'

Which lead me here #1286 ending in

Did you find a solution? no, and i currently don't care 😅

Rename the package name of capacitor-cordova-android-plugins/src/main/AndroidManifest.xml

To match the id of my current firebase config. Which lead me here :

Manifest merger failed : Attribute application@appComponentFactory value=(androidx.core.app.CoreComponentFactory) from [androidx.core:core:1.1.0] AndroidManifest.xml:24:18-86
    is also present at [com.android.support:support-compat:28.0.0] AndroidManifest.xml:22:18-91 value=(android.support.v4.app.CoreComponentFactory).
    Suggestion: add 'tools:replace="android:appComponentFactory"' to <application> element at AndroidManifest.xml:5:5-43:19 to override.

Which seems to be a bug with AndroidX. Tried this : https://github.com/ionic-team/capacitor/pull/2045#issuecomment-546707620 (with this repo on master) + Refactor > Migrate to AndroidX

And now... it works on Android. The thing is, I shouldn't have to edit the package name of capacitor-cordova-android-plugins/src/main/AndroidManifest.xml since it's always generated.

Do you have any idea how it could be easier to implement ?

Cheers

florianchevallier commented 4 years ago

Alright ! seems that adding

uaSkipApplyGoogleServicesPlugin=true

into the gradle.properties file does the trick. You still need to do the refactor to AndroidX.

I get the notification in background while the app is open, but not while it's closed. But it may be something else not related.

To anyone coming here, here is my ReactJS code to make it work. You'll see that you still need register() to make it work, and to use the Push Notification from @capacitor/core.

I've also followed all the integration of push notification tutorial for iOS apps in capacitor with firebase to make it work for the iPhones.

import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, useIonViewDidEnter } from '@ionic/react';
import React from 'react';
import ExploreContainer from '../components/ExploreContainer';
import { UrbanAirShip } from '@ionic-native/urbanairship';
import './Home.css';

import {
  Plugins,
  PushNotification,
  PushNotificationToken,
  PushNotificationActionPerformed } from '@capacitor/core';

const { PushNotifications } = Plugins;

PushNotifications.register();

async function registerNotification() {
  try {
    await UrbanAirShip.takeOff({
      development: {
        appKey: "xxx",
        appSecret: "xxxx"
      },
      production: {
        appKey: "", // needed, even if empty
        appSecret: "" // needed, even if empty
      }
    })
    await UrbanAirShip.setUserNotificationsEnabled(true)
    const isEnabled = await UrbanAirShip.isUserNotificationsEnabled();
    const isAppEnabled = await UrbanAirShip.isAppNotificationsEnabled();
    const channelId = await UrbanAirShip.getChannelID();
    console.log('isEnabled', isEnabled, isAppEnabled);
    console.log('channelId', channelId);

    PushNotifications.addListener('registration', 
      (token: PushNotificationToken) => {
        console.log('Push registration success, token: ' + token.value);
      }
    );

    // Some issue with our setup and push will not work
    PushNotifications.addListener('registrationError', 
      (error: any) => {
        console.log('Error on registration: ' + JSON.stringify(error));
      }
    );

    // Show us the notification payload if the app is open on our device
    PushNotifications.addListener('pushNotificationReceived', 
      (notification: PushNotification) => {
        console.log('Push received: ' + JSON.stringify(notification));
      }
    );

    // Method called when tapping on a notification
    PushNotifications.addListener('pushNotificationActionPerformed', 
      (notification: PushNotificationActionPerformed) => {
        console.log('Push action performed: ' + JSON.stringify(notification));
      }
    );

  } catch (err) {
    console.log(err);
  }
}

const Home: React.FC = () => {
  useIonViewDidEnter(() => {
    registerNotification();
  })
  return (
    <IonPage>
      <IonHeader>
        <IonToolbar>
          <IonTitle>Blank</IonTitle>
        </IonToolbar>
      </IonHeader>
      <IonContent>
        <IonHeader collapse="condense">
          <IonToolbar>
            <IonTitle size="large">Blank</IonTitle>
          </IonToolbar>
        </IonHeader>
        <ExploreContainer />
      </IonContent>
    </IonPage>
  );
};

export default Home;
vokamut commented 1 year ago

I use hook "capacitor:copy:after":

package.json:

{
    "scripts": {
        "capacitor:copy:after": "node ./hooks/capacitor-copy-after.js $CAPACITOR_PLATFORM_NAME"
    }
}

hooks/capacitor-copy-after.js:

const fs = require('fs');

if (process.argv[2] === 'android') {
    const androidManifest = './android/capacitor-cordova-android-plugins/src/main/AndroidManifest.xml';

    const googleServicesBase = './google-services.json';
    const googleServicesCap = './android/capacitor-cordova-android-plugins/google-services.json';

    fs.readFile(androidManifest, 'utf8', (err, data) => {
        if (err) {
            console.error(err);
            return;
        }

        data = data.replace('capacitor.android.plugins', 'my.project.android'); // CHANGE APPLICATION ID

        fs.writeFile(androidManifest, data, (err) => {
            if (err) {
                console.error(err);
            }
        });
    });

    fs.copyFile(googleServicesBase, googleServicesCap, (err) => {
        if (err) {
            console.error(err);
        }
    });
}
ionitron-bot[bot] commented 1 year ago

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Capacitor, please create a new issue and ensure the template is fully filled out.