2017-02-09 10 views
4

Я хочу интегрировать регистрацию Google с помощью фрагментов TagLayout ViewPager. ViewPager содержит два фрагмента: LoginFragment и RegistrationFragment, и оба содержат кнопку «Регистрация Google».Получение исключения «Только управление GoogleApiClient с id 0» при использовании TabLayout Viewpager

Проблема в том, что я получаю следующую ошибку при запуске.

java.lang.IllegalStateException: Уже управление GoogleApiClient с идентификатором 0

Полная ошибка протоколирование

java.lang.IllegalStateException: Already managing a GoogleApiClient with id 0 
at com.google.android.gms.common.internal.zzac.zza(Unknown Source) 
at com.google.android.gms.internal.zzzt.zza(Unknown Source) 
at com.google.android.gms.common.api.GoogleApiClient$Builder.zzf(Unknown Source) 
at com.google.android.gms.common.api.GoogleApiClient$Builder.build(Unknown Source) 
at com.naturesouq_shopping.fragment.RegistrationFragment.buildGoogleApiClient(RegistrationFragment.java:174) 
at com.naturesouq_shopping.fragment.RegistrationFragment.getIds(RegistrationFragment.java:140) 
at com.naturesouq_shopping.fragment.RegistrationFragment.onCreateView(RegistrationFragment.java:85) 
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2184) 
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1298) 
at android.support.v4.app.FragmentManagerImpl.moveFragmentsToInvisible(FragmentManager.java:2323) 
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2136) 
at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2092) 
at android.support.v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:1969) 
at android.support.v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:620) 
at android.support.v4.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:166) 
at android.support.v4.view.ViewPager.populate(ViewPager.java:1268) 
at android.support.v4.view.ViewPager.populate(ViewPager.java:1116) 
at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1642) 
at android.view.View.measure(View.java:20236) 

Я пытаюсь следующий код

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

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

     buildGoogleApiClient(); 

    // ..... 
} 

private synchronized void buildGoogleApiClient() { 
    /** build_client */ 
    try { 
     mGoogleApiClient = new GoogleApiClient.Builder(getActivity()) 
       .enableAutoManage(getActivity() /* FragmentActivity */, this /* OnConnectionFailedListener */) 
       .addApi(Auth.GOOGLE_SIGN_IN_API, gso) 
       .build(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

и

@Override 
public void onStart() { 
    super.onStart(); 
    if (mGoogleApiClient != null) { 
     mGoogleApiClient.connect(); 
    } 

} 

@Override 
public void onStop() { 
    Log.d("GARG", "***** on Stop ***** "); 
    if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) { 
     Log.d("GARG", "***** on Stop mGoogleApiClient disconnect ***** "); 

     mGoogleApiClient.stopAutoManage(getActivity()); 
     mGoogleApiClient.disconnect(); 
    } 
    super.onStop(); 
} 

Есть ли другой способ подключения клиента Google API? Любая идея о том, где я делаю неправильно и правильно?

ответ

8

Я думаю, что вы пытаетесь построить и подключиться через googleApiClient, который уже был построен и подключен. Это может решить вашу проблему:

if(mGoogleApiClient == null || !mGoogleApiClient.isConnected()){ 
try { 
    mGoogleApiClient = new GoogleApiClient.Builder(getActivity()) 
      .enableAutoManage(getActivity() /* FragmentActivity */, this /* OnConnectionFailedListener */) 
      .addApi(Auth.GOOGLE_SIGN_IN_API, gso) 
      .build(); 
} catch (Exception e) { 
    e.printStackTrace(); 
} 
} 
+0

Проблема с этим подходом, когда RegistrationFragment пытается получить GoogleApiClient, который уже был построен и соединенный LoginFragment, он просто не в состоянии тихо и, если есть код позже в RegistrationFragment, который использует mGoogleApiClient это будет бросаться NPE , – vlazzle

+0

Просто стараюсь быть конкретным. Я полагал, что это то место, где была дыра, когда я изучал код OP. – Journey

+0

Ваш код хорош, потому что он решает проблему с кодом OP, но даже лучший код не позволит создавать будущие проблемы. – vlazzle

6

official doc for enableAutoManage говорит, что это:

В любой момент времени только один клиент автоматически управляемого разрешено в ид. Чтобы повторно использовать идентификатор, вы должны сначала вызвать stopAutoManage (FragmentActivity) на предыдущем клиенте.

Ваш код использует версию enableAutoManage без параметра ClientId, так что это недобросовестный 0. Ниже я объясню, почему у вас будет несколько авто-управляемых клиентов для ClientId 0, что и выше документация предупреждение против ,

После того, как один из ваших фрагментов прикреплен к FragmentActivity, он сообщает, что активность начинает управлять новым экземпляром GoogleApiClient. Но что, если FragmentActivity уже управляет другим экземпляром GoogleApiClient? Вот когда вы получите сообщение об ошибке.

В вашем случае вашей FragmentActivity, содержащей ViewPager, предлагается управлять двумя разными GoogleApiClients, один из RegistrationFragment и один из LoginFragment. Согласно трассировке стека, FragmentActivity сначала начал управлять сайтом GoogleApiClient, а затем разбился, когда вы попросили его управлять GoogleApiClient RegistrationFragment.

Вы можете попробовать несколько вещей:

  • Проходят два разных clientIds к enableAutoManage, один для LoginFragment и другой для ReservationFragment.
  • Укажите, где вам нужно позвонить stopAutoManage. Это может быть сложно с помощью фрагментов в ViewPager.
  • Если бы я был вами, я бы серьезно подумал о создании GoogleApiClient в FragmentActivity, который содержит ViewPager, а не в RegistrationFragment и LoginFragment.Тогда вы можете либо сделать работу, которая требует GoogleApiClient в деятельности, или продолжать делать это в обоих фрагментах после получения GoogleApiClient от деятельности, как так:

частного GoogleApiClient GoogleApiClient;

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

    @Override 
    void onDetach() { 
     super.onDetach(); 
     googleApiClient = null; 
    } 
Смежные вопросы