Yet another API Exception code 10
See original GitHub issueHi,
I would like to begin with the fact that I am well aware that this “code 10” issue is very common and well documented. Yet after days of struggling with it, I am still unable to find a solution to this issue.
My goal is to create a simple Quasar app working with capacitor, using my own proprietary backend. I will start over from scratch and describe exactly what I do in details to make it easy for you to spot what I did wrong, hoping this could help future readers as well. I’m using one Google account to access the Google API console, and my personnal account to try to login. I’m only creating this app for testing purposes.
First, I created a new app:
paul@vivobook:~/git$ quasar --version
1.1.2
paul@vivobook:~/git$ quasar create testapp
___
/ _ \ _ _ __ _ ___ __ _ _ __
| | | | | | |/ _` / __|/ _` | '__|
| |_| | |_| | (_| \__ \ (_| | |
\__\_\\__,_|\__,_|___/\__,_|_|
? Project name (internal usage for dev) testapp
? Project product name (must start with letter if building mobile apps) Quasar A
pp
? Project description A Quasar Framework app
? Author Paul
? Pick your favorite CSS preprocessor: (can be changed later) SCSS
? Pick a Quasar components & directives import strategy: (can be changed later)
Auto import
? Check the features needed for your project: Vuex, Axios, Vue-i18n
? Continue to install project dependencies after the project has been created? (
recommended) NPM
Then, I installed the package directly in the web project (npx cap update is of no use here):
$ cd testapp
$ npm i --save @codetrix-studio/capacitor-google-auth
After this, I created a very basic login page:
<template>
<q-page class="flex flex-center">
<img
alt="Quasar logo"
src="~assets/quasar-logo-full.svg"
>
<div v-if="user">
{{ user }}
<button @click="logoutFromGoogle">Sign out from google</button>
</div>
<div v-else>
<button v-if="$q.platform.is.android" @click="startGoogleSignIn">Sign in with google</button>
</div>
</q-page>
</template>
<script>
import { Plugins } from '@capacitor/core';
const { GoogleAuth } = Plugins;
export default {
name: 'PageIndex',
data: function () {
return {
user: null
};
},
methods: {
async startGoogleSignIn () {
try {
this.user = await GoogleAuth.signIn();
} catch (e) {
console.log(e);
return;
}
console.log(user);
},
async logoutFromGoogle () {
await GoogleAuth.signOut();
this.user = null;
}
}
}
</script>
After this I generated the app in order to get a fingerprint.
$ quasar dev -m capacitor -T android
Dev mode.......... capacitor
Pkg quasar........ v1.14.1
Pkg @quasar/app... v2.1.1
Debugging......... enabled
Running mode...... IDE (manual)
// logs cut here for briefness
App · ⚠️ Quasar CAPACITOR is missing. Installing it...
? What is the Capacitor app id? com.paul.testapp
// The command succeeded
^C
$ cd src-capacitor/
$ npm i --save @codetrix-studio/capacitor-google-auth
+ @codetrix-studio/capacitor-google-auth@2.1.1
added 2 packages from 2 contributors and audited 60 packages in 2.658s
found 0 vulnerabilities
$ npx cap update
✔ Updating Android plugins in 6.06ms
Found 1 Capacitor plugin for android:
@codetrix-studio/capacitor-google-auth (2.1.1)
✔ update android in 27.53ms
✔ update web in 28.01μp
Update finished in 0.038s
$ cd ..
$ quasar dev -m capacitor -T android
At this point, I have a dev web server running and Android studio opened with my project files. I ran the Gradle signingReport task:
The next step is to create OAuth credentials from Google.
First things first, I created a new project:
Then I set up the OAuth consent screen filling in as much as we can without requiring verification. As seen here this is set up as an external app (FYI hotspotdev.me is a redirect to my localhost).
I then generated the OAuth client IDs for an Android app. I did not generate any for a web client, since - to my understanding - the consent screen is the native Android one.
I then added this tag to my head
:
<meta name="google-signin-client_id" content="90xxxxxxxxxv2.apps.googleusercontent.com">
Then edited src/main/res/values/strings.xml by adding:
<string name="server_client_id">90xxxxxxxxxxxv2.apps.googleusercontent.com</string>
I then edited src/main/java/com/paul/testapp/MainActivity.java:
package com.paul.testapp;
import android.os.Bundle;
import com.codetrixstudio.capacitor.GoogleAuth.GoogleAuth;
import com.getcapacitor.BridgeActivity;
import com.getcapacitor.Plugin;
import java.util.ArrayList;
public class MainActivity extends BridgeActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Initializes the Bridge
this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {{
// Additional plugins you've installed go here
// Ex: add(TotallyAwesomePlugin.class);
add(GoogleAuth.class);
}});
}
}
And finally edited src/main/assets/capacitor.config.json:
{
"appId": "com.paul.testapp",
"appName": "Quasar App",
"bundledWebRuntime": false,
"npmClient": "npm",
"webDir": "www",
"server": {
"url": "http://10.42.0.1:8080"
},
"plugins": {
"GoogleAuth": {
"scopes": ["profile", "email"],
"serverClientId": "90xxxxxxxxxxxxxxxxxxv2.apps.googleusercontent.com",
"forceCodeForRefreshToken" : true
}
}
}
I tried setting forceCodeForRefreshToken
to false
with the same outcome.
At this point every login attempt fails with the well-known stack trace:
2020-10-05 21:21:36.375 29147-29147/com.paul.testapp E/Capacitor/Plugin: Something went wrong
com.google.android.gms.common.api.ApiException: 10:
at com.google.android.gms.common.internal.ApiExceptionUtil.fromStatus(com.google.android.gms:play-services-base@@17.1.0:4)
at com.google.android.gms.auth.api.signin.GoogleSignIn.getSignedInAccountFromIntent(com.google.android.gms:play-services-auth@@18.1.0:9)
at com.codetrixstudio.capacitor.GoogleAuth.GoogleAuth.handleOnActivityResult(GoogleAuth.java:70)
at com.getcapacitor.Bridge.onActivityResult(Bridge.java:776)
at com.getcapacitor.BridgeActivity.onActivityResult(BridgeActivity.java:214)
at android.app.Activity.dispatchActivityResult(Activity.java:7598)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4451)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4500)
at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:49)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1839)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:201)
at android.app.ActivityThread.main(ActivityThread.java:6861)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
2020-10-05 21:21:36.377 29147-29147/com.paul.testapp D/Capacitor: Sending plugin error: {"save":false,"callbackId":"11496723","pluginId":"GoogleAuth","methodName":"signIn","success":false,"error":{"message":"Something went wrong"}}
Now I came across #15 , which indicated that the use of web tokens could solve the issue. This made me set up a VPN on my phone to translate hotspotdev.me to my development PC’s IP. I also created a new web token:
and edited capacitor.config.json:
"server": {
"url": "http://hotspotdev.me:8080"
},
I replaced the ID in the head
HTML tag by the web client I just generated, with the same outcome.
I’m fairly new to mobile development, and may have missed something obvious. Please let me know if I wrongly configured anything.
I appreciate each one of your answers, of course please let me know if you need any additional information.
Thank you very much!
Issue Analytics
- State:
- Created 3 years ago
- Comments:7 (3 by maintainers)
Top GitHub Comments
This problem is really frustrating. Things I’ve done:
It works on iOS but still got Exception code 10 on Android.
EDIT: Finally I solved this by building apk using generate signed apk (on Android Studio 4.0.1, Build -> Generate Signed Bundle / APK -> APK), I usually build apk without signing unless I want to release it to play store.
Thank you for your answer. I finally got it working after using the Web Client ID on the 3 places the token is needed:
I’m fairly sure people would be happy to have this detail on the README.
I also set “forceCodeForRefreshToken” to true and false, both worked.
I also used the code you provided for the possible fix, without the semicolon you left over!