Skip to content

Instantly share code, notes, and snippets.

@Isabellle
Forked from puf/ChatMessage.java
Created June 4, 2016 16:33
Show Gist options
  • Save Isabellle/fc082d4387c526e1919aff72129b8b17 to your computer and use it in GitHub Desktop.
Save Isabellle/fc082d4387c526e1919aff72129b8b17 to your computer and use it in GitHub Desktop.
Zero to App: Develop with Firebase (for Android - Google I/O 2016)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.google.firebase.zerotoapp.MainActivity">
<RelativeLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/header"
android:gravity="end">
<ImageView
android:layout_width="36dp"
android:layout_height="36dp"
android:background="@drawable/ic_account_box_black_24dp"
android:id="@+id/userIcon"
android:foregroundGravity="center"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true" />
<TextView
android:layout_width="141dp"
android:layout_height="wrap_content"
android:id="@+id/usernameTxt"
android:layout_toRightOf="@+id/userIcon"
android:layout_alignTop="@+id/userIcon"
android:layout_alignBottom="@+id/userIcon"
android:gravity="center_vertical"
tools:text="Username"
android:layout_weight="0" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sign in"
android:id="@+id/loginBtn"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sign out"
android:id="@+id/logoutBtn"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true" />
</RelativeLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/messagesList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
tools:listitem="@android:layout/two_line_list_item"
android:layout_above="@+id/footer"
android:layout_below="@+id/header" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:id="@+id/footer">
<ImageButton
android:layout_width="36dp"
android:layout_height="36dp"
android:id="@+id/imageBtn"
android:background="@android:drawable/ic_menu_gallery" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/messageTxt"
android:layout_gravity="bottom"
android:layout_weight="1"
android:inputType="textShortMessage|textAutoCorrect" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send"
android:id="@+id/sendBtn"
android:layout_gravity="bottom" />
</LinearLayout>
</RelativeLayout>
package com.google.firebase.zerotoapp;
public class ChatMessage {
public String name;
public String message;
public ChatMessage() {
}
public ChatMessage(String name, String message) {
this.name = name;
this.message = message;
}
}
package com.google.firebase.zerotoapp;
import android.app.Activity;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
public class ChatMessageAdapter extends RecyclerView.Adapter<ChatMessageViewHolder> {
private static final String TAG = "ChatMessageAdapter";
private final Activity activity;
List<ChatMessage> messages = new ArrayList<>();
public ChatMessageAdapter(Activity activity) {
this.activity = activity;
}
public void addMessage(ChatMessage chat) {
messages.add(chat);
notifyItemInserted(messages.size());
}
@Override
public ChatMessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ChatMessageViewHolder(activity, activity.getLayoutInflater().inflate(android.R.layout.two_line_list_item, parent, false));
}
@Override
public void onBindViewHolder(ChatMessageViewHolder holder, int position) {
holder.bind(messages.get(position));
}
@Override
public int getItemCount() {
return messages.size();
}
}
package com.google.firebase.zerotoapp;
import android.app.Activity;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
public class ChatMessageViewHolder extends RecyclerView.ViewHolder {
private static final String TAG = "ChatMessageViewHolder";
private final Activity activity;
TextView name, message;
ImageView image;
public ChatMessageViewHolder(Activity activity, View itemView) {
super(itemView);
this.activity = activity;
name = (TextView) itemView.findViewById(android.R.id.text1);
message = (TextView) itemView.findViewById(android.R.id.text2);
image= new ImageView(activity);
((ViewGroup)itemView).addView(image);
}
public void bind(ChatMessage chat) {
name.setText(chat.name);
if (chat.message.startsWith("https://firebasestorage.googleapis.com/") || chat.message.startsWith("content://")) {
message.setVisibility(View.INVISIBLE);
image.setVisibility(View.VISIBLE);
Glide.with(activity)
.load(chat.message)
.into(image);
}
else {
message.setVisibility(View.VISIBLE);
image.setVisibility(View.GONE);
message.setText(chat.message);
}
}
}
package com.google.firebase.zerotoapp;
import android.app.Activity;
import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.text.InputType;
import android.widget.EditText;
import android.widget.LinearLayout;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.FirebaseApp;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import java.util.ArrayList;
import java.util.List;
public class LoginDialog {
private static final String TAG = "LoginDialog";
static List<OnSuccessListener<EmailPasswordResult>> callbacks = new ArrayList<>();
public static void onCredentials(final OnSuccessListener<EmailPasswordResult> callback) {
callbacks.add(callback);
}
public static class EmailPasswordResult {
public String email;
public String password;
public EmailPasswordResult() {
}
public EmailPasswordResult(String email, String password) {
this.email = email;
this.password = password;
}
}
public static void showLoginPrompt(final Activity activity, final FirebaseApp app) {
showLoginPrompt(activity, app, null);
}
public static void showLoginPrompt(final Activity activity, final FirebaseApp app, final OnSuccessListener<EmailPasswordResult> callback) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("What's your username");
LinearLayout parent = new LinearLayout(activity);
parent.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
parent.setOrientation(LinearLayout.VERTICAL);
final EditText email = new EditText(activity);
email.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
email.setHint("User name");
parent.addView(email);
final EditText password = new EditText(activity);
password.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
password.setHint("Password");
parent.addView(password);
builder.setView(parent);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
FirebaseAuth.getInstance(app).createUserWithEmailAndPassword(email.getText().toString(), password.getText().toString())
.addOnCompleteListener(activity, new OnCompleteListener<AuthResult>() {
public void onComplete(Task<AuthResult> task) {
EmailPasswordResult result = new EmailPasswordResult(email.getText().toString(), password.getText().toString());
if (callback != null) {
callback.onSuccess(result);
}
else {
for (OnSuccessListener<EmailPasswordResult> callback: callbacks){
callback.onSuccess(result);
}
}
}
});
dialog.dismiss();
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.show();
}
}
package com.google.firebase.zerotoapp;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.FirebaseApp;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
static final int RC_PHOTO_PICKER = 1;
private Button sendBtn;
private EditText messageTxt;
private RecyclerView messagesList;
private ChatMessageAdapter adapter;
private ImageButton imageBtn;
private TextView usernameTxt;
private View loginBtn;
private View logoutBtn;
private FirebaseApp app;
private FirebaseDatabase database;
private FirebaseAuth auth;
private FirebaseStorage storage;
private DatabaseReference databaseRef;
private StorageReference storageRef;
private String username;
private void setUsername(String username) {
Log.d(TAG, "setUsername("+String.valueOf(username)+")");
if (username == null) {
username = "Android";
}
boolean isLoggedIn = !username.equals("Android");
this.username = username;
this.usernameTxt.setText(username);
this.logoutBtn.setVisibility(isLoggedIn ? View.VISIBLE : View.GONE);
this.loginBtn .setVisibility(isLoggedIn ? View.GONE : View.VISIBLE);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sendBtn = (Button) findViewById(R.id.sendBtn);
messageTxt = (EditText) findViewById(R.id.messageTxt);
messagesList = (RecyclerView) findViewById(R.id.messagesList);
imageBtn = (ImageButton) findViewById(R.id.imageBtn);
loginBtn = findViewById(R.id.loginBtn);
logoutBtn = findViewById(R.id.logoutBtn);
usernameTxt = (TextView) findViewById(R.id.usernameTxt);
setUsername("Android");
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
messagesList.setHasFixedSize(false);
messagesList.setLayoutManager(layoutManager);
// Show an image picker when the user wants to upload an imasge
imageBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/jpeg");
intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
startActivityForResult(Intent.createChooser(intent, "Complete action using"), RC_PHOTO_PICKER);
}
});
// Show a popup when the user asks to sign in
loginBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
LoginDialog.showLoginPrompt(MainActivity.this, app);
}
});
// Allow the user to sign out
logoutBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
auth.signOut();
}
});
adapter = new ChatMessageAdapter(this);
messagesList.setAdapter(adapter);
adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
public void onItemRangeInserted(int positionStart, int itemCount) {
messagesList.smoothScrollToPosition(adapter.getItemCount());
}
});
// Get the Firebase app and all primitives we'll use
app = FirebaseApp.getInstance();
database = FirebaseDatabase.getInstance(app);
auth = FirebaseAuth.getInstance(app);
storage = FirebaseStorage.getInstance(app);
// Get a reference to our chat "room" in the database
databaseRef = database.getReference("chat");
sendBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
ChatMessage chat = new ChatMessage(username, messageTxt.getText().toString());
// Push the chat message to the database
databaseRef.push().setValue(chat);
messageTxt.setText("");
}
});
// Listen for when child nodes get added to the collection
databaseRef.addChildEventListener(new ChildEventListener() {
public void onChildAdded(DataSnapshot snapshot, String s) {
// Get the chat message from the snapshot and add it to the UI
ChatMessage chat = snapshot.getValue(ChatMessage.class);
adapter.addMessage(chat);
}
public void onChildChanged(DataSnapshot dataSnapshot, String s) { }
public void onChildRemoved(DataSnapshot dataSnapshot) { }
public void onChildMoved(DataSnapshot dataSnapshot, String s) { }
public void onCancelled(DatabaseError databaseError) { }
});
// When the user has entered credentials in the login dialog
LoginDialog.onCredentials(new OnSuccessListener<LoginDialog.EmailPasswordResult>() {
public void onSuccess(LoginDialog.EmailPasswordResult result) {
// Sign the user in with the email address and password they entered
auth.signInWithEmailAndPassword(result.email, result.password);
}
});
// When the user signs in or out, update the username we keep for them
auth.addAuthStateListener(new FirebaseAuth.AuthStateListener() {
public void onAuthStateChanged(FirebaseAuth firebaseAuth) {
if (firebaseAuth.getCurrentUser() != null) {
// User signed in, set their email address as the user name
setUsername(firebaseAuth.getCurrentUser().getEmail());
}
else {
// User signed out, set a default username
setUsername("Android");
}
}
});
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == RC_PHOTO_PICKER && resultCode == RESULT_OK) {
Uri selectedImageUri = data.getData();
// Get a reference to the location where we'll store our photos
storageRef = storage.getReference("chat_photos");
// Get a reference to store file at chat_photos/<FILENAME>
final StorageReference photoRef = storageRef.child(selectedImageUri.getLastPathSegment());
// Upload file to Firebase Storage
photoRef.putFile(selectedImageUri)
.addOnSuccessListener(this, new OnSuccessListener<UploadTask.TaskSnapshot>() {
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
// When the image has successfully uploaded, we get its download URL
Uri downloadUrl = taskSnapshot.getDownloadUrl();
// Set the download URL to the message box, so that the user can send it to the database
messageTxt.setText(downloadUrl.toString());
}
});
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment