diff --git a/android-start/app/build.gradle b/android-start/app/build.gradle index 3074195db..83a98c9ef 100644 --- a/android-start/app/build.gradle +++ b/android-start/app/build.gradle @@ -42,17 +42,17 @@ dependencies { compile 'com.android.support:appcompat-v7:25.0.0' // Google - compile 'com.google.android.gms:play-services-auth:10.0.0' + compile 'com.google.android.gms:play-services-auth:10.0.1' // Firebase - compile 'com.google.firebase:firebase-database:10.0.0' - compile 'com.google.firebase:firebase-auth:10.0.0' - compile 'com.google.firebase:firebase-config:10.0.0' - compile 'com.google.android.gms:play-services-appinvite:10.0.0' - compile 'com.google.firebase:firebase-messaging:10.0.0' - compile 'com.google.android.gms:play-services-ads:10.0.0' - compile 'com.google.firebase:firebase-crash:10.0.0' - compile 'com.google.firebase:firebase-appindexing:10.0.0' + compile 'com.google.firebase:firebase-database:10.0.1' + compile 'com.google.firebase:firebase-auth:10.0.1' + compile 'com.google.firebase:firebase-config:10.0.1' + compile 'com.google.android.gms:play-services-appinvite:10.0.1' + compile 'com.google.firebase:firebase-messaging:10.0.1' + compile 'com.google.android.gms:play-services-ads:10.0.1' + compile 'com.google.firebase:firebase-crash:10.0.1' + compile 'com.google.firebase:firebase-appindexing:10.0.1' // Firebase UI compile 'com.firebaseui:firebase-ui-database:0.4.0' diff --git a/android-start/app/src/main/AndroidManifest.xml b/android-start/app/src/main/AndroidManifest.xml index e0833dfa9..0d931d19a 100644 --- a/android-start/app/src/main/AndroidManifest.xml +++ b/android-start/app/src/main/AndroidManifest.xml @@ -8,16 +8,28 @@ android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> + - - - + + + + + + + + + + diff --git a/android-start/app/src/main/java/com/google/firebase/codelab/friendlychat/MainActivity.java b/android-start/app/src/main/java/com/google/firebase/codelab/friendlychat/MainActivity.java index e887e1473..19b4aed1b 100644 --- a/android-start/app/src/main/java/com/google/firebase/codelab/friendlychat/MainActivity.java +++ b/android-start/app/src/main/java/com/google/firebase/codelab/friendlychat/MainActivity.java @@ -104,6 +104,11 @@ public MessageViewHolder(View v) { private EditText mMessageEditText; // Firebase instance variables + private FirebaseAuth mFirebaseAuth; + private FirebaseUser mFirebaseUser; + private DatabaseReference mFirebaseDatabaseReference; + private FirebaseRecyclerAdapter + mFirebaseAdapter; @Override protected void onCreate(Bundle savedInstanceState) { @@ -113,6 +118,21 @@ protected void onCreate(Bundle savedInstanceState) { // Set default username is anonymous. mUsername = ANONYMOUS; + // Initialize Firebase Auth + mFirebaseAuth = FirebaseAuth.getInstance(); + mFirebaseUser = mFirebaseAuth.getCurrentUser(); + if (mFirebaseUser == null) { + // Not signed in, launch the Sign In activity + startActivity(new Intent(this, SignInActivity.class)); + finish(); + return; + } else { + mUsername = mFirebaseUser.getDisplayName(); + if (mFirebaseUser.getPhotoUrl() != null) { + mPhotoUrl = mFirebaseUser.getPhotoUrl().toString(); + } + } + mGoogleApiClient = new GoogleApiClient.Builder(this) .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */) .addApi(Auth.GOOGLE_SIGN_IN_API) @@ -125,7 +145,54 @@ protected void onCreate(Bundle savedInstanceState) { mLinearLayoutManager.setStackFromEnd(true); mMessageRecyclerView.setLayoutManager(mLinearLayoutManager); - mProgressBar.setVisibility(ProgressBar.INVISIBLE); + // New child entries + mFirebaseDatabaseReference = FirebaseDatabase.getInstance().getReference(); + mFirebaseAdapter = new FirebaseRecyclerAdapter( + FriendlyMessage.class, + R.layout.item_message, + MessageViewHolder.class, + mFirebaseDatabaseReference.child(MESSAGES_CHILD)) { + + @Override + protected void populateViewHolder(MessageViewHolder viewHolder, + FriendlyMessage friendlyMessage, int position) { + mProgressBar.setVisibility(ProgressBar.INVISIBLE); + viewHolder.messageTextView.setText(friendlyMessage.getText()); + viewHolder.messengerTextView.setText(friendlyMessage.getName()); + if (friendlyMessage.getPhotoUrl() == null) { + viewHolder.messengerImageView + .setImageDrawable(ContextCompat + .getDrawable(MainActivity.this, + R.drawable.ic_account_circle_black_36dp)); + } else { + Glide.with(MainActivity.this) + .load(friendlyMessage.getPhotoUrl()) + .into(viewHolder.messengerImageView); + } + } + }; + + mFirebaseAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() { + @Override + public void onItemRangeInserted(int positionStart, int itemCount) { + super.onItemRangeInserted(positionStart, itemCount); + int friendlyMessageCount = mFirebaseAdapter.getItemCount(); + int lastVisiblePosition = + mLinearLayoutManager.findLastCompletelyVisibleItemPosition(); + // If the recycler view is initially being loaded or the + // user is at the bottom of the list, scroll to the bottom + // of the list to show the newly added message. + if (lastVisiblePosition == -1 || + (positionStart >= (friendlyMessageCount - 1) && + lastVisiblePosition == (positionStart - 1))) { + mMessageRecyclerView.scrollToPosition(positionStart); + } + } + }); + + mMessageRecyclerView.setLayoutManager(mLinearLayoutManager); + mMessageRecyclerView.setAdapter(mFirebaseAdapter); mMessageEditText = (EditText) findViewById(R.id.messageEditText); mMessageEditText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(mSharedPreferences @@ -153,7 +220,13 @@ public void afterTextChanged(Editable editable) { mSendButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - // Send messages on click. + FriendlyMessage friendlyMessage = new + FriendlyMessage(mMessageEditText.getText().toString(), + mUsername, + mPhotoUrl); + mFirebaseDatabaseReference.child(MESSAGES_CHILD) + .push().setValue(friendlyMessage); + mMessageEditText.setText(""); } }); } @@ -189,7 +262,38 @@ public boolean onCreateOptionsMenu(Menu menu) { @Override public boolean onOptionsItemSelected(MenuItem item) { - return super.onOptionsItemSelected(item); + switch (item.getItemId()) { + + case R.id.sign_out_menu: + mFirebaseAuth.signOut(); + Auth.GoogleSignInApi.signOut(mGoogleApiClient); + mUsername = ANONYMOUS; + startActivity(new Intent(this, SignInActivity.class)); + return true; + + default: + return super.onOptionsItemSelected(item); + } + } + + private Indexable getMessageIndexable(FriendlyMessage friendlyMessage) { + PersonBuilder sender = Indexables.personBuilder() + .setIsSelf(mUsername == friendlyMessage.getName()) + .setName(friendlyMessage.getName()) + .setUrl(MESSAGE_URL.concat(friendlyMessage.getId() + "/sender")); + + PersonBuilder recipient = Indexables.personBuilder() + .setName(mUsername) + .setUrl(MESSAGE_URL.concat(friendlyMessage.getId() + "/recipient")); + + Indexable messageToIndex = Indexables.messageBuilder() + .setName(friendlyMessage.getText()) + .setUrl(MESSAGE_URL.concat(friendlyMessage.getId())) + .setSender(sender) + .setRecipient(recipient) + .build(); + + return messageToIndex; } @Override diff --git a/android-start/app/src/main/java/com/google/firebase/codelab/friendlychat/SignInActivity.java b/android-start/app/src/main/java/com/google/firebase/codelab/friendlychat/SignInActivity.java index 0a158b816..464b023bc 100644 --- a/android-start/app/src/main/java/com/google/firebase/codelab/friendlychat/SignInActivity.java +++ b/android-start/app/src/main/java/com/google/firebase/codelab/friendlychat/SignInActivity.java @@ -48,6 +48,7 @@ public class SignInActivity extends AppCompatActivity implements private GoogleApiClient mGoogleApiClient; // Firebase instance variables + private FirebaseAuth mFirebaseAuth; @Override protected void onCreate(Bundle savedInstanceState) { @@ -71,16 +72,65 @@ protected void onCreate(Bundle savedInstanceState) { .build(); // Initialize FirebaseAuth + mFirebaseAuth = FirebaseAuth.getInstance(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.sign_in_button: + signIn(); break; } } + private void signIn() { + Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient); + startActivityForResult(signInIntent, RC_SIGN_IN); + } + + @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); + if (result.isSuccess()) { + // Google Sign In was successful, authenticate with Firebase + GoogleSignInAccount account = result.getSignInAccount(); + firebaseAuthWithGoogle(account); + } else { + // Google Sign In failed + Log.e(TAG, "Google Sign In failed."); + } + } + } + + private void firebaseAuthWithGoogle(GoogleSignInAccount acct) { + Log.d(TAG, "firebaseAuthWithGooogle:" + acct.getId()); + AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null); + mFirebaseAuth.signInWithCredential(credential) + .addOnCompleteListener(this, new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task 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()); + Toast.makeText(SignInActivity.this, "Authentication failed.", + Toast.LENGTH_SHORT).show(); + } else { + startActivity(new Intent(SignInActivity.this, MainActivity.class)); + finish(); + } + } + }); + } + @Override public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { // An unresolvable error has occurred and Google APIs (including Sign-In) will not diff --git a/android-start/build.gradle b/android-start/build.gradle index f5a38fc74..7fb4bbf1a 100644 --- a/android-start/build.gradle +++ b/android-start/build.gradle @@ -6,7 +6,7 @@ buildscript { mavenLocal() } dependencies { - classpath 'com.android.tools.build:gradle:2.2.2' + classpath 'com.android.tools.build:gradle:2.2.3' classpath 'com.google.gms:google-services:3.0.0' // NOTE: Do not place your application dependencies here; they belong diff --git a/android/build.gradle b/android/build.gradle index 402c017f8..ffaa9e304 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -5,7 +5,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.2.2' + classpath 'com.android.tools.build:gradle:2.2.3' classpath 'com.google.gms:google-services:3.0.0' // NOTE: Do not place your application dependencies here; they belong