capacitor-native-google-one-tap-signin 0.0.21 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,12 +8,14 @@ Currently the idToken, id (e-mail), displayName, givenName, familyName, profileP
8
8
 
9
9
  The user is automatically signed-in, without a prompt after the first sign-in.
10
10
 
11
+ API version 29 or higher seems to be required for one-tap sign-in to work.
12
+
11
13
 
12
14
  # Demos
13
15
  See the `demo` folder.
14
16
 
15
17
  # Setup
16
- You need to provide the plug-in a client ID of type "Web application". However you will also need to create a client ID of type "Android" as stated in the [One Tap Get started docu](https://developers.google.cn/identity/one-tap/android/get-started).
18
+ You need to provide the plug-in a client ID of type "Web application". However you will also need to create a client ID of type "Android" as stated in the [One Tap Get started docu](https://developers.google.cn/identity/one-tap/android/get-started) in the [Google Cloud Console](https://console.cloud.google.com/apis/dashboard).
17
19
 
18
20
  To test it using an emulator, you need to create an emulator with android play services. See [my stackoverflow answer](https://stackoverflow.com/questions/71325279/missing-featurename-auth-api-credentials-begin-sign-in-version-6/75285717#75285717).
19
21
 
Binary file
@@ -14,7 +14,7 @@ apply plugin: 'com.android.library'
14
14
  android {
15
15
  compileSdkVersion 31
16
16
  defaultConfig {
17
- minSdkVersion 22
17
+ minSdkVersion 29
18
18
  targetSdkVersion 31
19
19
  versionCode 1
20
20
  versionName "1.0"
@@ -44,10 +44,12 @@ repositories {
44
44
  dependencies {
45
45
  implementation fileTree(dir: 'libs', include: ['*.jar'])
46
46
  implementation project(':capacitor-android')
47
- implementation 'androidx.appcompat:appcompat:1.2.0'
47
+ implementation 'androidx.appcompat:appcompat:1.4.2'
48
48
  testImplementation 'junit:junit:4.13'
49
49
  androidTestImplementation 'com.android.support.test:runner:1.0.2'
50
50
  androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
51
51
  implementation 'com.google.android.gms:play-services-auth:20.4.1'
52
+ implementation 'com.google.android.gms:play-services-tasks:18.0.2'
53
+ implementation 'com.google.android.gms:play-services-base:18.0.1'
52
54
  }
53
55
 
@@ -1,6 +1,7 @@
1
1
  package com.proventask.capacitor.GoogleOneTapAuth;
2
2
 
3
3
  import android.app.Activity;
4
+ import android.content.Context;
4
5
  import android.content.Intent;
5
6
  import android.util.Log;
6
7
 
@@ -8,53 +9,42 @@ import androidx.activity.result.ActivityResult;
8
9
  import androidx.activity.result.ActivityResultLauncher;
9
10
  import androidx.activity.result.IntentSenderRequest;
10
11
  import androidx.activity.result.contract.ActivityResultContracts;
11
- import androidx.annotation.NonNull;
12
12
 
13
13
  import com.getcapacitor.JSObject;
14
14
  import com.getcapacitor.Plugin;
15
15
  import com.getcapacitor.PluginCall;
16
16
  import com.getcapacitor.PluginMethod;
17
17
  import com.getcapacitor.annotation.CapacitorPlugin;
18
- import com.google.android.gms.auth.api.credentials.Credentials;
19
- import com.google.android.gms.auth.api.credentials.CredentialsClient;
18
+
20
19
  import com.google.android.gms.auth.api.identity.BeginSignInRequest;
21
- import com.google.android.gms.auth.api.identity.BeginSignInResult;
22
20
  import com.google.android.gms.auth.api.identity.Identity;
23
21
  import com.google.android.gms.auth.api.identity.SignInClient;
24
- import com.google.android.gms.auth.api.signin.GoogleSignIn;
25
- import com.google.android.gms.auth.api.signin.GoogleSignInClient;
26
- import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
22
+ import com.google.android.gms.common.ConnectionResult;
23
+ import com.google.android.gms.common.GoogleApiAvailability;
27
24
  import com.google.android.gms.common.api.ApiException;
28
- import com.google.android.gms.tasks.OnCompleteListener;
29
- import com.google.android.gms.tasks.Task;
30
25
 
31
26
  @CapacitorPlugin()
32
27
  public class GoogleOneTapAuth extends Plugin {
33
28
  private static final String TAG = "GoogleOneTapAuth Plugin";
34
-
35
29
  private String androidClientId;
36
30
  private SignInClient oneTapClient;
37
- private CredentialsClient mCredentialsClient;
38
- private GoogleSignInClient mSignInClient;
39
31
  private PluginCall currentPluginCall = null;
40
32
  private ActivityResultLauncher<IntentSenderRequest> googleOneTapSignInActivityResultHandlerIntentSenderRequest;
41
- private boolean isSignInInProgress = false;
33
+
42
34
 
43
35
  @Override
44
36
  public void load() {
45
37
  androidClientId = getConfig().getString("androidClientId");
46
38
 
47
39
  if (androidClientId == null || androidClientId.endsWith("apps.googleusercontent.com") == false) {
48
- throw new RuntimeException("androidClientId must end with 'apps.googleusercontent.com' but is: " + androidClientId);
40
+ throw new RuntimeException("androidClientId must end with 'apps.googleusercontent.com' but is: " + androidClientId + ". Check capacitor.config.ts.");
49
41
  }
50
42
 
51
43
  oneTapClient = Identity.getSignInClient(this.getActivity());
52
- mCredentialsClient = Credentials.getClient(this.getContext());
53
- // DEFAULT_SIGN_IN scopes are id and profile, see GoogleSignInOptions
54
- var gsoBuilder = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
55
- .requestIdToken(androidClientId);
56
- mSignInClient = GoogleSignIn.getClient(this.getContext(), gsoBuilder.build());
44
+ RegisterSignInResultHandler();
45
+ }
57
46
 
47
+ private void RegisterSignInResultHandler() {
58
48
  googleOneTapSignInActivityResultHandlerIntentSenderRequest = bridge.registerForActivityResult(
59
49
  new ActivityResultContracts.StartIntentSenderForResult(),
60
50
  result -> {
@@ -81,24 +71,54 @@ public class GoogleOneTapAuth extends Plugin {
81
71
  } else {
82
72
  currentPluginCall.reject(resultCodeString, pluginResult);
83
73
  }
84
- isSignInInProgress = false;
85
74
  });
86
75
  }
87
76
 
88
77
  @PluginMethod()
89
78
  public void signIn(PluginCall call) {
90
- if (!isSignInInProgress) {
91
- isSignInInProgress = true;
92
- currentPluginCall = call;
93
- beginSignIn(true);
94
- }
79
+ currentPluginCall = call;
80
+ beginSignIn(true);
81
+ }
82
+
83
+ // This method is called first with tryAutoLogin=true and if not successful then with tryAutoLogin=false.
84
+ private void beginSignIn(boolean tryAutoLogin) {
85
+ var context = this.getContext();
86
+ var beginSignInRequest = createBeginSignInRequest(tryAutoLogin);
87
+
88
+ oneTapClient.beginSignIn(beginSignInRequest)
89
+ .addOnCompleteListener(task -> {
90
+ if (task.isSuccessful()) {
91
+ var result = task.getResult();
92
+ var intentSender = result.getPendingIntent().getIntentSender();
93
+ var intentSenderRequest = new IntentSenderRequest.Builder(intentSender).build();
94
+ googleOneTapSignInActivityResultHandlerIntentSenderRequest.launch(intentSenderRequest);
95
+ } else {
96
+ if (tryAutoLogin) {
97
+ beginSignIn(false);
98
+ } else {
99
+ Log.e(TAG, "beginSignIn failed", task.getException());
100
+ var errorMessage = task.getException().toString();
101
+
102
+ if (!isGooglePlayServicesAvailable(context)) {
103
+ errorMessage += "\nGooglePlayService is not installed or must be updated.";
104
+ }
105
+ if (errorMessage.contains("Missing Feature{name=auth_api_credentials_begin_sign_in")) {
106
+ errorMessage += "\nGooglePlay is not installed or must be logged in to setup.";
107
+ }
108
+ if (errorMessage.contains("ApiException: 8")) {
109
+ errorMessage += "\nOne reason for the exception is when the device has no internet.";
110
+ }
111
+ currentPluginCall.reject(errorMessage);
112
+ }
113
+ }
114
+ });
95
115
  }
96
116
 
97
117
  private BeginSignInRequest createBeginSignInRequest(boolean tryAutoLogin) {
98
118
  return BeginSignInRequest.builder()
99
119
  .setGoogleIdTokenRequestOptions(BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
100
120
  .setSupported(true)
101
- // Your server's client ID, not your Android client ID.
121
+ // A OAuth client ID with application type "Web application".
102
122
  .setServerClientId(androidClientId)
103
123
  // If true, only the Google accounts that the user has authorized before will show up in the credential list. This can
104
124
  // help prevent a new account being created when the user has an existing account registered with the application.
@@ -109,48 +129,21 @@ public class GoogleOneTapAuth extends Plugin {
109
129
  .build();
110
130
  }
111
131
 
112
- private void beginSignIn(boolean tryAutoLogin) {
113
- var beginSignInRequest = createBeginSignInRequest(tryAutoLogin);
114
-
115
- oneTapClient.beginSignIn(beginSignInRequest)
116
- .addOnCompleteListener(new OnCompleteListener<BeginSignInResult>() {
117
- @Override
118
- public void onComplete(@NonNull Task<BeginSignInResult> task) {
119
- if (task.isSuccessful()) {
120
- var result = task.getResult();
121
- var intentSender = result.getPendingIntent().getIntentSender();
122
- var intentSenderRequest = new IntentSenderRequest.Builder(intentSender).build();
123
- googleOneTapSignInActivityResultHandlerIntentSenderRequest.launch(intentSenderRequest);
124
- } else {
125
- if (tryAutoLogin) {
126
- beginSignIn(false);
127
- }
128
- else {
129
- Log.e(TAG, "beginSignIn failed", task.getException());
130
- var errorMessage = task.getException().toString();
131
- if (errorMessage.contains("ApiException: 8")) {
132
- errorMessage += "\nOne reason for the exception is when the device has no internet.";
133
- }
134
- currentPluginCall.reject(errorMessage);
135
- isSignInInProgress = false;
136
- }
137
- }
138
- }
139
- });
132
+ private boolean isGooglePlayServicesAvailable(Context context) {
133
+ var googleApiAvailability = GoogleApiAvailability.getInstance();
134
+ int resultCode = googleApiAvailability.isGooglePlayServicesAvailable(context);
135
+ return resultCode == ConnectionResult.SUCCESS;
140
136
  }
141
137
 
142
138
  @PluginMethod()
143
139
  public void signOut(final PluginCall call) {
144
140
  oneTapClient.signOut()
145
- .addOnCompleteListener(new OnCompleteListener<Void>() {
146
- @Override
147
- public void onComplete(@NonNull Task<Void> task) {
148
- if (task.isSuccessful()) {
149
- call.resolve(null);
150
- } else {
151
- Log.e(TAG, "signOut failed", task.getException());
152
- call.reject(task.getException().toString());
153
- }
141
+ .addOnCompleteListener(task -> {
142
+ if (task.isSuccessful()) {
143
+ call.resolve(null);
144
+ } else {
145
+ Log.e(TAG, "signOut failed", task.getException());
146
+ call.reject(task.getException().toString());
154
147
  }
155
148
  });
156
149
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capacitor-native-google-one-tap-signin",
3
- "version": "0.0.21",
3
+ "version": "0.1.0",
4
4
  "description": "Google One Tap sign-in plugin for capacitor.",
5
5
  "main": "dist/esm/index.js",
6
6
  "types": "dist/esm/index.d.ts",
@@ -14,15 +14,15 @@
14
14
  "author": "David Neuy",
15
15
  "license": "MIT",
16
16
  "devDependencies": {
17
- "@capacitor/android": "^4.0.1",
18
- "@capacitor/cli": "^4.0.1",
19
- "@capacitor/core": "^4.0.1",
20
- "@capacitor/ios": "^4.0.1",
17
+ "@capacitor/android": "^4.6.2",
18
+ "@capacitor/cli": "^4.6.2",
19
+ "@capacitor/core": "^4.6.2",
20
+ "@capacitor/ios": "^4.6.2",
21
21
  "@ionic/prettier-config": "^2.0.0",
22
- "@types/gapi": "0.0.42",
23
- "@types/gapi.auth2": "0.0.56",
24
- "prettier": "^2.7.1",
25
- "typescript": "^4.7.4"
22
+ "@types/gapi": "^0.0.44",
23
+ "@types/gapi.auth2": "^0.0.57",
24
+ "prettier": "^2.8.3",
25
+ "typescript": "^4.9.5"
26
26
  },
27
27
  "peerDependencies": {
28
28
  "@capacitor/core": "^4"