Skip to content

Various Login fixes and Dialog #25

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Nov 11, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
.DS_Store
/build
/captures
/library/target
/library/target
/**/*.iml
259 changes: 138 additions & 121 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,27 +40,28 @@ So say we have these chat messages in our Firebase database:

We can represent a chat message with this Java class:

public class ChatMessage {
String message;
String name;
```java
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! I know about this GFMD feature, but somehow am too used to StackOverflow Markdown.

public class ChatMessage {
String message;
String name;

public ChatMessage() {
}

public ChatMessage(String name, String message) {
this.message = message;
this.name = name;
}
public ChatMessage() {
}

public String getMessage() {
return message;
}
public ChatMessage(String name, String message) {
this.message = message;
this.name = name;
}

public String getName() {
return name;
}
public String getMessage() {
return message;
}

public String getName() {
return name;
}
}
```
A few things to note here:

* the field have the exact same name as the properties in Firebase. This allows Firebase to automatically map the properties to these fields.
Expand All @@ -70,28 +71,30 @@ A few things to note here:

A little-known feature of Firebase for Android is that you can pass an instance of this `ChatMessage` class to `setValue()`:

Firebase ref = new Firebase("https://nanochat.firebaseio.com/");
ChatMessage msg = new ChatMessage("puf", "Hello FirebaseUI world!");
ref.push().setValue(msg);

```java
Firebase ref = new Firebase("https://nanochat.firebaseio.com/");
ChatMessage msg = new ChatMessage("puf", "Hello FirebaseUI world!");
ref.push().setValue(msg);
```
The Firebase Android client will read the values from the `msg` and write them into the properties of the new child in the database.

Conversely, we can read a `ChatMessage` straight from a `DataSnapshot` in our event handlers:

ref.limitToLast(5).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot msgSnapshot: snapshot.getChildren()) {
ChatMessage msg = msgSnapshot.getValue(ChatMessage.class);
Log.i("Chat", chat.getName()+": "+chat.getMessage());
}
}
@Override
public void onCancelled(FirebaseError firebaseError) {
Log.e("Chat", "The read failed: " + firebaseError.getMessage());
```java
ref.limitToLast(5).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot msgSnapshot: snapshot.getChildren()) {
ChatMessage msg = msgSnapshot.getValue(ChatMessage.class);
Log.i("Chat", chat.getName()+": "+chat.getMessage());
}
});

}
@Override
public void onCancelled(FirebaseError firebaseError) {
Log.e("Chat", "The read failed: " + firebaseError.getMessage());
}
});
```
In the above snippet we have a query for the last 5 chat messages. Whenever those change (i.e. when an new message is added)
we get the `ChatMessage` objects from the `DataSnapshot` with `getValue(ChatMessage.class)`. The Firebase Android client will
then read the properties that it got from the database and map them to the fields of our `ChatMessage` class.
Expand All @@ -105,53 +108,59 @@ But when we build our app using FirebaseUI, we often won't need to register our

We'll assume you've already added a `ListView` to your layout and have looked it up in the `onCreate` method of your activity:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
```java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

ListView messagesView = (ListView) findViewById(R.id.messages_list);
}
ListView messagesView = (ListView) findViewById(R.id.messages_list);
}
```

#### Set up connection to Firebase

First we'll tell Firebase that we intend to use it in this activity and set up a reference to the database of chat message.

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
```java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

ListView messagesView = (ListView) findViewById(R.id.messages_list);
ListView messagesView = (ListView) findViewById(R.id.messages_list);

Firebase.setAndroidContext(this);
Firebase ref = new Firebase("https://nanochat.firebaseio.com");
}
Firebase.setAndroidContext(this);
Firebase ref = new Firebase("https://nanochat.firebaseio.com");
}
```

#### Create custom FirebaseListAdapter subclass

Next, we need to create a subclass of the `FirebaseListAdapter` with the correct parameters and implement its `populateView` method:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
```java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

ListView messagesView = (ListView) findViewById(R.id.messages_list);
ListView messagesView = (ListView) findViewById(R.id.messages_list);

Firebase.setAndroidContext(this);
Firebase ref = new Firebase("https://nanochat.firebaseio.com");
Firebase.setAndroidContext(this);
Firebase ref = new Firebase("https://nanochat.firebaseio.com");

mAdapter = new FirebaseListAdapter<ChatMessage>(this, ChatMessage.class, android.R.layout.two_line_list_item, ref) {
@Override
protected void populateView(View view, ChatMessage chatMessage) {
((TextView)view.findViewById(android.R.id.text1)).setText(chatMessage.getName());
((TextView)view.findViewById(android.R.id.text2)).setText(chatMessage.getMessage());
mAdapter = new FirebaseListAdapter<ChatMessage>(this, ChatMessage.class, android.R.layout.two_line_list_item, ref) {
@Override
protected void populateView(View view, ChatMessage chatMessage) {
((TextView)view.findViewById(android.R.id.text1)).setText(chatMessage.getName());
((TextView)view.findViewById(android.R.id.text2)).setText(chatMessage.getMessage());

}
};
messagesView.setListAdapter(mAdapter);
}
}
};
messagesView.setListAdapter(mAdapter);
}
```

In this last snippet we create a subclass of `FirebaseListAdapter`.
We tell is that it is of type `<ChatMessage>`, so that it is a type-safe collection. We also tell it to use
Expand All @@ -171,51 +180,55 @@ correct `TextView` controls from the `view`. The code is a bit verbose, but hey.
Finally, we need to clean up after ourselves. When the activity is destroyed, we need to call `release()`
on the `ListAdapter` so that it can stop listening for changes in the Firebase database.

@Override
protected void onDestroy() {
super.onDestroy();
mAdapter.cleanup();
}
```java
@Override
protected void onDestroy() {
super.onDestroy();
mAdapter.cleanup();
}
```

#### Sending chat messages

Remember when we showed how to use the `ChatMessage` class in `setValue()`.
We can now use that in our activity to allow sending a message:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

ListView messagesView = (ListView) findViewById(R.id.messages_list);

Firebase.setAndroidContext(this);
Firebase ref = new Firebase("https://nanochat.firebaseio.com");

mAdapter = new FirebaseListAdapter<ChatMessage>(this, ChatMessage.class, android.R.layout.two_line_list_item, ref) {
@Override
protected void populateView(View view, ChatMessage chatMessage) {
((TextView)view.findViewById(android.R.id.text1)).setText(chatMessage.getName());
((TextView)view.findViewById(android.R.id.text2)).setText(chatMessage.getMessage());
}
};
setListAdapter(mAdapter);

final EditText mMessage = (EditText) findViewById(R.id.message_text);
findViewById(R.id.send_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mRef.push().setValue(new ChatMessage("puf", mMessage.getText().toString()));
mMessage.setText("");
}
});
}
```java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

@Override
protected void onDestroy() {
super.onDestroy();
mAdapter.cleanup();
}
ListView messagesView = (ListView) findViewById(R.id.messages_list);

Firebase.setAndroidContext(this);
Firebase ref = new Firebase("https://nanochat.firebaseio.com");

mAdapter = new FirebaseListAdapter<ChatMessage>(this, ChatMessage.class, android.R.layout.two_line_list_item, ref) {
@Override
protected void populateView(View view, ChatMessage chatMessage) {
((TextView)view.findViewById(android.R.id.text1)).setText(chatMessage.getName());
((TextView)view.findViewById(android.R.id.text2)).setText(chatMessage.getMessage());
}
};
setListAdapter(mAdapter);

final EditText mMessage = (EditText) findViewById(R.id.message_text);
findViewById(R.id.send_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mRef.push().setValue(new ChatMessage("puf", mMessage.getText().toString()));
mMessage.setText("");
}
});
}

@Override
protected void onDestroy() {
super.onDestroy();
mAdapter.cleanup();
}
```

Et voila: a minimal, yet fully functional, chat app in about 30 lines of code. Not bad, right?

Expand All @@ -235,35 +248,39 @@ A ViewHolder is similar to container of a ViewGroup that allows simple lookup of
If we use the same layout as before (`android.R.layout.two_line_list_item`), there are two `TextView`s in there.
We can wrap that in a ViewHolder with:

private static class ChatMessageViewHolder extends RecyclerView.ViewHolder {
TextView messageText;
TextView nameText;
```java
private static class ChatMessageViewHolder extends RecyclerView.ViewHolder {
TextView messageText;
TextView nameText;

public ChatMessageViewHolder(View itemView) {
super(itemView);
nameText = (TextView)itemView.findViewById(android.R.id.text1);
messageText = (TextView) itemView.findViewById(android.R.id.text2);
}
public ChatMessageViewHolder(View itemView) {
super(itemView);
nameText = (TextView)itemView.findViewById(android.R.id.text1);
messageText = (TextView) itemView.findViewById(android.R.id.text2);
}
}
```

There's nothing magical going on here; we're just mapping numeric IDs and casts into a nice, type-safe contract.

### Create a custom FirebaseListAdapter

Just like we did for FirebaseListAdapter, we'll create an anonymous subclass for our ChatMessages:

RecyclerView recycler = (RecyclerView) findViewById(R.id.messages_recycler);
recycler.setHasFixedSize(true);
recycler.setLayoutManager(new LinearLayoutManager(this));

mAdapter = new FirebaseRecyclerViewAdapter<ChatMessage, ChatMessageViewHolder>(ChatMessage.class, android.R.layout.two_line_list_item, ChatMessageViewHolder.class, mRef) {
@Override
public void populateViewHolder(ChatMessageViewHolder chatMessageViewHolder, ChatMessage chatMessage) {
chatMessageViewHolder.nameText.setText(chatMessage.getName());
chatMessageViewHolder.messageText.setText(chatMessage.getMessage());
}
};
recycler.setAdapter(mAdapter);
```java
RecyclerView recycler = (RecyclerView) findViewById(R.id.messages_recycler);
recycler.setHasFixedSize(true);
recycler.setLayoutManager(new LinearLayoutManager(this));

mAdapter = new FirebaseRecyclerViewAdapter<ChatMessage, ChatMessageViewHolder>(ChatMessage.class, android.R.layout.two_line_list_item, ChatMessageViewHolder.class, mRef) {
@Override
public void populateViewHolder(ChatMessageViewHolder chatMessageViewHolder, ChatMessage chatMessage) {
chatMessageViewHolder.nameText.setText(chatMessage.getName());
chatMessageViewHolder.messageText.setText(chatMessage.getMessage());
}
};
recycler.setAdapter(mAdapter);
```

Like before, we get a custom RecyclerView populated with data from Firebase by setting the properties to the correct fields.

Expand Down
3 changes: 2 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ android {

defaultConfig {
applicationId "com.firebase.uidemo"
minSdkVersion 10
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName "1.0"
Expand All @@ -33,5 +33,6 @@ dependencies {
compile 'com.google.android.gms:play-services-plus:8.1.0'
compile 'com.firebase:firebase-client-android:2.3.1'
compile 'com.android.support:recyclerview-v7:22.2.1'
compile 'com.facebook.android:facebook-android-sdk:4.6.0'
compile project(':library')
}
21 changes: 21 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,27 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<!-- Twitter Configuration -->
<activity android:name="com.firebase.ui.auth.TwitterPromptActivity" />
<meta-data
android:name="com.firebase.ui.TwitterKey"
android:value="@string/twitter_app_key"/>
<meta-data
android:name="com.firebase.ui.TwitterSecret"
android:value="@string/twitter_app_secret"/>

<!-- Facebook Configuration -->
<activity
android:name="com.facebook.FacebookActivity"
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:label="@string/app_name"
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="@string/facebook_app_id" />


</application>

</manifest>
Binary file added app/src/main/ic_google-web.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading