expo: SDK37 standalone app: "Couldn't get GCM token on device"

✅ Resolved: jump straight to the solution

The following comment provides a solution and an explanation of the problem: https://github.com/expo/expo/issues/7727#issuecomment-616674874


Original post (for reference)

🐛 Bug Report

This extends #7653. Per the request of @sjchmiela , I’m opening a separate issue for where this error is happening in a production environment.

I have confirmed we followed the instructions in this guide to set up Android notifications correctly. Everything was working fine in Expo SDK 35, and then broken once we upgraded to SDK 37.

We’re seeing this error in Sentry for ~40 users, all Android, mostly version 28 and 29.

Environment

Below is my dev environment, though we are seeing this error in production.

  Expo CLI 3.17.11 environment info:
    System:
      OS: macOS Mojave 10.14.6
      Shell: 5.0.11 - /usr/local/bin/bash
    Binaries:
      Node: 10.19.0 - /var/folders/hq/l83ht_9n2kv0dy9xfdqn1v3r0000gn/T/yarn--1586301240769-0.3336967041216845/node
      Yarn: 1.19.2 - /var/folders/hq/l83ht_9n2kv0dy9xfdqn1v3r0000gn/T/yarn--1586301240769-0.3336967041216845/yarn
      npm: 6.13.4 - ~/.nvm/versions/node/v10.19.0/bin/npm
      Watchman: 4.9.0 - /usr/local/bin/watchman
    IDEs:
      Android Studio: 3.5 AI-191.8026.42.35.5977832
      Xcode: 11.3.1/11C504 - /usr/bin/xcodebuild
    npmPackages:
      expo: ^37.0.0 => 37.0.3
      react-native: https://github.com/expo/react-native/archive/sdk-37.0.0.tar.gz => 0.61.4
      react-navigation: ^3.11.0 => 3.11.0

Build targets are iOS and Android, the issue is for Android only.

Steps to Reproduce

  1. Call Notifications.getExpoPushTokenAsync() in native app

Expected Behavior

  1. Gets a token

Actual Behavior

  1. Returns error “Couldn’t get GCM token on device”

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 4
  • Comments: 26 (13 by maintainers)

Commits related to this issue

Most upvoted comments

I have reproduced the error and I think I have also found a workaround. Could you, please, try:

  • providing the google-services.json file with the expo.android.googleServicesFile setting in app.json
  • providing the api_key copied from the google-services.json under expo.android.config.googleSignIn.apiKey
  • (optionally) providing an API key for Google Maps under expo.android.config.googleMaps.apiKey (if you don’t use them don’t worry about it)
  • rebuilding your app with expo build:android
  • verifying if the issue remains (I had to run the application twice, the first time it errored with “Couldn’t get GCM token on device”, the second one returned an Expo push token, which, if I may, I would consider issue resolved 😃)

Example

For a ./google-services.json:

{
  "project_info": {
    "project_number": "…",
    "firebase_url": "…",
    "project_id": "…",
    "storage_bucket": "…"
  },
  "client": [
    {
      "client_info": {
        "mobilesdk_app_id": "…",
        "android_client_info": {
          "package_name": "…"
        }
      },
      "api_key": [
        {
          "current_key": "KEY_KEY_KEY_KEY_KEY"
        }
      ]
    },

please make app.json:

{
  "expo": {
    "…": "…",
    "android": {
      "package": "…",
      "googleServicesFile": "./google-services.json",
      "config": {
        "googleSignIn": {
          "apiKey": "KEY_KEY_KEY_KEY_KEY"
        }
      }

@sjchmiela Your fix worked for our production standalone app. Much appreciated.

For my case, I have the issue with a standalone application, available through app stores and not running in Expo Client.

The upgrade has been just deployed to production Turtle builders! Read on to find out what does it mean for you.

What was the issue?

There was a bug in the library that is being used to prepare the Android project when building a standalone app—it was always modifying provided google-services.json, even if it has been provided by the user.

The modifications, originally, were supposed to modify a placeholder google-services.json by including your custom Google API key (passed in via googleSignIn). Recently it was modifying the google-services.json, yes, it was your google-services.json and it was removing your key from the JSON if it wasn’t provided in the googleSignIn property.

See the PR fixing at https://github.com/expo/expo-cli/pull/1897.

Since the fix is in production, is there something I should do?

In fact, yes, if you have applied the workaround described at https://github.com/expo/expo/issues/7727#issuecomment-611544439, please be advised to remove the googleSignIn configuration. If googleServicesFile is provided the googleSignIn configuration is going to be ignored and a warning is going to be printed in logs on expo.io builds.

If you have a google-services.json file and you want to use it for your standalone app all you need to do is to provide a path to it in googleServicesFile.

If you don’t have a google-services.json file and you don’t want to get one, you can still use googleSignIn object to pass in only the key and the hash. A template google-services.json file will be used and your keys will be interpolated into it.

I keep getting “Couldn’t get GCM token on device” error

Unfortunately, the changes we’re speaking of are interpolated into native resources when the app is built, so it won’t be possible to fix the problem using an OTA update. You will need to rebuild your app using expo build:android and push the update to Google Play Store (or any other distribution channel).

I’m getting another error: “Couldn’t get push token on device. Check that your FCM configuration is valid.”

First, check if your FCM configuration is valid, i.e. if your google-services.json is up-to-date.

Then, if it is up-to-date, please check in the Google Cloud console if the keys that are used in your app are allowed to communicate with Firebase Installations API. For more information on how to do it, check out https://github.com/expo/expo/issues/7606#issuecomment-608616162.

If it still doesn’t work, try restarting the application. It looks like sometimes it takes a restart to trigger the push token update. It probably doesn’t depend on us or our code — this may be an intermittent issue with Firebase.

If it still doesn’t work, please file a new issue on the repository, let’s fix this bug!

Does the problem come from “Could not find google-services.json while looking in [src/nullnull/debug, src/debug/nullnull, src/nullnull, src/debug, src/nullnullDebug]”?

No, it doesn’t a couple lines below you should see a line reading:

Parsing json file: /app/turtle/workingdir/android/sdk37/android-shell-app/app/google-services.json

Zrzut ekranu 2020-04-20 o 18 24 19

Should we add the workaround to the docs?

No, as it only has been a workaround until the real issue (with the aforementioned library) was fixed. However, I am really sorry some of you had to spend so much time debugging an issue that wasn’t your fault. I, too, know how daunting this can be and I apologize. As always I recommend checking out the issues list here or our forums if you encounter any more blocking (or any other) issues using Expo.

Do I need to rebuild the app or will a publish suffice?

As Google configuration is included in native resources of the app you will need to do a full rebuild with expo build:android and then distribute the new version of the app.

I’m using an ejected ExpoKit app, is there something I should do?

Make sure google-services.json in android/app are up-to-date.

Try cleaning your project (from Android Studio: <kbd>Project</kbd> > <kbd>Clean Project</kbd>) and rebuilding.

If that doesn’t work you can try adding implementation 'com.google.firebase:firebase-messaging:20.1.5' to the dependencies section of android/app/build.gradle (thus, upgrading the Firebase Cloud Messaging library). It may fix some issues.

I’m still on SDK lower than 37. How to approach this issue?

I was afraid of breaking any behavior that users of previous SDKs may depend on, so I didn’t change anything apart from adding a warning.

If you’re on SDK36 or lower and would like to use your own google-services.json:

The app is crashing when trying to fetch a push token when not connected to the Internet

Frankly speaking I haven’t experienced it myself, so I don’t have any straight-up solution. Would you care to post a new issue on the repo so we can keep the discussion separate? (Posting the build URL would be helpful!)

@sjchmiela I can confirm your fix works for our production standalone app. Greatly appreciated (just to one-up @RoninSTi)

I have merged the pull request that fixes the unintuitive behavior in @expo/xdl which required adding the same keys under googleSignIn property to have it included in google-services.json (despite having googleServicesFile defined).

I will answer all the remaining questions once the new version is up on the production Android builders.

FWIW I needed to publish a new version to the Google Play store; just publishing to Expo wasn’t able to provide OTA changes about the app.json. Forcing a full version upgrade was enough to get the changes to percolate.

Thanks @sjchmiela for putting together a workaround!

This is really bad practise not to mention this by the expo team