/* * Copyright 2013-2015 The GDG Frisbee Project * * Licensed under * * the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.gdg.frisbee.android.common; import android.annotation.TargetApi; import android.app.PendingIntent; import android.content.Intent; import android.os.Build; import android.os.Bundle; import android.support.annotation.CallSuper; import android.support.annotation.CheckResult; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.StringRes; import android.support.design.widget.Snackbar; import android.support.v7.app.ActionBar; import android.support.v7.widget.Toolbar; import android.widget.FrameLayout; import android.widget.Toast; import com.google.android.gms.appindexing.Action; import com.google.android.gms.appindexing.AppIndex; 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.GoogleSignInResult; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GoogleApiAvailability; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.PendingResult; import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.common.api.ResultCallbacks; import com.google.android.gms.common.api.Status; import org.gdg.frisbee.android.R; import org.gdg.frisbee.android.app.GoogleApiClientFactory; import org.gdg.frisbee.android.utils.PlusUtils; import org.gdg.frisbee.android.utils.PrefUtils; import org.gdg.frisbee.android.utils.RecentTasksStyler; import org.gdg.frisbee.android.view.ColoredSnackBar; import butterknife.BindView; import butterknife.ButterKnife; import timber.log.Timber; public abstract class GdgActivity extends TrackableActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { private static final int RC_SIGN_IN = 101; @Nullable @BindView(R.id.content_frame) FrameLayout mContentLayout; @Nullable @BindView(R.id.toolbar_actionbar) Toolbar toolbar; private GoogleApiClient mGoogleApiClient; private GoogleApiClient signInClient; @Override public void setContentView(int layoutResId) { super.setContentView(layoutResId); ButterKnife.bind(this); setSupportActionBar(toolbar); } @Override protected String getTrackedViewName() { return null; } public GoogleApiClient getGoogleApiClient() { return mGoogleApiClient; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); RecentTasksStyler.styleRecentTasksEntry(this); mGoogleApiClient = createGoogleApiClient(); } @Override protected void onStart() { super.onStart(); mGoogleApiClient.connect(); if (PrefUtils.isSignedIn(this) && PlusUtils.getCurrentAccount(this) == null) { requestSignIn(); } } /** * Create {@link GoogleApiClient}. This can be overridden to change the scope of the GoogleApiClient * * @return {@link GoogleApiClient} without connecting. {@code connect()} must be called afterwards. */ @CheckResult protected GoogleApiClient createGoogleApiClient() { return GoogleApiClientFactory.createWith(this); } @Override protected void onStop() { super.onStop(); mGoogleApiClient.unregisterConnectionCallbacks(this); mGoogleApiClient.unregisterConnectionFailedListener(this); mGoogleApiClient.disconnect(); } protected final void requestSignIn() { if (signInClient == null) { signInClient = GoogleApiClientFactory.createForSignIn(this, this); } Auth.GoogleSignInApi.silentSignIn(signInClient).setResultCallback(new ResultCallbacks<GoogleSignInResult>() { @Override public void onSuccess(@NonNull GoogleSignInResult result) { onSuccessfulSignIn(result.getSignInAccount()); } @Override public void onFailure(@NonNull Status status) { Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(signInClient); startActivityForResult(signInIntent, RC_SIGN_IN); } }); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == RC_SIGN_IN) { GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data); if (result.isSuccess()) { onSuccessfulSignIn(result.getSignInAccount()); } else { PrefUtils.setSignedOut(this); } } } /** * Called when a successful SignIn operation is made * * @param signInAccount {@link GoogleSignInAccount} of the user */ @CallSuper protected void onSuccessfulSignIn(GoogleSignInAccount signInAccount) { PrefUtils.setSignedIn(this); } @NonNull @Override public ActionBar getSupportActionBar() { //noinspection ConstantConditions return super.getSupportActionBar(); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) protected boolean isContextValid() { boolean isContextValid = !isFinishing() && (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1 || !isDestroyed()); if (!isContextValid) { Timber.d("Context is not valid"); } return isContextValid; } protected void showError(@StringRes final int errorStringRes) { if (isContextValid()) { if (mContentLayout != null) { Snackbar snackbar = Snackbar.make(mContentLayout, errorStringRes, Snackbar.LENGTH_SHORT); ColoredSnackBar.alert(snackbar).show(); } else { Toast.makeText(this, errorStringRes, Toast.LENGTH_SHORT).show(); } } } @Override public void onConnected(Bundle bundle) { } @Override public void onConnectionSuspended(int i) { mGoogleApiClient.connect(); } @Override public void onConnectionFailed(@NonNull ConnectionResult result) { PendingIntent mSignInIntent = result.getResolution(); if (mSignInIntent == null && PrefUtils.shouldShowFatalPlayServiceMessage(this)) { showFatalPlayServiceMessage(result); } } private void showFatalPlayServiceMessage(@NonNull ConnectionResult result) { Timber.e("Google Play Service did not resolve error"); GoogleApiAvailability.getInstance().showErrorNotification(this, result.getErrorCode()); PrefUtils.setFatalPlayServiceMessageShown(this); } protected void recordEndPageView(Action viewAction) { PendingResult<Status> result = AppIndex.AppIndexApi.end(getGoogleApiClient(), viewAction); result.setResultCallback(appIndexApiCallback("end " + viewAction)); } protected void recordStartPageView(Action viewAction) { PendingResult<Status> result = AppIndex.AppIndexApi.start(getGoogleApiClient(), viewAction); result.setResultCallback(appIndexApiCallback("start " + viewAction)); } protected ResultCallback<Status> appIndexApiCallback(final String label) { return new ResultCallback<Status>() { @Override public void onResult(@NonNull Status status) { if (status.isSuccess()) { Timber.d("App Indexing API: Recorded event %s view successfully.", label); } else { Timber.e("App Indexing API: There was an error recording the event view. Status = %s", status.toString()); } } }; } }