2016-03-27 10 views
5

Il mio gioco utilizza Google Play Games e Firebase (per il sistema di classifiche, perché sfortunatamente non è possibile ridurre il punteggio in Google Classifiche).Google Play Games, Firebase e il nuovo accesso a Google

In passato ho usato il modo deprecato per l'iscrizione per la Firebase via Plus.AccountApi.getAccountName e gli amici ...

Così ho provato a convertire il nuovo Google Sign-in, ma a quanto pare non può essere utilizzato in combinazione con Google Play Games:

Auth.GOOGLE_SIGN_IN_API cannot be used with Games.API 

tutto il mio obiettivo era/è quello di sbarazzarsi di Google+ dipendenza (come Google Play Games non richiede lo più) e il permesso GET_ACCOUNTS.

Come posso accedere a Firebase senza Google+ e GET_ACCOUNTS e senza il nuovo accesso a Google? Posso? Forse la creazione di due GoogleApiClients separati sarebbe una soluzione?

+0

Senza vedere il codice minimo per riprodurre il problema, sarà impossibile dire il motivo per cui non funziona. Vedi [MCVE] (http://stackoverflow.com/help/mcve). –

risposta

2

Bene, ho semplicemente finito con la creazione di due GoogleApiClients separati: uno per Google Play Games e un altro per Firebase (utilizzando il nuovo accesso Google). Non vedo alcun problema con questo approccio e mi sono liberato della dipendenza da Google+ & dell'autorizzazione GET_ACCOUNTS.

+0

Sto affrontando un problema simile. Mi piacerebbe saperne di più dettagli dal tuo caso d'uso. Come si eseguono in sequenza le due chiamate connect()? (Suppongo tu debba fare due chiamate di connessione separate) – dlmt

+0

Con 2 client API separati, come prevedi il problema di scegliere un account google o account di giochi diverso se l'utente ha più account sul suo dispositivo? Potrei facilmente vedere uno scenario in cui i due non corrispondono. – Moritz

1

Per utilizzare Google Play Games Api con Firebase attenersi alla seguente procedura:

*** Nota: getGamesServerAuthCode è il metodo consigliato da Google; anche se è deprezzato. Potrebbero aver dimenticato di rimuovere l'annotazione di deprecazione al momento del rilascio al pubblico.

Passaggio 1: Dopo aver effettuato l'accesso; ottenere il codice di autorizzazione. Ad esempio, è possibile utilizzare onSignInSucceeded(). Assicurati che il client API sia connesso.

Games.getGamesServerAuthCode(gameHelper.getApiClient(), [web_client_id]).setResultCallback(new ResultCallback<Games.GetServerAuthCodeResult>() { 
      @Override 
      public void onResult(@NonNull Games.GetServerAuthCodeResult result) { 
       if (result.getStatus().isSuccess()) { 
        String authCode = result.getCode(); 
        exchangeAuthCodeForToken(authCode); 
       } 
      } 
     }); 

Passaggio 2: scambiare il codice di autorizzazione per un token.

class AuthToken { 
    String access_token; 
    String token_type; 
    int expires_in; 
    String id_token; 
} 

void exchangeAuthCodeForToken(final String authCode) { 
    AsyncTask<Void, Void, AuthToken> task = new AsyncTask<Void, Void, AuthToken>() { 
     @Override 
     protected AuthToken doInBackground(Void... voids) { 
      try { 
       URL url = new URL("https://www.googleapis.com/oauth2/v4/token"); 
       Map<String, Object> params = new LinkedHashMap<>(); 
       params.put("code", authCode); 
       params.put("client_id", "[web_client_id]"); 
       params.put("client_secret", "[secret]"); 
       params.put("redirect_uri", "[redirect_uri]"); 
       params.put("grant_type", "authorization_code"); 

       StringBuilder postData = new StringBuilder(); 
       for (Map.Entry<String, Object> param : params.entrySet()) { 
        if (postData.length() != 0) postData.append('&'); 
        postData.append(URLEncoder.encode(param.getKey(), "UTF-8")); 
        postData.append('='); 
        postData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8")); 
       } 
       byte[] postDataBytes = postData.toString().getBytes("UTF-8"); 

       HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 
       conn.setRequestMethod("POST"); 
       conn.setRequestProperty("Host", "www.googleapis.com"); 
       conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 
       conn.setDoOutput(true); 
       conn.getOutputStream().write(postDataBytes); 

       int responseCode = conn.getResponseCode(); 
       if (responseCode == HttpsURLConnection.HTTP_OK) { 
        Reader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); 

        // Build the string 
        StringBuilder sb = new StringBuilder(); 
        for (int c; (c = in.read()) >= 0;) { 
         sb.append((char) c); 
        } 

        // Convert JSON to a Java Object 
        GsonBuilder builder = new GsonBuilder(); 
        Gson gson = builder.create(); 
        AuthToken token = gson.fromJson(sb.toString(), AuthToken.class); 

        // Disconnect 
        conn.disconnect(); 

        return token; 
       } 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
      return null; 
     } 

     @Override 
     protected void onPostExecute(AuthToken token) { 
      // Authorize Firebase with Games API 
      firebaseAuthWithGamesApi(token.id_token); 
     } 

    }.execute(); 
} 

Passaggio 3: utilizzare il codice di autorizzazione per accedere con Firebase.

private void firebaseAuthWithGamesApi(String authToken) { 
     AuthCredential credential = GoogleAuthProvider.getCredential(authToken, null); 
     mAuth.signInWithCredential(credential) 
       .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() { 
        @Override 
        public void onComplete(@NonNull Task<AuthResult> task) { 
         Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful()); 

         // If sign in fails, display a message to the user. If sign in succeeds 
         // the auth state listener will be notified and logic to handle the 
         // signed in user can be handled in the listener. 
         if (!task.isSuccessful()) { 
          Log.w(TAG, "signInWithCredential", task.getException()); 
         } 
        } 
       }); 
    } 
+0

Può essere una soluzione, ma 'Games.getGamesServerAuthCode' è deprecato e la prossima richiesta di rete restituisce informazioni token senza' id_token' che è necessario per ottenere 'AuthCredential' che dobbiamo accedere alla Firebase – mohax

+0

Ho sentito da alcuni articoli che era contrassegnato come deprezzato e che si sono dimenticati di rimuoverlo. Non sono sicuro però. Sono sicuro che stanno lavorando alla sua sostituzione. Ma, devo ancora vederlo. –

+0

E che ne dite di 'id_token' mancante? Provo qualche risposta da qui ma non riesco a ottenere questo campo in risposta (Ony 'acces_token' viene restituito e quando provo a passarlo a GoogleAuthProvider.getCredential fallisce con il messaggio che non può riconoscere' id_token' qui – mohax