Skip to content

Commit 745ad82

Browse files
committed
More codelab improvements
1 parent dd5afce commit 745ad82

File tree

1 file changed

+56
-58
lines changed

1 file changed

+56
-58
lines changed

codelabs/chat/README.md

Lines changed: 56 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
In this code lab you'll build a chat application for Android using Firebase and Android Studio.
44

5-
<img alt="Chat login" src="images/0_0.png" height="600">
6-
<img alt="Chat messages" src="images/0_1.png" height="600">
5+
![Chat login](images/0_0.png)
6+
![Chat messages](images/0_1.png)
77

88
What you'll learn:
99

@@ -83,18 +83,18 @@ In this step we'll create a project in Android Studio.
8383

8484
Before we can start writing code that interacts with our Firebase database, we'll need to make Android Studio aware that we'll be using Firebase. We need to do this in a few places: in the `gradle.build` script for our app and in its `AndroidManifest.xml`.
8585

86-
1. open Gradle Scripts > build.gradle (Module: app)
86+
First, open Gradle Scripts > build.gradle (Module: app)
8787

8888
This file contains the steps that Android Studio uses to build our app. We'll add a reference to Firebase to it, so we can start using it.
8989

90-
2. add the following lines to the dependencies object at the bottom:
90+
Then add the following lines to the dependencies object at the bottom:
9191

9292
compile 'com.firebase:firebase-client-android:2.5.0'
9393
compile 'com.firebaseui:firebase-ui:0.3.0'
9494

9595
This tells Gradle to include the Firebase SDK and the FirebaseUI library.
9696

97-
3. Add the following inside the `android` object:
97+
Add the following inside the `android` object:
9898

9999
packagingOptions {
100100
exclude 'META-INF/LICENSE'
@@ -106,38 +106,38 @@ Before we can start writing code that interacts with our Firebase database, we'l
106106

107107
![gradle.build with Firebase additions](images/3_1.png)
108108

109-
4. At this stage you'll need to synchronize the project with the gradle files again. Either click the Sync Now link in the notification bar or the corresponding button in the toolbar: Sync Project with Gradle Files.
109+
At this stage you'll need to synchronize the project with the gradle files again. Either click the Sync Now link in the notification bar or the corresponding button in the toolbar: Sync Project with Gradle Files.
110110

111111
![Sync Project with Gradle Files button in toolbar](images/3_2.png)
112112

113113
Android Studio will parse the gradle files and pick up our changes.
114114

115-
5. Since Firebase is a hosted service, our app will need to be able to access the internet.
116-
6. Open app > manifests > AndroidManifest.xml
117-
7. Add this line inside the `manifest` element:
115+
Since Firebase is a hosted service, our app will need to be able to access the internet. Open app > manifests > AndroidManifest.xml then add this line inside the `manifest` element:
118116

119117
```html
120118
<uses-permission android:name="android.permission.INTERNET" />
121119
```
122120

123121
![INTERNET permission in AndroidManifest.xml](images/3_3.png)
124122

125-
8. Import Firebase at the top of your MainActivity by adding the following line:
123+
Import Firebase at the top of your MainActivity by adding the following line:
126124

127125
```java
128126
import com.firebase.client.Firebase;
129127
```
130128

131-
9. Now we can get to the Java code. The first step there is to set up initial connection between our code and its Firebase backend.
129+
Now we can get to the Java code. The first step there is to set up initial connection between our code and its Firebase backend.
132130
open `MainActivity.java` and add this code to the end of the `onCreate` method:
133131

134132
```java
135133
Firebase.setAndroidContext(this);
136134
```
137135

138-
This code allows the Firebase client to keep its context.
139-
10. If Android Studio is having trouble finding the Firebase class, be sure that you've added dependencies and have synchronized the build file with the project.
140-
11. We also want to create a connection to our database. We'll keep this connection in a member field:
136+
This code allows the Firebase client to keep its context.
137+
138+
**If Android Studio is having trouble finding the Firebase class, be sure that you've added dependencies and have synchronized the build file with the project.**
139+
140+
We also want to create a connection to our database. We'll keep this connection in a member field:
141141

142142
```java
143143
private Firebase mFirebaseRef;
@@ -149,7 +149,7 @@ private Firebase mFirebaseRef;
149149
mFirebaseRef = new Firebase("https://<your-app>.firebaseio.com");
150150
```
151151

152-
Be sure to replace `<your-app>` with the name of the Firebase app you created in the first section.
152+
**Be sure to replace `<your-app>` with the name of the Firebase app you created in the first section.**
153153

154154
![MainActivity with setAndroidContext and mFirebaseRef](images/3_4.png)
155155

@@ -161,7 +161,7 @@ Next we'll send data to Firebase! In this step we'll allow the user to enter a m
161161

162162
![Data dashboard and app for sending a message](images/4_1.png)
163163

164-
1. We'll first add the necessary views to activity_main.xml:
164+
We'll first add the necessary views to activity_main.xml:
165165

166166
```xml
167167
<LinearLayout
@@ -185,20 +185,20 @@ Next we'll send data to Firebase! In this step we'll allow the user to enter a m
185185
</LinearLayout>
186186
```
187187

188-
This layout puts a horizontal bar at the bottom that contains an `EditText`, where the user can enter their chat message, and a `Button` that they can click to send the message.
188+
This layout puts a horizontal bar at the bottom that contains an `EditText`, where the user can enter their chat message, and a `Button` that they can click to send the message.
189189

190-
![Activity_main.xml with footer](images/4_2.png)
190+
![Activity_main.xml with footer](images/4_2.png)
191191

192-
2. In our `MainActivity.java` we'll now add variables for the `EditText` and `Button` at the end of the onCreate method:
192+
In our `MainActivity.java` we'll now add variables for the `EditText` and `Button` at the end of the onCreate method:
193193

194194
```java
195195
final EditText textEdit = (EditText) this.findViewById(R.id.text_edit);
196196
Button sendButton = (Button) this.findViewById(R.id.send_button);
197197
```
198198

199-
![MainActivity.java with EditText and Button bound](images/4_3.png)
199+
![MainActivity.java with EditText and Button bound](images/4_3.png)
200200

201-
3. Next, we'll add a method that grabs the text from the input and send it to our Firebase database:
201+
Next, we'll add a method that grabs the text from the input and send it to our Firebase database:
202202

203203
```java
204204
sendButton.setOnClickListener(new View.OnClickListener() {
@@ -214,29 +214,31 @@ sendButton.setOnClickListener(new View.OnClickListener() {
214214
});
215215
```
216216

217-
You will have to import the packages for some of these classes. Android Studio will tell you where to import them from.
217+
You will have to import the packages for some of these classes. Android Studio will tell you where to import them from.
218+
219+
Here we grab the message from the EditText, add it to a Map, and send it off to Firebase. We'll look at a way to replace that Map with something more type-safe in the next section, but for now this will work.
218220

219-
Here we grab the message from the EditText, add it to a Map, and send it off to Firebase. We'll look at a way to replace that Map with something more type-safe in the next section, but for now this will work.
221+
We hard-coded our user name for the moment. We'll use Firebase Authentication to make this dynamic in the last section of this code lab.
220222

221-
We hard-coded our user name for the moment. We'll use Firebase Authentication to make this dynamic in the last section of this code lab.
223+
![onCreate with sendButton implemented](images/4_4.png)
222224

223-
![onCreate with sendButton implemented](images/4_4.png)
225+
If you now run the application in the emulator, you will see an input field with a Send button that sends the message to Firebase. Open the URL of your Firebase database, and you'll see it light up green as you add new messages.
224226

225-
5. If you now run the application in the emulator, you will see an input field with a Send button that sends the message to Firebase. Open the URL of your Firebase database, and you'll see it light up green as you add new messages.
226-
6. Open the Data tab in the Firebase Dashboard of your app. You'll see it light up green as you add new messages. Admit it, this is pretty cool!
227+
Open the Data tab in the Firebase Dashboard of your app. You'll see it light up green as you add new messages. Admit it, this is pretty cool!
227228

228229
Now that we can send messages to Firebase, it is time for the next step: making the messages show up in our Android app in realtime.
229230

230231
## Show the (existing and new) messages
231232

232233
A chat app that doesn’t show existing messages is not very useful. So in this step we’ll add a list of the existing messages to our Android app. And since we're using Firebase, new chat messages will be added to this list automatically. At the end of this section we’ll have a fully functional chat app.
233234

234-
<img alt="Chat messages Android app and new message" src="images/5_1.png" height="600">
235+
![Chat messages Android app and new message](images/5_1.png)
235236

236237
Let's take this in chunks: first we'll create a Java class to represent each message, then we'll create an Adapter that gets each of the messages from Firebase and puts them into a ListView.
237238

238-
1. As you can see in the screenshot, each chat message has the same layout. Instead of creating a custom layout, we'll use one of the built-in layouts of Android: `android.R.layout.two_line_list_item`. We'll show the user name on the first line (in bold) and the message text on the second line.
239-
2. Create a class `ChatMessage.java` that wraps the username and text message:
239+
As you can see in the screenshot, each chat message has the same layout. Instead of creating a custom layout, we'll use one of the built-in layouts of Android: `android.R.layout.two_line_list_item`. We'll show the user name on the first line (in bold) and the message text on the second line.
240+
241+
Create a class `ChatMessage.java` that wraps the username and text message:
240242

241243
```java
242244
public class ChatMessage {
@@ -261,15 +263,15 @@ public class ChatMessage {
261263
}
262264
```
263265

264-
As you can see, this is plain-old Java object. But it’s a POJO with some special traits. First `ChatMessage` follows a JavaBean pattern for its property names. The `getName` method is a getter for a `name` property, while `getText()` is a getter for a `text` property. And second, those property names correspond to the ones we’ve been using when we sent messages to Firebase in our `OnClickListener`.
266+
As you can see, this is plain-old Java object. But it’s a POJO with some special traits. First `ChatMessage` follows a JavaBean pattern for its property names. The `getName` method is a getter for a `name` property, while `getText()` is a getter for a `text` property. And second, those property names correspond to the ones we’ve been using when we sent messages to Firebase in our `OnClickListener`.
265267

266-
![ChatMessage.java](images/5_3.png)
268+
![ChatMessage.java](images/5_3.png)
267269

268-
Warning: if you end up making this `ChatMessage` an inner class of another class, you must make it static: `public static class ChatMessage`.
270+
Warning: if you end up making this `ChatMessage` an inner class of another class, you must make it static: `public static class ChatMessage`.
269271

270-
3. With the layout for the message specified and their structure defined in a class, we need to make a space for them in the `main_activity.xml`
272+
With the layout for the message specified and their structure defined in a class, we need to make a space for them in the `main_activity.xml`
271273

272-
Add a ListView with `android:id="@android:id/list"`` above the LinearLayout:
274+
Add a ListView with `android:id="@android:id/list"`` above the LinearLayout:
273275

274276
```xml
275277
<ListView
@@ -279,29 +281,29 @@ public class ChatMessage {
279281
android:layout_above="@+id/footer"/>
280282
```
281283

282-
This is the container that all messages will be added to: one message_layout for each ChatMessage.
284+
This is the container that all messages will be added to: one message_layout for each ChatMessage.
283285

284-
![activity_main.xml with ListView](images/5_4.png)
286+
![activity_main.xml with ListView](images/5_4.png)
285287

286-
The `id` value is very important here, since Android's `ListActivity` uses it to find the `ListView`. So make sure to enter it exactly as specified: ``@android:id/list`.
288+
The `id` value is very important here, since Android's `ListActivity` uses it to find the `ListView`. So make sure to enter it exactly as specified: ``@android:id/list`.
287289

288-
4. Make the `MainActivity` class descend from `ListActivity`. This is a built-in Android base-class. By deriving from this, our activity will automatically have access to the ListView we added to the layout:
290+
Make the `MainActivity` class descend from `ListActivity`. This is a built-in Android base-class. By deriving from this, our activity will automatically have access to the ListView we added to the layout:
289291

290292
```java
291293
public class MainActivity extends ListActivity {
292294
```
293295

294-
5. We're ready to start on our ListAdapter, which we'll base on the `FirebaseListAdapter` from the firebase-ui project we imported. `The FirebaseListAdapter` class adapts a Firebase collection so that it becomes usable in an Android `ListView`. First we'll add a member to our `MainActivity`:
296+
We're ready to start on our ListAdapter, which we'll base on the `FirebaseListAdapter` from the firebase-ui project we imported. `The FirebaseListAdapter` class adapts a Firebase collection so that it becomes usable in an Android `ListView`. First we'll add a member to our `MainActivity`:
295297

296298
```java
297299
public class MainActivity extends ListActivity {
298300
private Firebase mFirebaseRef;
299301
FirebaseListAdapter<ChatMessage> mListAdapter;
300302
```
301303

302-
![MainActivity extends ListActivity](images/5_5.png)
304+
![MainActivity extends ListActivity](images/5_5.png)
303305

304-
6. To make everything come together, we add this to the onCreate method of our MainActivity:
306+
To make everything come together, we add this to the onCreate method of our MainActivity:
305307

306308
```java
307309
mListAdapter = new FirebaseListAdapter<ChatMessage>(this, ChatMessage.class,
@@ -315,13 +317,13 @@ mListAdapter = new FirebaseListAdapter<ChatMessage>(this, ChatMessage.class,
315317
setListAdapter(mListAdapter);
316318
```
317319

318-
The FirebaseListAdapter maps the data from your Firebase database into the ListView that you added to the layout. It creates a new instance of your `two_line_list_item` for each `ChatMessage` and calls the `populateView` method. We override this method and put the name and text in the correct subviews.
320+
The FirebaseListAdapter maps the data from your Firebase database into the ListView that you added to the layout. It creates a new instance of your `two_line_list_item` for each `ChatMessage` and calls the `populateView` method. We override this method and put the name and text in the correct subviews.
319321

320-
![MainActivity code](images/5_6.png)
322+
![MainActivity code](images/5_6.png)
321323

322-
7. Don't worry, the hardest part is behind us now. All that is left in this step is some clean-up. But before that, run your app and see that it shows all existing messages. And if you send a new message, it shows up in the emulator and in your Firebase dashboard.
324+
Don't worry, the hardest part is behind us now. All that is left in this step is some clean-up. But before that, run your app and see that it shows all existing messages. And if you send a new message, it shows up in the emulator and in your Firebase dashboard.
323325
324-
8. The cleanup is minor, but it's important to keep our code as readable as possible at all times. Remember that onSendButtonClick method that we wrote in step 5? That use of a Map looked a bit messy. Now that we have a ChatMessage class, we can make it much more readable:
326+
The cleanup is minor, but it's important to keep our code as readable as possible at all times. Remember that onSendButtonClick method that we wrote in step 5? That use of a Map looked a bit messy. Now that we have a ChatMessage class, we can make it much more readable:
325327

326328
```java
327329
sendButton.setOnClickListener(new View.OnClickListener() {
@@ -335,7 +337,7 @@ sendButton.setOnClickListener(new View.OnClickListener() {
335337
});
336338
```
337339

338-
9. Finally, we also need to clean up our list adapter when the activity is destroyed. This will close the connection to the Firebase server, when the activity is not showing.
340+
Finally, we also need to clean up our list adapter when the activity is destroyed. This will close the connection to the Firebase server, when the activity is not showing.
339341

340342
```java
341343
@Override
@@ -345,19 +347,19 @@ protected void onDestroy() {
345347
}
346348
```
347349

348-
![MainActivity showing OnClickListener and onDestroy](images/5_7.png)
350+
![MainActivity showing OnClickListener and onDestroy](images/5_7.png)
349351

350352
In this section we made our app show the chat messages. It was a lot of work, but in the end you can see that the Java code for our main activity still fits in a single screenshot.
351353

352354
## Enable e-mail+password login
353355

354356
As a final step, we're going to allow the users of our app to log in using email and password.
355357

356-
1. In the Login & Auth tab of your Firebase dashboard, enable Email & Password authentication
358+
In the Login & Auth tab of your Firebase dashboard, enable Email & Password authentication
357359

358360
![Enable email+password auth in dashboard](images/6_1.png)
359361

360-
2. First add a button to the top right of activity_main.xml
362+
First add a button to the top right of activity_main.xml
361363

362364
```xml
363365
<Button
@@ -372,7 +374,7 @@ As a final step, we're going to allow the users of our app to log in using email
372374

373375
![main_activity.xml with login button](images/6_2.png)
374376

375-
3. Extend FirebaseLoginBaseActivity
377+
Extend FirebaseLoginBaseActivity
376378

377379
Although extending `ListActivity` was useful earlier, when it saved some lines of code, it's now more important that we extend `FirebaseLoginBaseActivity`.
378380

@@ -421,7 +423,7 @@ protected void onFirebaseLoginUserError(FirebaseLoginError firebaseLoginError) {
421423

422424
![Add Firebase event handlers](images/6_3.5.png)
423425

424-
4. Enable Password Authentication
426+
Enable Password Authentication
425427

426428
```java
427429
@Override
@@ -433,7 +435,7 @@ protected void onStart() {
433435

434436
![Enable PASSWORD auth](images/6_4.png)
435437

436-
5. Wire up login button
438+
Wire up login button
437439

438440
```java
439441
Button loginButton = (Button) this.findViewById(R.id.login);
@@ -454,17 +456,13 @@ Now go into your Firebase Dashboard and go to the Auth tab and select "Email/Pas
454456
455457
This is also where you can configure the password reset emails that you can send to your users, in case they forgot their password.
456458
457-
6. Log in with your new user.
458-
459-
<img alt="Chat app with login" src="images/0_1.png" height="600">
460-
461459
## Wrap-up
462460
463461
Wrap-up
464462
465463
Congratulations! You've just built a fully functional multi-user chat application that uses Firebase to store the data and authentication users.
466464

467-
<img alt="Chat app with login" src="images/0_0.png" height="600">
465+
![Chat app with login](images/0_0.png)
468466

469467
As a reward for finishing the codelab you’ve earned a promo code! When you’re ready to put your Firebase app in production, you can use the promo code `androidcodelab49` for $49 off your first month of a paid Firebase plan. Just enter the code when you upgrade your Firebase.
470468

0 commit comments

Comments
 (0)