Created
November 24, 2014 21:57
-
-
Save markbratanov/a94291edaf02b0b236d3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.starkenglish; | |
import android.app.Activity; | |
import android.app.ActionBar; | |
import android.app.AlertDialog; | |
import android.app.Fragment; | |
import android.app.FragmentManager; | |
import android.app.ProgressDialog; | |
import android.content.Context; | |
import android.content.Intent; | |
import android.content.IntentSender; | |
import android.os.AsyncTask; | |
import android.os.Build; | |
import android.os.Bundle; | |
import android.support.v4.app.FragmentActivity; | |
import android.support.v7.app.ActionBarActivity; | |
import android.util.Log; | |
import android.view.Gravity; | |
import android.view.LayoutInflater; | |
import android.view.Menu; | |
import android.view.MenuItem; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import android.support.v4.widget.DrawerLayout; | |
import android.widget.ArrayAdapter; | |
import android.widget.TextView; | |
import com.firebase.client.AuthData; | |
import com.firebase.client.Firebase; | |
import com.firebase.client.FirebaseError; | |
import com.google.android.gms.auth.GoogleAuthException; | |
import com.google.android.gms.auth.GoogleAuthUtil; | |
import com.google.android.gms.auth.UserRecoverableAuthException; | |
import com.google.android.gms.common.ConnectionResult; | |
import com.google.android.gms.common.Scopes; | |
import com.google.android.gms.common.SignInButton; | |
import com.google.android.gms.common.api.GoogleApiClient; | |
import com.google.android.gms.plus.Plus; | |
import java.io.IOException; | |
import java.util.HashMap; | |
import java.util.Map; | |
public class MainActivity extends FragmentActivity | |
implements NavigationDrawerFragment.NavigationDrawerCallbacks, | |
GoogleApiClient.ConnectionCallbacks, | |
GoogleApiClient.OnConnectionFailedListener { | |
/** | |
* Fragment managing the behaviors, interactions and presentation of the navigation drawer. | |
*/ | |
private NavigationDrawerFragment mNavigationDrawerFragment; | |
/** | |
* Used to store the last screen title. For use in {@link #restoreActionBar()}. | |
*/ | |
private CharSequence mTitle; | |
/*************************************** | |
* GENERAL * | |
***************************************/ | |
/* TextView that is used to display information about the logged in user */ | |
private TextView mLoggedInStatusTextView; | |
/* A dialog that is presented until the Firebase authentication finished. */ | |
private ProgressDialog mAuthProgressDialog; | |
/* A reference to the firebase */ | |
private Firebase ref; | |
/* Data from the authenticated user */ | |
private AuthData authData; | |
/* A tag that is used for logging statements */ | |
private static final String TAG = "LoginDemo"; | |
/*************************************** | |
* GOOGLE * | |
***************************************/ | |
/* Request code used to invoke sign in user interactions for Google+ */ | |
public static final int RC_GOOGLE_LOGIN = 1; | |
/* Client used to interact with Google APIs. */ | |
private GoogleApiClient mGoogleApiClient; | |
/* A flag indicating that a PendingIntent is in progress and prevents us from starting further intents. */ | |
private boolean mGoogleIntentInProgress; | |
/* Track whether the sign-in button has been clicked so that we know to resolve all issues preventing sign-in | |
* without waiting. */ | |
private boolean mGoogleLoginClicked; | |
/* Store the connection result from onConnectionFailed callbacks so that we can resolve them when the user clicks | |
* sign-in. */ | |
private ConnectionResult mGoogleConnectionResult; | |
/* The login button for Google */ | |
private SignInButton mGoogleLoginButton; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
mNavigationDrawerFragment = (NavigationDrawerFragment) | |
getFragmentManager().findFragmentById(R.id.navigation_drawer); | |
mTitle = getTitle(); | |
// Set up the drawer. | |
mNavigationDrawerFragment.setUp( | |
R.id.navigation_drawer, | |
(DrawerLayout) findViewById(R.id.drawer_layout)); | |
//getSupportActionBar().setLogo(R.drawable.ic_action_starkenglish); | |
/*************************************** | |
* GOOGLE * | |
***************************************/ | |
/* Load the Google login button */ | |
mGoogleLoginButton = (SignInButton)findViewById(R.id.login_with_google); | |
mGoogleLoginButton.setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View view) { | |
mGoogleLoginClicked = true; | |
if (!mGoogleApiClient.isConnecting()) { | |
if (mGoogleConnectionResult != null) { | |
resolveSignInError(); | |
} else if (mGoogleApiClient.isConnected()) { | |
getGoogleOAuthTokenAndLogin(); | |
} else { | |
/* connect API now */ | |
Log.d(TAG, "Trying to connect to Google API"); | |
mGoogleApiClient.connect(); | |
} | |
} | |
} | |
}); | |
/* Setup the Google API object to allow Google+ logins */ | |
mGoogleApiClient = new GoogleApiClient.Builder(this) | |
.addConnectionCallbacks(this) | |
.addOnConnectionFailedListener(this) | |
.addApi(Plus.API) | |
.addScope(Plus.SCOPE_PLUS_LOGIN) | |
.build(); | |
/*************************************** | |
* GENERAL * | |
***************************************/ | |
/* Create the SimpleLogin class that is used for all authentication with Firebase */ | |
String firebaseUrl = getResources().getString(R.string.firebase_url); | |
Firebase.setAndroidContext(getApplicationContext()); | |
ref = new Firebase(firebaseUrl); | |
/* Setup the progress dialog that is displayed later when authenticating with Firebase */ | |
mAuthProgressDialog = new ProgressDialog(this); | |
mAuthProgressDialog.setTitle("Loading"); | |
mAuthProgressDialog.setMessage("Authenticating"); | |
mAuthProgressDialog.setCancelable(false); | |
mAuthProgressDialog.show(); | |
/* Check if the user is authenticated with Firebase already. If this is the case we can set the authenticated | |
* user and hide hide any login buttons */ | |
ref.addAuthStateListener(new Firebase.AuthStateListener() { | |
@Override | |
public void onAuthStateChanged(AuthData authData) { | |
mAuthProgressDialog.hide(); | |
setAuthenticatedUser(authData); | |
} | |
}); | |
// Toolbar toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar); | |
// setSupportActionBar(toolbar); | |
} | |
@Override | |
public void onNavigationDrawerItemSelected(int position) { | |
// update the main content by replacing fragments | |
FragmentManager fragmentManager = getFragmentManager(); | |
fragmentManager.beginTransaction() | |
.replace(R.id.container, PlaceholderFragment.newInstance(position + 1)) | |
.commit(); | |
} | |
public void onSectionAttached(int number) { | |
switch (number) { | |
case 1: | |
mTitle = getString(R.string.title_section1); | |
break; | |
case 2: | |
mTitle = getString(R.string.title_section2); | |
break; | |
case 3: | |
mTitle = getString(R.string.title_section3); | |
break; | |
} | |
} | |
public void restoreActionBar() { | |
ActionBar actionBar = getActionBar(); | |
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); | |
actionBar.setDisplayShowTitleEnabled(true); | |
actionBar.setTitle(mTitle); | |
} | |
/** | |
* A placeholder fragment containing a simple view. | |
*/ | |
public static class PlaceholderFragment extends Fragment { | |
/** | |
* The fragment argument representing the section number for this | |
* fragment. | |
*/ | |
private static final String ARG_SECTION_NUMBER = "section_number"; | |
/** | |
* Returns a new instance of this fragment for the given section | |
* number. | |
*/ | |
public static PlaceholderFragment newInstance(int sectionNumber) { | |
PlaceholderFragment fragment = new PlaceholderFragment(); | |
Bundle args = new Bundle(); | |
args.putInt(ARG_SECTION_NUMBER, sectionNumber); | |
fragment.setArguments(args); | |
return fragment; | |
} | |
public PlaceholderFragment() { | |
} | |
@Override | |
public View onCreateView(LayoutInflater inflater, ViewGroup container, | |
Bundle savedInstanceState) { | |
View rootView = inflater.inflate(R.layout.fragment_main, container, false); | |
return rootView; | |
} | |
@Override | |
public void onAttach(Activity activity) { | |
super.onAttach(activity); | |
((MainActivity) activity).onSectionAttached( | |
getArguments().getInt(ARG_SECTION_NUMBER)); | |
} | |
} | |
/** | |
* This method fires when any startActivityForResult finishes. The requestCode maps to | |
* the value passed into startActivityForResult. | |
*/ | |
@Override | |
public void onActivityResult(int requestCode, int resultCode, Intent data) { | |
super.onActivityResult(requestCode, resultCode, data); | |
Map<String, String> options = new HashMap<String, String>(); | |
if (requestCode == RC_GOOGLE_LOGIN) { | |
/* This was a request by the Google API */ | |
if (resultCode != RESULT_OK) { | |
mGoogleLoginClicked = false; | |
} | |
mGoogleIntentInProgress = false; | |
if (!mGoogleApiClient.isConnecting()) { | |
mGoogleApiClient.connect(); | |
} | |
} | |
} | |
@Override | |
public boolean onCreateOptionsMenu(Menu menu) { | |
/* If a user is currently authenticated, display a logout menu */ | |
if (this.authData != null) { | |
getMenuInflater().inflate(R.menu.main, menu); | |
return true; | |
} else { | |
return false; | |
} | |
} | |
@Override | |
public boolean onOptionsItemSelected(MenuItem item) { | |
int id = item.getItemId(); | |
if (id == R.id.action_logout) { | |
logout(); | |
return true; | |
} | |
return super.onOptionsItemSelected(item); | |
} | |
/** | |
* Unauthenticate from Firebase and from providers where necessary. | |
*/ | |
private void logout() { | |
if (this.authData != null) { | |
/* logout of Firebase */ | |
ref.unauth(); | |
/* Logout of any of the Frameworks. This step is optional, but ensures the user is not logged into | |
* Facebook/Google+ after logging out of Firebase. */ | |
if (this.authData.getProvider().equals("google")) { | |
/* Logout from Google+ */ | |
if (mGoogleApiClient.isConnected()) { | |
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient); | |
mGoogleApiClient.disconnect(); | |
} | |
} | |
/* Update authenticated user and show login buttons */ | |
setAuthenticatedUser(null); | |
} | |
} | |
/** | |
* Once a user is logged in, take the authData provided from Firebase and "use" it. | |
*/ | |
private void setAuthenticatedUser(AuthData authData) { | |
if (authData != null) { | |
/* Hide all the login buttons */ | |
mGoogleLoginButton.setVisibility(View.GONE); | |
//card_view | |
//Intent intent = new Intent(this, LessonView.class); | |
//startActivity(intent); | |
/* show a provider specific status text */ | |
String name = null; | |
if (authData.getProvider().equals("facebook") | |
|| authData.getProvider().equals("google") | |
|| authData.getProvider().equals("twitter")) { | |
name = (String)authData.getProviderData().get("displayName"); | |
} else if (authData.getProvider().equals("anonymous") | |
|| authData.getProvider().equals("password")) { | |
name = authData.getUid(); | |
} else { | |
Log.e(TAG, "Invalid provider: " + authData.getProvider()); | |
} | |
if (name != null) { | |
mLoggedInStatusTextView.setText("Logged in as " + name + " (" + authData.getProvider() + ")"); | |
} | |
} else { | |
/* No authenticated user show all the login buttons */ | |
mGoogleLoginButton.setVisibility(View.VISIBLE); | |
} | |
this.authData = authData; | |
/* invalidate options menu to hide/show the logout button */ | |
invalidateOptionsMenu(); | |
} | |
/** | |
* Show errors to users | |
*/ | |
private void showErrorDialog(String message) { | |
new AlertDialog.Builder(this) | |
.setTitle("Error") | |
.setMessage(message) | |
.setPositiveButton(android.R.string.ok, null) | |
.setIcon(android.R.drawable.ic_dialog_alert) | |
.show(); | |
} | |
/** | |
* Utility class for authentication results | |
*/ | |
private class AuthResultHandler implements Firebase.AuthResultHandler { | |
private final String provider; | |
public AuthResultHandler(String provider) { | |
this.provider = provider; | |
} | |
@Override | |
public void onAuthenticated(AuthData authData) { | |
mAuthProgressDialog.hide(); | |
Log.i(TAG, provider + " auth successful"); | |
setAuthenticatedUser(authData); | |
} | |
@Override | |
public void onAuthenticationError(FirebaseError firebaseError) { | |
mAuthProgressDialog.hide(); | |
showErrorDialog(firebaseError.toString()); | |
} | |
} | |
/*************************************** | |
* GOOGLE * | |
***************************************/ | |
/* A helper method to resolve the current ConnectionResult error. */ | |
private void resolveSignInError() { | |
if (mGoogleConnectionResult.hasResolution()) { | |
try { | |
mGoogleIntentInProgress = true; | |
mGoogleConnectionResult.startResolutionForResult(this, RC_GOOGLE_LOGIN); | |
} catch (IntentSender.SendIntentException e) { | |
// The intent was canceled before it was sent. Return to the default | |
// state and attempt to connect to get an updated ConnectionResult. | |
mGoogleIntentInProgress = false; | |
mGoogleApiClient.connect(); | |
} | |
} | |
} | |
private void getGoogleOAuthTokenAndLogin() { | |
mAuthProgressDialog.show(); | |
/* Get OAuth token in Background */ | |
AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() { | |
String errorMessage = null; | |
@Override | |
protected String doInBackground(Void... params) { | |
String token = null; | |
try { | |
String scope = String.format("oauth2:%s", Scopes.PLUS_LOGIN); | |
token = GoogleAuthUtil.getToken(MainActivity.this, Plus.AccountApi.getAccountName(mGoogleApiClient), scope); | |
} catch (IOException transientEx) { | |
/* Network or server error */ | |
Log.e(TAG, "Error authenticating with Google: " + transientEx); | |
errorMessage = "Network error: " + transientEx.getMessage(); | |
} catch (UserRecoverableAuthException e) { | |
Log.w(TAG, "Recoverable Google OAuth error: " + e.toString()); | |
/* We probably need to ask for permissions, so start the intent if there is none pending */ | |
if (!mGoogleIntentInProgress) { | |
mGoogleIntentInProgress = true; | |
Intent recover = e.getIntent(); | |
startActivityForResult(recover, RC_GOOGLE_LOGIN); | |
} | |
} catch (GoogleAuthException authEx) { | |
/* The call is not ever expected to succeed assuming you have already verified that | |
* Google Play services is installed. */ | |
Log.e(TAG, "Error authenticating with Google: " + authEx.getMessage(), authEx); | |
errorMessage = "Error authenticating with Google: " + authEx.getMessage(); | |
} | |
return token; | |
} | |
@Override | |
protected void onPostExecute(String token) { | |
mGoogleLoginClicked = false; | |
if (token != null) { | |
/* Successfully got OAuth token, now login with Google */ | |
ref.authWithOAuthToken("google", token, new AuthResultHandler("google")); | |
} else if (errorMessage != null) { | |
mAuthProgressDialog.hide(); | |
showErrorDialog(errorMessage); | |
} | |
} | |
}; | |
task.execute(); | |
} | |
@Override | |
public void onConnected(final Bundle bundle) { | |
/* Connected with Google API, use this to authenticate with Firebase */ | |
getGoogleOAuthTokenAndLogin(); | |
} | |
@Override | |
public void onConnectionFailed(ConnectionResult result) { | |
if (!mGoogleIntentInProgress) { | |
/* Store the ConnectionResult so that we can use it later when the user clicks on the Google+ login button */ | |
mGoogleConnectionResult = result; | |
if (mGoogleLoginClicked) { | |
/* The user has already clicked login so we attempt to resolve all errors until the user is signed in, | |
* or they cancel. */ | |
resolveSignInError(); | |
} else { | |
Log.e(TAG, result.toString()); | |
} | |
} | |
} | |
@Override | |
public void onConnectionSuspended(int i) { | |
// ignore | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment