2016-03-19 25 views
40

tutto va bene, se vai una seconda volta questo frammento riceve un errore. Ho provato a mettere null se view, ma non cambia nulla. Codice:Gestisci già un GoogleApiClient con id 0 In FRAGMENT

public class Login extends Fragment implements 
     GoogleApiClient.OnConnectionFailedListener, 
     View.OnClickListener { 

    private static final String TAG = "SignInActivity"; 
    private static final int RC_SIGN_IN = 9001; 

    private GoogleApiClient mGoogleApiClient; 
    private TextView mStatusTextView; 
    private ProgressDialog mProgressDialog; 


    private static String url; 

    private static View view; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 

     if (view != null) { 
      ViewGroup parent = (ViewGroup) view.getParent(); 
      if (parent != null) 
       parent.removeView(view); 
     } 
     try { 
      view = inflater.inflate(R.layout.activity_login, container, false); 

      // Views 
      mStatusTextView = (TextView) view.findViewById(R.id.status); 

      // Button listeners 
      view.findViewById(R.id.sign_in_button).setOnClickListener(this); 
      view.findViewById(R.id.sign_out_button).setOnClickListener(this); 
      view.findViewById(R.id.disconnect_button).setOnClickListener(this); 

      // [START configure_signin] 
      // Configure sign-in to request the user's ID, email address, and basic 
      // profile. ID and basic profile are included in DEFAULT_SIGN_IN. 
      GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) 
        .requestEmail() 
        .build(); 
      // [END configure_signin] 

      // [START build_client] 
      // Build a GoogleApiClient with access to the Google Sign-In API and the 
      // options specified by gso. 
      mGoogleApiClient = new GoogleApiClient.Builder(getActivity()) 
        .enableAutoManage(getActivity()/* FragmentActivity */, this /* OnConnectionFailedListener */) 
        .addApi(Auth.GOOGLE_SIGN_IN_API, gso) 
        .build(); 
      // [END build_client] 

      // [START customize_button] 
      // Customize sign-in button. The sign-in button can be displayed in 
      // multiple sizes and color schemes. It can also be contextually 
      // rendered based on the requested scopes. For example. a red button may 
      // be displayed when Google+ scopes are requested, but a white button 
      // may be displayed when only basic profile is requested. Try adding the 
      // Scopes.PLUS_LOGIN scope to the GoogleSignInOptions to see the 
      // difference. 
      SignInButton signInButton = (SignInButton) view.findViewById(R.id.sign_in_button); 
      signInButton.setSize(SignInButton.SIZE_STANDARD); 
      signInButton.setScopes(gso.getScopeArray()); 
      // [END customize_button] 
     } catch (InflateException e) { 
     /* map is already there, just return view as it is */ 
     } 
     super.onCreate(savedInstanceState); 



     return view; 
    } 



    @Override 
    public void onStart() { 
     super.onStart(); 

     OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient); 
     if (opr.isDone()) { 
      // If the user's cached credentials are valid, the OptionalPendingResult will be "done" 
      // and the GoogleSignInResult will be available instantly. 
      Log.d(TAG, "Got cached sign-in"); 
      GoogleSignInResult result = opr.get(); 
      handleSignInResult(result); 
     } else { 
      // 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. 
      showProgressDialog(); 
      opr.setResultCallback(new ResultCallback<GoogleSignInResult>() { 
       @Override 
       public void onResult(GoogleSignInResult googleSignInResult) { 
        //adaugat de mine sa porneacsa singur cererea de logare 
        signIn(); 
        //fin 
        hideProgressDialog(); 
        handleSignInResult(googleSignInResult); 
       } 
      }); 
     } 
    } 

    // [START onActivityResult] 
    @Override 
    public void onActivityResult(int requestCode, int resultCode, Intent data) { 
     super.onActivityResult(requestCode, resultCode, data); 

     // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...); 
     if (requestCode == RC_SIGN_IN) { 
      GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data); 
      handleSignInResult(result); 
     } 
    } 
    // [END onActivityResult] 

    // [START handleSignInResult] 
    private void handleSignInResult(GoogleSignInResult result) { 
     Log.d(TAG, "handleSignInResult:" + result.isSuccess()); 
     if (result.isSuccess()) { 
      // Signed in successfully, show authenticated UI. 
      GoogleSignInAccount acct = result.getSignInAccount(); 
      mStatusTextView.setText(getString(R.string.signed_in_fmt, acct.getDisplayName() + " Your token " + acct.getId())); 

      url = "http://grupovrt.ddns.net:81/index.php?token="+acct.getId(); 





      updateUI(true); 
     } else { 
      // Signed out, show unauthenticated UI. 
      updateUI(false); 
     } 
    } 
    // [END handleSignInResult] 

    // [START signIn] 
    private void signIn() { 
     Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient); 
     startActivityForResult(signInIntent, RC_SIGN_IN); 
    } 
    // [END signIn] 

    // [START signOut] 
    private void signOut() { 
     Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
       new ResultCallback<Status>() { 
        @Override 
        public void onResult(Status status) { 
         // [START_EXCLUDE] 
         updateUI(false); 
         // [END_EXCLUDE] 
        } 
       }); 
    } 
    // [END signOut] 

    // [START revokeAccess] 
    private void revokeAccess() { 
     Auth.GoogleSignInApi.revokeAccess(mGoogleApiClient).setResultCallback(
       new ResultCallback<Status>() { 
        @Override 
        public void onResult(Status status) { 
         // [START_EXCLUDE] 
         updateUI(false); 
         // [END_EXCLUDE] 
        } 
       }); 
    } 
    // [END revokeAccess] 

    @Override 
    public void onConnectionFailed(ConnectionResult connectionResult) { 
     // An unresolvable error has occurred and Google APIs (including Sign-In) will not 
     // be available. 
     Log.d(TAG, "onConnectionFailed:" + connectionResult); 
    } 

    private void showProgressDialog() { 
     if (mProgressDialog == null) { 
      mProgressDialog = new ProgressDialog(getActivity()); 
      mProgressDialog.setMessage(getString(R.string.loading)); 
      mProgressDialog.setIndeterminate(true); 
     } 

     mProgressDialog.show(); 
    } 

    private void hideProgressDialog() { 
     if (mProgressDialog != null && mProgressDialog.isShowing()) { 
      mProgressDialog.hide(); 
     } 
    } 

    private void updateUI(boolean signedIn) { 
     if (signedIn) { 

      getView().findViewById(R.id.sign_in_button).setVisibility(View.GONE); 
      getView().findViewById(R.id.sign_out_and_disconnect).setVisibility(View.VISIBLE); 
     } else { 
      mStatusTextView.setText(R.string.signed_out); 

      getView().findViewById(R.id.sign_in_button).setVisibility(View.VISIBLE); 
      getView().findViewById(R.id.sign_out_and_disconnect).setVisibility(View.GONE); 
     } 
    } 

    @Override 
    public void onClick(View v) { 
     switch (v.getId()) { 
      case R.id.sign_in_button: 
       signIn(); 
       break; 
      case R.id.sign_out_button: 
       signOut(); 
       break; 
      case R.id.disconnect_button: 
       revokeAccess(); 
       break; 
     } 
    } 
} 

registro:

FATAL EXCEPTION: main 
                      Process: ro.vrt.videoplayerstreaming, PID: 23662 
                      java.lang.IllegalStateException: Already managing a GoogleApiClient with id 0 
                       at com.google.android.gms.common.internal.zzx.zza(Unknown Source) 
                       at com.google.android.gms.common.api.internal.zzw.zza(Unknown Source) 
                       at com.google.android.gms.common.api.GoogleApiClient$Builder.zza(Unknown Source) 
                       at com.google.android.gms.common.api.GoogleApiClient$Builder.zze(Unknown Source) 
                       at com.google.android.gms.common.api.GoogleApiClient$Builder.build(Unknown Source) 
                       at ro.vrt.videoplayerstreaming.Login.onCreateView(Login.java:75) 
                       at android.support.v4.app.Fragment.performCreateView(Fragment.java:1974) 
                       at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067) 
                       at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1252) 
                       at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738) 
                       at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617) 
                       at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:517) 
                       at android.os.Handler.handleCallback(Handler.java:739) 
                       at android.os.Handler.dispatchMessage(Handler.java:95) 
                       at android.os.Looper.loop(Looper.java:148) 
                       at android.app.ActivityThread.main(ActivityThread.java:5849) 
                       at java.lang.reflect.Method.invoke(Native Method) 
                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:763) 
                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:653) 

io se ho capito bene, il problema viene da qui

mGoogleApiClient = new GoogleApiClient.Builder(getActivity()) 
      .enableAutoManage(getActivity()/* FragmentActivity */, this /* OnConnectionFailedListener */) 
      .addApi(Auth.GOOGLE_SIGN_IN_API, gso) 
      .build(); 

ho cercato di mettere 0, ma ancora non funziona.

.enableAutoManage(getActivity(), 0 /* FragmentActivity */, this /* OnConnectionFailedListener */) 

Cosa posso fare? grazie.

+0

Sto affrontando lo stesso problema :( –

risposta

87

Si può provare a chiamare stopAutoManage() in onPuase() o qualsiasi altro evento del ciclo di vita del vostro frammento

@Override 
public void onPause() { 
    super.onPause(); 
    mGoogleClient.stopAutoManage(getActivity()); 
    mGoogleClient.disconnect(); 
} 
+0

Ha funzionato per me insieme con l'uso di 'revokeAccess'. (Y) – NarendraJi

+0

@MrNarendra in modo che hai usato' stopAutoManage() 'e' revokeAccess'? – Shruti

+0

di lavoro .. Grazie @ S_Madushan –

28

Si dovrebbe anche aggiungere la chiamata a stopAutoManage() in onPause() il metodo del frammento troppo:

@Override 
public void onPause() { 
    super.onPause(); 

    mGoogleApiClient.stopAutoManage(getActivity()); 
    mGoogleApiClient.disconnect(); 
} 
+6

In realtà @whaleswallace è corretto.La risposta accettata non riesce a risolvere il problema se si dispone di più di un frammento nella propria attività.Il metodo corretto consiste nell'aggiungere il metodo "onPause". – Ishaan

+2

Meglio usare onDestroyView(), onPause essere chiamato anche quando si visualizza la finestra di dialogo.Tutto tutto dipende dal requisito. Cheers !!! –

+0

Questa soluzione ha funzionato per me. Ma ho una domanda.Ho creato 'GoogleApiClient.Builder' dal metodo' onActivityCreated() 'di il frammento e quando goto un altro schermo, viene chiamato 'onPause' e' api client' è disconnesso. E quando riprendo, viene chiamato 'onActivityCreated'? – viper

-1

Prova a utilizzare il tuo mGoogleApiClient dalla tua attività. se hai dichiarato GoogleApiClient sulla tua attività, quindi non puoi ri-dichiarato sul tuo frammento. invece, il riutilizzo variabile che l'attività dal frammento

mGoogleApiClientInFragment = ((Youractivityclass)getActivity()).mGoogleApiClient; 

sostituire YouractivityClass con la vostra attività del frammento, e assicurarsi che impostare il vostro mGoogleApiClient campo nella vostra attività al pubblico

15

Per evitare ulteriori problema

@Override 
public void onStop() { 
    super.onStop(); 
    if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) { 
     mGoogleApiClient.stopAutoManage((Activity) context); 
     mGoogleApiClient.disconnect(); 
    } 
} 
+2

per evitare problemi di arresto anomalo, questa risposta dovrebbe essere adottata –

3

Il official doc for enableAutoManage dice questo:

In qualsiasi momento, è consentito un solo client gestito automaticamente per ID. Per riutilizzare un id è necessario prima chiamare stopAutoManage (FragmentActivity) sul client precedente.

Il codice utilizza la versione di enableAutoManage senza un parametro clientId, quindi è inadempiente a 0. Di seguito spiego perché si avrà più client auto-gestita per clientId 0, che è ciò che la documentazione di cui sopra è in guardia contro .

Dopo che il frammento di accesso è collegato a FragmentActivity, indica tale attività per iniziare a gestire una nuova istanza di GoogleApiClient. Ma cosa succede se FragmentActivity sta già gestendo un'altra istanza di GoogleApiClient? Questo è quando ottieni l'errore.

Ci sono alcuni possibili scenari che possono portare a questa situazione multiplo di GoogleApiClients-per-FragmentActivity.

  • FragmentActivity ha un altro frammento in aggiunta al Login che crea un GoogleApiClient e chiede anche a FragmentActivity di gestirlo.
  • FragmentActivity crea un oggetto GoogleApiClient e avvia la gestione prima che Frammento di accesso sia collegato a FragmentActivity.
  • Forse aggiungi il frammento di login in un FragmentTransaction e chiami addToBackStack. Quindi l'utente torna indietro, quindi in un secondo momento il frammento di accesso viene ricollegato. In questo caso, gli importanti chiamate di metodo Attività di accesso sono onCreateView -> onDestroyView -> onCreateView come illustrato di seguito:

    fragment lifecycle diagram

Questo è problematico perché la seconda chiamata a Login.onCreateView cerca di avere FragmentActivity gestire un secondo GoogleApiClient.

Se fossi in te, prenderei seriamente in considerazione la possibilità di creare GoogleApiClient nell'attività anziché in nessun frammento. Poi si potrebbe o fare il lavoro che richiede GoogleApiClient in attività, o continuare a farlo in Entrata Frammento dopo aver ottenuto la GoogleApiClient dall'attività in questo modo:

private GoogleApiClient googleApiClient; 

@Override 
void onAttach(Activity activity) { 
    super.onAttach(activity); 
    googleApiClient = activity.getGoogleApiClient(); 
} 

@Override 
void onDetach() { 
    super.onDetach(); 
    googleApiClient = null; 
} 
+0

O forse "creare" il GoogleApiClient su onCreate() anziché onCreateView? – pauminku

3

ho affrontato un problema simile, come avevo collocato login pulsante su due diversi frammenti appartenenti alla stessa attività.

Così inorder per risolvere questo problema, I assegnati diversi id per enableAutoManage durante la creazione del nuovo oggetto di GoogleApiClient.

Ad esempio, nel frammento 1, durante la creazione oggetto GoogleApiClient, assegnare 0 come è id:

mGoogleApiClient = new GoogleApiClient.Builder(getActivity()) 
        .enableAutoManage(getActivity(), 0, this /* OnConnectionFailedListener */) 
        .addApi(Auth.GOOGLE_SIGN_IN_API, gso) 
        .build(); 

In Frammento 2, durante la creazione oggetto GoogleApiClient, assegnare 1 come è id & così via:

mGoogleApiClient = new GoogleApiClient.Builder(getActivity()) 
        .enableAutoManage(getActivity(), 1, this /* OnConnectionFailedListener */) 
        .addApi(Auth.GOOGLE_SIGN_IN_API, gso) 
        .build(); 
0

io suggerisco di inizializzare il mGoogleApiClient su onCreate() invece spento su onCreateView().

onCreateView(), come indicato da @vlazzle può essere chiamato più volte in un singolo ciclo di vita activity.