Skip to content

Instantly share code, notes, and snippets.

@puf
Last active July 12, 2021 21:56
Show Gist options
  • Save puf/f49a1b07e92952b44f2dc36d9af04e3c to your computer and use it in GitHub Desktop.
Save puf/f49a1b07e92952b44f2dc36d9af04e3c 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>
apply plugin: 'com.android.application'
android {
compileSdkVersion 24
buildToolsVersion '24'
defaultConfig {
applicationId "com.google.firebase.zerotoapp"
minSdkVersion 16
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:24.0.0'
compile 'com.android.support:design:24.0.0'
compile 'com.android.support:recyclerview-v7:24.0.0'
compile 'com.google.firebase:firebase-database:9.2.1'
compile 'com.google.firebase:firebase-auth:9.2.1'
compile 'com.google.firebase:firebase-storage:9.2.1'
compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'com.firebaseui:firebase-ui-auth:0.4.3'
}
apply plugin: 'com.google.gms.google-services'
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());
}
});
}
}
}
@yannsonnboys
Copy link

Amazing

@HammadNasir
Copy link

@dibya001
Copy link

best example of firebase till date.thank you very much

@pratapsolankiandroid
Copy link

pratapsolankiandroid commented Sep 9, 2016

Really cool !

@DevLucem
Copy link

DevLucem commented Dec 30, 2016

good one but facing an error on line 176 MainActivity.java You also need to update the dependencies.. Also realized the bintray.com is taking too long to respond to the sync issues.

Any tips on resolving the error? Has the firebase-ui-auth been updated to 0.6.0???

Fixed.. some imports
import com.google.firebase.storage.UploadTask was missing

@SiyaLab
Copy link

SiyaLab commented Jan 18, 2017

Hi, do you mind helping me with the implementation that I did. I have been trying to solve it for a while now with no luck and no one seems to know where I went wrong...
http://stackoverflow.com/questions/41616312/nosuchmethodexception-while-using-firebaseui-recycleradapter/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment