Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
AndrewSouthpaw opened this issue Apr 7, 2020 · 26 comments · Fixed by expo/expo-cli#1897 or expo/turtle#209
Closed
Assignees
Labels
bug Expo Go The client distributed on app stores Notifications

Comments

@AndrewSouthpaw
Copy link
Contributor

AndrewSouthpaw commented Apr 7, 2020

✅ Resolved: jump straight to the solution

The following comment provides a solution and an explanation of the problem: #7727 (comment)


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"
@joshg2k
Copy link
Contributor

joshg2k commented Apr 8, 2020

+1 this issue

@merikwesterveld
Copy link

Same happening here

@sjchmiela sjchmiela self-assigned this Apr 8, 2020
@sjchmiela
Copy link
Contributor

Hm, ok, so, at first (in the issue where I asked you to create another one) I understood the "production application" as a standalone application built using expo build:android. Only now when I focused 100% on this report I noticed the title mentions "Expo Client".

Did/do you mean "apps in production mode running in Expo Client"? If so I'm sorry I put you through the process of creating a new issue—it is totally related to the original.

Next time I will make sure to understand a comment correctly before asking to create another issue. 🙂

Good news is that both #7653 and this should be resolved in the latest release of Expo Client for Android — v2.15.1. Cross-posting from #7653 (comment):

The 2.15.1 update, fixing this particular issue, is currently propagating through Google Play Store. You can also install it using expo client:install:android. 🙂

Let me know if this has resolved your problem and my understanding is correct, if not, we'll get down to debugging!

@alex-fournier
Copy link
Contributor

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

@sjchmiela sjchmiela changed the title SDK37 Android Expo Client: "Couldn't get GCM token on device" in production application SDK37 standalone app: "Couldn't get GCM token on device" Apr 8, 2020
@AndrewSouthpaw
Copy link
Contributor Author

Same; the app is deployed via Travis using the expo build:android command.

@AndrewSouthpaw
Copy link
Contributor Author

Sorry for the misleading title! 😄

@smuxx
Copy link

smuxx commented Apr 9, 2020

+1 this issue

@eddyoc
Copy link

eddyoc commented Apr 9, 2020

+1. This issue appears to have started with our upgrade to SDK 37. Issue exhibiting for us on Android standalone.

@sjchmiela
Copy link
Contributor

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"
        }
      }

@RoninSTi
Copy link
Contributor

RoninSTi commented Apr 9, 2020

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

@joshg2k
Copy link
Contributor

joshg2k commented Apr 9, 2020

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

@mikeacruz
Copy link

mikeacruz commented Apr 9, 2020

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

I really appreciate this. Thank you.

@alex-fournier
Copy link
Contributor

Working for me as well :) Thanks a lot for your work.

@lukBakTsh
Copy link

lukBakTsh commented Apr 10, 2020

googleSignIn API key was always taken from the google-services.json file, I think this error may be related to this problem:

Running grade
Running gradle

@browserstackvaibhav
Copy link

Any update on this?

@gitnasr
Copy link

gitnasr commented Apr 14, 2020

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

expo team should add this step to docs! thanks anyway

@nicholasgrillsolutions
Copy link

Yea, they should! Took me hours to find out.

@MarzV
Copy link

MarzV commented Apr 14, 2020

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

@gitnasr
Copy link

gitnasr commented Apr 14, 2020

it took me about 49 hours to figure out a solution! and I needed to rebuild apk to users

@AndrewSouthpaw
Copy link
Contributor Author

AndrewSouthpaw commented Apr 14, 2020

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!

@MarzV
Copy link

MarzV commented Apr 15, 2020

Hey the issue for me is not resolved with the fix @sjchmiela suggested. Everything was working fine before the update to SDK 37, and as you can see in my dev settings, I am still working with the sdk 36. In a expo managed app, so its not ejected

I am testing the STANDALONE app on browserstack.
Device: Samsun Galaxy s10
Os: Android, V9

This is the log from cradle:
Could not find google-services.json while looking in [src/nullnull/debug, src/debug/nullnull, src/nullnull, src/debug, src/nullnullDebug]
registerResGeneratingTask is deprecated, use registerGeneratedResFolders(FileCollection)
Could not find google-services.json while looking in [src/nullnull/release, src/release/nullnull, src/nullnull, src/release, src/nullnullRelease]
registerResGeneratingTask is deprecated, use registerGeneratedResFolders(FileCollection)

I presume this is where things go wrong.

As you probably can see, I use the suggested solution with the googleSignIn key, but there is not token set when calling await Notifications.getExpoPushTokenAsync();

If I understand the problem correct, this has something todo with the path to google.service.json. Can somebody explain how to set the path correct, or am I missing something else?

@MarzV
Copy link

MarzV commented Apr 16, 2020

@sjchmiela, First of all, thnkz for addressing this issue, lot of people depend on this feature. But can can you please eleborate on this a bit more in detail in the scenario that a build is made with SDK 36

Before this issues was raised, I did not have the extra code in my app.json for the google.service.json. I mean this snippet of code:

"android": {
"package": "secret",
"googleServicesFile": "./google-services.json",
"config": {
"googleSignIn": {
"apiKey": "xxxxxxxxxxxxxxxx"
}
},
"versionCode": 1
},
}

But after the moment issues where raised that pushtoken was no longer set for standalone apps. there was a suggestion that adding the above code would fix the problem, so I did.

Question: When building with SDK 36 do we still need to add the above extra snippet of code, even when before it was not there and everything worked just fine. Or do we now always need to add this extra code snippit to the app.json file.?

Your answer is much appreciated

sjchmiela added a commit to expo/expo-cli that referenced this issue Apr 17, 2020
…1897)

# Why

Following [Using FCM doc](https://docs.expo.io/versions/latest/guides/using-fcm/) or [GoogleSignIn - Usage with Firebase part](https://docs.expo.io/versions/latest/sdk/google-sign-in/#usage-with-firebase) would not render the expected results — `googleSignIn` configuration was always being applied onto `google-services.json`, even if a custom one has been provided by the user. Most probably this is not how this should work or what the user expect.

When pushed to Turtle builders, should fix expo/expo#7727.

# How

Depending on the SDK version of the built project:
- if the SDK is >= 37:
  - only change `google-services.json` if none was provided (so we're operating on a placeholder one)
  - if both configuration settings are provided print a warning and not modify the custom `google-services.json`
- if the SDK is < 37:
  - if the user provides a custom `googleServicesFile`, print a warning that its contents are about to be modified,
  - always modify `google-services.json`, as it has been working before.

I have also moved the `replace "host.exp.exponent" with ${javaPackage}` to where the logic above is mentioned so that all `google-services.json` modifications are in one place.

# Test plan

- SDK37, only `googleServicesFile` — [job](https://staging.expo.io/dashboard/sjchmiela/builds/4dca157f-3ae5-4739-96a7-2a1fbcf2ec0e), no warning, used `google-services.json`
- SDK37, only `googleSignIn` — [job](https://staging.expo.io/dashboard/sjchmiela/builds/2c44d75e-9ce1-4098-ab64-04e76f01efda), no warning, uses placeholder project ID and `googleSignIn` key
- SDK37, both provided — [job](https://staging.expo.io/dashboard/sjchmiela/builds/23626002-acf2-4a30-a620-2062f134d671), warning present (google-services.json overrides others), used `google-services.json`
- SDK36, only `googleServicesFile` — ~[job](https://staging.expo.io/dashboard/sjchmiela/builds/8366c022-dcff-4047-bf0a-0264a52870a1), no warning, **removed key from google-services.json**~ force-pushed version where the warning should be printed and the key still removed
- SDK36, only `googleSignIn` — [job](https://staging.expo.io/dashboard/sjchmiela/builds/d59e4334-a815-4d6a-8ba2-108ab2f5d8bc), no warning, used `googleSignIn` and leaking project ID
- SDK36, both provided — [job](https://staging.expo.io/dashboard/sjchmiela/builds/d5a8ab8f-07f7-4aac-9c64-7012421d1b49), warning present (google-services.json overridden), google-services.json overridden
@sjchmiela
Copy link
Contributor

sjchmiela commented Apr 17, 2020

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.

@rinovethamoses97
Copy link

rinovethamoses97 commented Apr 18, 2020

@sjchmiela Thanks much. You Suggestion Worked for me. Any idea why the app crashes while trying to get a push token when the device is not connected to the internet?

sjchmiela added a commit to expo/turtle that referenced this issue Apr 20, 2020
#209)

<!-- Thanks for contributing to _turtle_! Before you submit your pull request, please make sure to check the following boxes by putting an x in the [ ] (don't: [x ], [ x], do: [x]) -->

### Checklist
- [x] I've read the [Contribution Guidelines] (https://github.com/expo/turtle/blob/master/CONTRIBUTING.md).
- [x] I've updated the [CHANGELOG](https://github.com/expo/turtle/blob/master/CHANGELOG.md) if necessary.
- [x] I've ensured the unit and smoke tests are still passing - either by running `yarn test:unit` and `yarn test:smoke:[ios|android]` or by checking the appropriate CircleCI builds' statuses.
- [x] **I've manually tested whether the changes I made work as expected.**

### Motivation and Context

- `google-services.json` was being handled unintuitively, fixed with expo/expo-cli#1897
- Expo Client's secrets were leaking in shell apps, fixed with expo/expo#7768
- When deployed, fixes expo/expo#7727.

### Description

XDL was modifying `google-services.json`, removing valid keys if the user doesn't provide the same, removed key in _some other place_ (see expo/expo#7727 (comment)). Fixed the change in XDL, upgraded to the fixed version here. Also removed secrets from the shell app.
@sjchmiela
Copy link
Contributor

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 expo/expo-cli#1897.

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

In fact, yes, if you have applied the workaround described at #7727 (comment), 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 #7606 (comment).

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: Project > Clean Project) 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!)

@brentvatne
Copy link
Member

I'm locking this thread to make sure @sjchmiela's response above remains as the definitive obvious answer. As he mentions at the end of his comment, if you are encountering an issue that you think is related, please post a new issue on the repo so we can keep the discussion separate and please share the build URL (you can share it privately to secure@expo.io and mention the issue in it if you wish).

@expo expo locked and limited conversation to collaborators Apr 20, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Expo Go The client distributed on app stores Notifications
Projects
None yet