13

के साथ टोकन पुनर्प्राप्त करने के लिए साइलेंट साइन इन मैं अपने ऐप में "Google साइन-इन" का उपयोग कर रहा हूं। इसलिए मैं उपयोगकर्ता बैकएंड के लिए आवश्यक उपयोगकर्ता ईमेल और आईडी टोकन प्राप्त करने के लिए GoogleApiClient क्लास का उपयोग करता हूं।GoogleApiClient

जब में उपयोगकर्ता के प्रवेश, तो मैं (बेशक) एक गतिविधि के लिए उपयोग किया है और मुझे लगता है कि गतिविधि का उपयोग GoogleApiClient बुला builder.enableAutoManage द्वारा यूआई जीवन चक्र सामान संभाल जाने के लिए (myActivity, ...)

यह ठीक काम करता है।

हालांकि, बाद के चरण में (कई दिनों बाद), मुझे एक नया टोकन प्राप्त करने की आवश्यकता है (किसी कारण से कि मैं यहां और नहीं जाऊंगा)। मैं इस टोकन चुपचाप उपयोगकर्ता इंटरैक्शन के बिना प्राप्त करना चाहता हूं। हालांकि, मेरे कोड में उस बिंदु पर जहां मुझे इस नए टोकन की आवश्यकता है, मेरे पास किसी भी गतिविधि उदाहरण तक पहुंच नहीं है। इसका मतलब है कि मैं ऊपर उल्लिखित कॉल बनाने के लिए सक्षम नहीं हूं यानी "builder.enableAutoManage"। और मैंने पाया है कि अगर मैं इतना कॉल नहीं करता हूं, तो चुप लॉगिन काम नहीं कर रहा है।

मैंने नीचे दिए गए कोड को संलग्न किया है। अब, "silentLogin" विधि में एक नज़र डालें। जब तक उपयोगकर्ता के रूप में मुझे प्राप्त टोकन वास्तविक साइन इन करता है, तो एक घंटे से भी छोटा होता है, फिर "लंबितResult.isDone" कथन सत्य वापस आ जाएगा और कैश किए गए टोकन प्राप्त किए जा सकते हैं। हालांकि, यदि उपयोगकर्ता के रूप में मुझे प्राप्त टोकन वास्तविक साइन इन करता है, तो एक घंटे से अधिक पुराना होता है, फिर "लंबितResult.setResultCallback" कॉल किया जाता है लेकिन "ऑनसेट" विधि को कभी भी कॉल नहीं किया जाता है और मुझे नया नहीं मिल सकता टोकन। यह समस्या तब नहीं होती है जब मैं एक गतिविधि से बिल्कुल वही करता हूं (और इसके द्वारा "builder.enableAutoManage" कॉल भी करें)।

तो, क्या कोई जानता है कि मैं क्या गलत कर रहा हूं और अधिक महत्वपूर्ण बात यह है कि इस समस्या को हल करने के लिए और एक गतिविधि उदाहरण तक पहुंच के बिना एक नया टोकन प्राप्त करें?

मैं com.google.android.gms उपयोग कर रहा हूँ: खेलने-सेवाओं लेखन: 8.4.0

package com.google.samples.quickstart.signin; 

import android.content.Context; 
import android.os.Bundle; 
import android.util.Log; 

import com.google.android.gms.auth.api.Auth; 
import com.google.android.gms.auth.api.signin.GoogleSignInAccount; 
import com.google.android.gms.auth.api.signin.GoogleSignInOptions; 
import com.google.android.gms.auth.api.signin.GoogleSignInResult; 
import com.google.android.gms.common.ConnectionResult; 
import com.google.android.gms.common.Scopes; 
import com.google.android.gms.common.api.GoogleApiClient; 
import com.google.android.gms.common.api.OptionalPendingResult; 
import com.google.android.gms.common.api.ResultCallback; 
import com.google.android.gms.common.api.Scope; 

/** 
* Use this class to login with google account using the OpenId oauth method. 
*/ 
public class GoogleLoginStackOverflow { 
    private static final String TAG = GoogleLoginIdToken.class.getName(); 
    private static final String SERVER_CLIENT_ID = "XXXXXXXXXXXXXXXXXXXXXXXX.apps.googleusercontent.com"; 

    private GoogleApiClient mGoogleApiClient; 
    private Context mContext; 

    private GoogleLoginStackOverflow(Context appContext) { 
     this.mContext = appContext; 
     createGoogleClient(); 
    } 

    /** 
    * Performs a silent sign in and fetch a token. 
    * 
    * @param appContext Application context 
    */ 
    public static void silentLogin(Context appContext) { 
     GoogleLoginStackOverflow googleLoginIdToken = new GoogleLoginStackOverflow(appContext); 
     googleLoginIdToken.silentLogin(); 
    } 

    private void createGoogleClient() { 
     GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) 
       .requestProfile() 
       .requestScopes(new Scope(Scopes.PROFILE)) 
       .requestIdToken(SERVER_CLIENT_ID) 
       .requestEmail() 
       .build(); 

     mGoogleApiClient = new GoogleApiClient.Builder(mContext) 
       .addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() { 
        @Override 
        public void onConnectionFailed(ConnectionResult connectionResult) { 
         System.out.println("onConnectionFailed = " + connectionResult); 
         onSilentLoginFinished(null); 
        } 
       }) 
       .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() { 
        @Override 
        public void onConnected(Bundle bundle) { 
         System.out.println("onConnected bundle = " + bundle); 
         onSilentLoginFinished(null); 
        } 

        @Override 
        public void onConnectionSuspended(int i) { 
         System.out.println("onConnectionSuspended i = " + i); 
         onSilentLoginFinished(null); 
        } 
       }).addApi(Auth.GOOGLE_SIGN_IN_API, gso) 
       .build(); 
    } 

    private void silentLogin() { 
     OptionalPendingResult<GoogleSignInResult> pendingResult = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient); 
     if (pendingResult != null) { 
      if (pendingResult.isDone()) { 
       // If the user's cached credentials are valid, the OptionalPendingResult will be "done" 
       // and the GoogleSignInResult will be available instantly. 
       Log.d(TAG, " ---------------- CACHED SIGN-IN ------------"); 
       System.out.println("pendingResult is done = "); 
       GoogleSignInResult signInResult = pendingResult.get(); 
       onSilentLoginFinished(signInResult); 
      } else { 
       System.out.println("Setting result callback"); 
       // If the user has not previously signed in on this device or the sign-in has expired, 
       // this asynchronous branch will attempt to sign in the user silently. Cross-device 
       // single sign-on will occur in this branch. 
       pendingResult.setResultCallback(new ResultCallback<GoogleSignInResult>() { 
        @Override 
        public void onResult(GoogleSignInResult googleSignInResult) { 
         System.out.println("googleSignInResult = " + googleSignInResult); 
         onSilentLoginFinished(googleSignInResult); 
        } 
       }); 
      } 
     } else { 
      onSilentLoginFinished(null); 
     } 
    } 

    private void onSilentLoginFinished(GoogleSignInResult signInResult) { 
     System.out.println("GoogleLoginIdToken.onSilentLoginFinished"); 
     if (signInResult != null) { 
      GoogleSignInAccount signInAccount = signInResult.getSignInAccount(); 
      if (signInAccount != null) { 
       String emailAddress = signInAccount.getEmail(); 
       String token = signInAccount.getIdToken(); 
       System.out.println("token = " + token); 
       System.out.println("emailAddress = " + emailAddress); 
      } 
     } 
    } 
} 
+0

जब आप टोकन कहते हैं, तो मैं पूछ सकता हूं कि किस तरह का टोकन? – zIronManBox

+0

Google एपीआई से जो टोकन मैं चाहता हूं वह एक आईडी टोकन है (मुझे लगता है कि यह एकमात्र टोकन प्रकार है जिसे आप GoogleSignInAccount.getIdToken() पर कॉल करके प्राप्त कर सकते हैं) –

उत्तर

8

मैं इस समस्या पाया। मैं धारणा है कि समारोह

OptionalPendingResult<GoogleSignInResult> pendingResult = Auth.GoogleSignInApi.silentSignIn(googleApiClient); 

मेरे लिए mGoogleApiClient कनेक्ट करने के लिए (क्योंकि यह एक लंबित परिणाम देता है) जा रहा था के तहत किया गया। हालांकि, यह मामला और ऊपर मैं सिर्फ silentLogin विधि की शुरुआत में कॉल

ConnectionResult result = mGoogleApiClient.blockingConnect(); 

जोड़ने के लिए की जरूरत को सुलझाने के लिये नहीं था। , (और फिर निश्चित रूप से बाद में डिस्कनेक्ट करें, और यह भी सुनिश्चित करें कॉल एक धागा मुख्य थ्रेड से अलग किया जाता है बनाने के)

टाडा '

22

हाँ ऊपर का जवाब सही है। आम तौर पर, किसी भी GoogleApiClient को किसी भी डेटा को वापस करने से पहले कनेक्ट होने की आवश्यकता होती है। enableAutoManage आपको ऑनस्टार्ट()/onStop() के दौरान स्वचालित रूप से कनेक्ट()/डिस्कनेक्ट() को कॉल करने में मदद करता है। यदि आप ऑटोमैनेज का उपयोग नहीं करते हैं, तो आपको मैन्युअल रूप से कनेक्ट() को कनेक्ट करने की आवश्यकता होगी।

और इससे भी बेहतर, आपको अंत में ब्लॉक में डिस्कनेक्ट करना चाहिए।

मान लीजिए कि आप यूआई थ्रेड पर नहीं हैं।

try { 
    ConnectionResult result = mGoogleApiClient.blockingConnect(); 
    if (result.isSuccess()) { 
     GoogleSignInResult googleSignInResult = 
      Auth.GoogleSignInApi.silentSignIn(googleApiClient).await(); 
    ... 
    } 
} finally { 
    mGoogleApiClient.disconnect(); 
} 

और यह भी, अपने कोड थोड़ा साफ करने के लिए: 1।जीएसओ विन्यास के नीचे से बनाया ऊपर अपने चिपकाया कोड के समान है:

GoogleSignInOptions gso = 
    new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) 
     .requestIdToken(SERVER_CLIENT_ID) 
     .requestEmail() 
     .build(); 
  1. अपने वर्तमान तर्क के आधार पर, addOnConnectionFailedListener/addConnectionCallbacks एडीबी लॉग अलावा अन्य मदद नहीं करता है। शायद उन्हें पूरी तरह से हटा दें?
+0

आपके उत्तर के लिए इसाबेला धन्यवाद! –

+3

Google प्रलेखन हमेशा शानदार रूप से विफल रहता है। यह बिल्कुल अस्पष्ट है अगर apiClient.connect को एक प्रयास किए गए साइनइन से पहले या बाद में बुलाया जाना चाहिए। वास्तव में, मुझे लगता है कि गायन और कनेक्शन के विभाजन के नए मॉडल ने जटिलता में वृद्धि की है, इसे कम नहीं किया है। किसी भी दर पर, उत्तर के लिए इसाबेला धन्यवाद, इससे मुझे भी मदद मिली है! – Creos

+0

मुझे लगता है कि यह कहना एक सुंदर बोल्ड स्टेटमेंट है कि Google दस्तावेज़ हमेशा शानदार रूप से विफल रहता है। – rupps

संबंधित मुद्दे