如何使用Firebase創建Android聊天應用程序
() translation by (you can also view the original English article)



使用Firebase創建實時社交應用程序很簡單。 而且您不必編寫壹行服務器端代碼。
在本教程中,我將展示如何利用Firebase UI創建聊天應用程序,您可以與您的朋友分享。 這是壹個非常簡單的應用程序,只有壹個聊天室,對所有用戶開放。
機智如妳,該應用程序依賴於Firebase Auth來管理用戶註冊並登錄。 還使用Firebase的實時數據庫來存儲聊天消息。
準備工作
為了與本教程保持壹致,需要註意以下幾點:
-
最新版本的Android Studio
- 壹個Firebase帳號
如何設置Firebase帳戶並為Android Studio中的Firebase開發做好準備,請參閱Envato Tuts +上我的教程 “入門Firebase for Android”。
1.創建壹個Android Studio項目
啟動Android Studio並創建壹個名為MainActivity的空activity的新項目。



要將項目配置為使用Firebase平臺,請單擊“ 工具”>“Firebase”,打開“Firebase Assistant”窗口。
在使用Firebase平臺的同時,最好將Firebase Analytics添加到項目中。 因此,在Firebase Assistant窗口中,進入Google Analytics(分析)部分,然後點擊Log an Google Analytics(分析)事件。



接下來,點擊“ 連接到Firebase”按鈕,確保選擇了“ 創建新的Firebase項目”選項。 建立連接後,點擊“ 添加Google Analytics(分析)”按鈕。



此時,Android Studio項目不僅集成Firebase Analytics,還可以使用所有其他Firebase服務。
2.添加依賴關系
我們將在此項目中使用兩個庫:Firebase UI和Android設計支持庫。 因此,打開app
模塊的build.gradle文件並添加以下compile
依賴項:
1 |
compile 'com.android.support:design:23.4.0' |
2 |
compile 'com.firebaseui:firebase-ui:0.6.0' |
點擊“ 立即同步”按鈕更新項目。
3.定義布局
已經綁定到MainActivity
的activity_main.xml文件定義了應用程序主界面的內容。 換句話說,它就是聊天室的界面。
像今天可用的其他大多數聊天應用程序壹樣,我們的應用程序具有以下UI元素:
- 按時間順序顯示所有群組聊天消息列表
- 用戶可以輸入新消息的輸入框
- 可以發布消息的按鈕
因此,activity_main.xml必須有ListView
、EditText
和FloatingActionButton
。 將它們全部放入RelativeLayout
布局後,您的布局XML應如下所示:
1 |
<?xml version="1.0" encoding="utf-8"?>
|
2 |
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android" |
3 |
xmlns:app="http://schemas.android.com/apk/res-auto" |
4 |
xmlns:tools="http://schemas.android.com/tools" |
5 |
android:id="@+id/activity_main" |
6 |
android:layout_width="match_parent" |
7 |
android:layout_height="match_parent" |
8 |
android:paddingBottom="@dimen/activity_vertical_margin" |
9 |
android:paddingLeft="@dimen/activity_horizontal_margin" |
10 |
android:paddingRight="@dimen/activity_horizontal_margin" |
11 |
android:paddingTop="@dimen/activity_vertical_margin" |
12 |
tools:context="com.tutsplus.mychatapp.MainActivity"> |
13 |
|
14 |
<android.support.design.widget.FloatingActionButton
|
15 |
android:layout_width="wrap_content" |
16 |
android:layout_height="wrap_content" |
17 |
android:clickable="true" |
18 |
android:src="@drawable/ic_send_black_24dp" |
19 |
android:id="@+id/fab" |
20 |
android:tint="@android:color/white" |
21 |
android:layout_alignParentBottom="true" |
22 |
android:layout_alignParentEnd="true" |
23 |
app:fabSize="mini" /> |
24 |
|
25 |
<android.support.design.widget.TextInputLayout
|
26 |
android:layout_width="match_parent" |
27 |
android:layout_height="wrap_content" |
28 |
android:layout_toLeftOf="@id/fab" |
29 |
android:layout_alignParentBottom="true" |
30 |
android:layout_alignParentStart="true"> |
31 |
|
32 |
<EditText
|
33 |
android:layout_width="match_parent" |
34 |
android:layout_height="wrap_content" |
35 |
android:hint="Input" |
36 |
android:id="@+id/input" |
37 |
/>
|
38 |
</android.support.design.widget.TextInputLayout>
|
39 |
|
40 |
<ListView
|
41 |
android:layout_width="match_parent" |
42 |
android:layout_height="match_parent" |
43 |
android:layout_alignParentTop="true" |
44 |
android:layout_alignParentStart="true" |
45 |
android:layout_above="@id/fab" |
46 |
android:dividerHeight="16dp" |
47 |
android:divider="@android:color/transparent" |
48 |
android:id="@+id/list_of_messages" |
49 |
android:layout_marginBottom="16dp"/> |
50 |
</RelativeLayout>
|
請註意,我把EditText
控件放在TextInputLayout
控件中。 這樣做會給EditText
添加壹個浮動標簽,這樣可以體現MD風格。
現在主界面的布局已經準備好了,我們可以繼續創建聊天消息的布局,ListView
裏面的子item單元。 首先創建壹個名為message.xml的新布局XML文件,該文件的根元素是RelativeLayout
。
該布局必須有TextView
框架來顯示聊天消息的文本,發送的時間及作者。 妳可以隨意放置他們的順序。 布局如下:
1 |
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" |
2 |
android:layout_width="match_parent" android:layout_height="match_parent"> |
3 |
|
4 |
<TextView
|
5 |
android:layout_width="wrap_content" |
6 |
android:layout_height="wrap_content" |
7 |
android:layout_alignParentTop="true" |
8 |
android:layout_alignParentStart="true" |
9 |
android:id="@+id/message_user" |
10 |
android:textStyle="normal|bold" /> |
11 |
|
12 |
<TextView
|
13 |
android:layout_width="wrap_content" |
14 |
android:layout_height="wrap_content" |
15 |
android:layout_alignBottom="@+id/message_user" |
16 |
android:layout_alignParentEnd="true" |
17 |
android:id="@+id/message_time" /> |
18 |
|
19 |
<TextView
|
20 |
android:layout_width="wrap_content" |
21 |
android:layout_height="wrap_content" |
22 |
android:layout_below="@+id/message_user" |
23 |
android:layout_alignParentStart="true" |
24 |
android:layout_marginTop="5dp" |
25 |
android:id="@+id/message_text" |
26 |
android:textAppearance="@style/TextAppearance.AppCompat.Body1" |
27 |
android:textSize="18sp" /> |
28 |
</RelativeLayout>
|
4.處理用戶認證
最好不要允許用戶匿名發布消息到聊天室。 這可能會導致垃圾郵件,安全問題以及不太理想的聊天體驗。 因此,讓我們現在配置我們的應用程序,只有註冊用戶才可以讀取和發送消息。
先從Firebase Console的Auth部分開始,並啟用Email / Password作為登錄提供者。



免費啟用OAuth 2.0登錄提供商。 然而,FirebaseUI v0.6.0無縫地支持Google登錄和Facebook登錄。
步驟1:處理用戶登錄
壹旦應用程序啟動,它必須檢查用戶是否登錄。 登錄後,該應用程序應該繼續顯示聊天室的內容。 否則,它必須將用戶重定向到登錄界面或註冊界面。 使用FirebaseUI創建這些界面比您想像的代碼少得多。
在MainActivity
的onCreate
()方法中,通過檢查當前FirebaseUser
對象是否為null
來檢查用戶是否已經登錄。 如果FirebaseUser對象是null
,您必須創建並配置Intent
對象來打開登錄activity。 為此,請使用SignInIntentBuilder
類。 壹旦Intent準備就緒,您必須使用startActivityForResult
()方法啟動登錄activity。
請註意,登錄activity還允許新用戶註冊。 因此,您沒有寫任何額外的代碼來處理用戶註冊。
將以下代碼添加到onCreate
()方法中:
1 |
if(FirebaseAuth.getInstance().getCurrentUser() == null) { |
2 |
// Start sign in/sign up activity
|
3 |
startActivityForResult( |
4 |
AuthUI.getInstance() |
5 |
.createSignInIntentBuilder() |
6 |
.build(), |
7 |
SIGN_IN_REQUEST_CODE
|
8 |
);
|
9 |
} else { |
10 |
// User is already signed in. Therefore, display
|
11 |
// a welcome Toast
|
12 |
Toast.makeText(this, |
13 |
"Welcome " + FirebaseAuth.getInstance() |
14 |
.getCurrentUser() |
15 |
.getDisplayName(), |
16 |
Toast.LENGTH_LONG) |
17 |
.show(); |
18 |
|
19 |
// Load chat room contents
|
20 |
displayChatMessages(); |
21 |
}
|
如上面的代碼所示,如果用戶已經登錄,我們首先顯示壹個Toast
歡迎用戶,然後調用名為displayChatMessages的方法。 現在,只需創建壹個存根。 稍後我們會添加代碼。
1 |
private void displayChatMessages() { |
2 |
|
3 |
}
|
壹旦用戶登錄,MainActivity
將收到壹個Intent
形式的結果。 必須重寫onActivityResult
()方法才來處理它。
如果結果的代碼是RESULT_OK
,則表示用戶已成功登錄。 如果是這樣,妳必須()再次調用displayChatMessages
方法。 否則,請調用finish
()方法關閉應用程序。
1 |
@Override
|
2 |
protected void onActivityResult(int requestCode, int resultCode, |
3 |
Intent data) { |
4 |
super.onActivityResult(requestCode, resultCode, data); |
5 |
|
6 |
if(requestCode == SIGN_IN_REQUEST_CODE) { |
7 |
if(resultCode == RESULT_OK) { |
8 |
Toast.makeText(this, |
9 |
"Successfully signed in. Welcome!", |
10 |
Toast.LENGTH_LONG) |
11 |
.show(); |
12 |
displayChatMessages(); |
13 |
} else { |
14 |
Toast.makeText(this, |
15 |
"We couldn't sign you in. Please try again later.", |
16 |
Toast.LENGTH_LONG) |
17 |
.show(); |
18 |
|
19 |
// Close the app
|
20 |
finish(); |
21 |
}
|
22 |
}
|
23 |
|
24 |
}
|
現在,您可以運行應用程序,並查看登錄和註冊屏幕。



步驟2:處理用戶註銷
默認情況下,FirebaseUI使用Smart Lock進行密碼管理。 因此,壹旦用戶登錄,即使應用重新啟動,他們也將保持登錄狀態。 為了允許用戶註銷,我們現在將在MainActivity
的菜單中添加壹個退出選項。
創建壹個名為main_menu.xml的新菜單資源文件,並向其添加壹個item
,其title
屬性設置為註銷。 該文件的內容應如下:
1 |
<menu xmlns:android="http://schemas.android.com/apk/res/android" |
2 |
xmlns:app="http://schemas.android.com/apk/res-auto"> |
3 |
|
4 |
<item android:title="Sign out" app:showAsAction="never" |
5 |
android:id="@+id/menu_sign_out"/> |
6 |
|
7 |
</menu>
|
要實例化MainActivity
裏面的菜單資源,重寫onCreateOptionsMenu
()方法並調用MenuInflater
對象的inflate
()方法。
1 |
@Override
|
2 |
public boolean onCreateOptionsMenu(Menu menu) { |
3 |
getMenuInflater().inflate(R.menu.main_menu, menu); |
4 |
return true; |
5 |
}
|
接下來,重寫onOptionsItemSelected
()方法來處理菜單項上的點擊事件。 在該方法中,您可以調用 AuthUI
類的signOut
()方法來簽名用戶。 因為註銷操作是異步執行的,所以我們還會添加壹個OnCompleteListener
。
1 |
@Override
|
2 |
public boolean onOptionsItemSelected(MenuItem item) { |
3 |
if(item.getItemId() == R.id.menu_sign_out) { |
4 |
AuthUI.getInstance().signOut(this) |
5 |
.addOnCompleteListener(new OnCompleteListener<Void>() { |
6 |
@Override
|
7 |
public void onComplete(@NonNull Task<Void> task) { |
8 |
Toast.makeText(MainActivity.this, |
9 |
"You have been signed out.", |
10 |
Toast.LENGTH_LONG) |
11 |
.show(); |
12 |
|
13 |
// Close activity
|
14 |
finish(); |
15 |
}
|
16 |
});
|
17 |
}
|
18 |
return true; |
19 |
}
|
用戶註銷後,應用程式應自動關閉。 這就是為什麽在上面的代碼中調用finish
()方法的原因。
5.創建壹個模型
為了將聊天消息存儲到Firebase實時數據庫中,您必須為它們創建壹個模型。 本教程前面創建的聊天消息的布局有三個視圖。 為了能夠填充這些視圖,模型也必須至少有三個字段。
創建壹個新的Java類ChatMessage.java並添加三個成員變量messageText
、messageUser
和messageTime
。 還要添加壹個構造方法來初始化這些變量。
要使模型與FirebaseUI兼容,您還必須向其添加默認構造方法以及所有成員變量的getter和setter方法。
現在,ChatMessage
類應該如下所示:
1 |
public class ChatMessage { |
2 |
|
3 |
private String messageText; |
4 |
private String messageUser; |
5 |
private long messageTime; |
6 |
|
7 |
public ChatMessage(String messageText, String messageUser) { |
8 |
this.messageText = messageText; |
9 |
this.messageUser = messageUser; |
10 |
|
11 |
// Initialize to current time
|
12 |
messageTime = new Date().getTime(); |
13 |
}
|
14 |
|
15 |
public ChatMessage(){ |
16 |
|
17 |
}
|
18 |
|
19 |
public String getMessageText() { |
20 |
return messageText; |
21 |
}
|
22 |
|
23 |
public void setMessageText(String messageText) { |
24 |
this.messageText = messageText; |
25 |
}
|
26 |
|
27 |
public String getMessageUser() { |
28 |
return messageUser; |
29 |
}
|
30 |
|
31 |
public void setMessageUser(String messageUser) { |
32 |
this.messageUser = messageUser; |
33 |
}
|
34 |
|
35 |
public long getMessageTime() { |
36 |
return messageTime; |
37 |
}
|
38 |
|
39 |
public void setMessageTime(long messageTime) { |
40 |
this.messageTime = messageTime; |
41 |
}
|
42 |
}
|
6.發布聊天消息
現在,該模型已經準備就緒,我們可以輕松地向Firebase實時數據庫添加新的聊天消息。
要發送新消息,用戶要點擊FloatingActionButton
。因此,您必須給它添加OnClickListener
點擊事件。
在監聽器中,您必須首先使用FirebaseDatabase
類的getReference
()方法獲取DatabaseReference
對象。 然後,您可以調用push
()和setValue
()方法將ChatMessage
類的新實例添加到實時數據庫。
這些ChatMessage
實例當然必須使用EditText
的內容進行初始化並且顯示當前登錄的用戶名稱。
因此,將以下代碼添加到onCreate
()方法中:
1 |
FloatingActionButton fab = |
2 |
(FloatingActionButton)findViewById(R.id.fab); |
3 |
|
4 |
fab.setOnClickListener(new View.OnClickListener() { |
5 |
@Override
|
6 |
public void onClick(View view) { |
7 |
EditText input = (EditText)findViewById(R.id.input); |
8 |
|
9 |
// Read the input field and push a new instance
|
10 |
// of ChatMessage to the Firebase database
|
11 |
FirebaseDatabase.getInstance() |
12 |
.getReference() |
13 |
.push() |
14 |
.setValue(new ChatMessage(input.getText().toString(), |
15 |
FirebaseAuth.getInstance() |
16 |
.getCurrentUser() |
17 |
.getDisplayName()) |
18 |
);
|
19 |
|
20 |
// Clear the input
|
21 |
input.setText(""); |
22 |
}
|
23 |
});
|
Firebase實時數據庫中的數據始終作為鍵值對存儲。 但是,如果您遵守上述代碼,您將看到我們調用了setValue
()而沒有指定任何鍵。 這僅僅是因為先調用了push
()方法,該方法自動生成壹個新的鍵。
7.顯示聊天消息
FirebaseUI有壹個非常方便的類FirebaseListAdapter,它大大降低了使用Firebase實時數據庫中存在的數據填充ListView
所需的工作量。 我們現在將使用它來獲取和顯示數據庫中存在的所有ChatMessage
對象。
將FirebaseListAdapter
對象添加為MainActivity
類的新成員變量。
1 |
private FirebaseListAdapter<ChatMessage> adapter; |
在displayChatMessages
()方法中,使用其構造方法初始化適配器,該構造方法需要以下參數:
-
Activity
引用
- 妳感興趣的
class
對象
- 列表子item的布局
- 壹個
DatabaseReference
對象
FirebaseListAdapter
是抽象類,有populateView
()抽象方法,必須被實現該方法。
顧名思義,populateView
()用於填充每個列表項的子item。 如果您熟悉ArrayAdapter
類,您可以將populateView
()方法看作getView
()方法的替代。
在該方法中,您必須首先使用findViewById
()來獲取message.xml布局文件中TextView
的每壹個的引用。 然後,您可以使用ChatMessage
類的getter 來調用它們的setText
()方法並填充它們。
此時,displayChatMessages
()方法的內容應該如下所示:
1 |
ListView listOfMessages = (ListView)findViewById(R.id.list_of_messages); |
2 |
|
3 |
adapter = new FirebaseListAdapter<ChatMessage>(this, ChatMessage.class, |
4 |
R.layout.message, FirebaseDatabase.getInstance().getReference()) { |
5 |
@Override
|
6 |
protected void populateView(View v, ChatMessage model, int position) { |
7 |
// Get references to the views of message.xml
|
8 |
TextView messageText = (TextView)v.findViewById(R.id.message_text); |
9 |
TextView messageUser = (TextView)v.findViewById(R.id.message_user); |
10 |
TextView messageTime = (TextView)v.findViewById(R.id.message_time); |
11 |
|
12 |
// Set their text
|
13 |
messageText.setText(model.getMessageText()); |
14 |
messageUser.setText(model.getMessageUser()); |
15 |
|
16 |
// Format the date before showing it
|
17 |
messageTime.setText(DateFormat.format("dd-MM-yyyy (HH:mm:ss)", |
18 |
model.getMessageTime())); |
19 |
}
|
20 |
};
|
21 |
|
22 |
listOfMessages.setAdapter(adapter); |
群聊應用已準備就緒。 運行它並發送壹條新消息,看到它們立即顯示在ListView
中。 如果您與朋友分享該應用程序,您也可以立即看到他們的發送過來的消息。
結論
在本教程中,您學習了如何使用Firebase和FirebaseUI創建壹個非常簡單的群聊應用程序。 您還看到使用FirebaseUI中的類可以輕松實現快速創建新界面並實現復雜功能。
要了解有關Firebase和FirebaseUI的更多信息,請參閱官方文檔。 或者在Envato Tuts +上查看我們的其他Firebase教程。
- ANDROID SDK開始Firebase for AndroidAshraff Hathibelagal
- ANDROID SDK安卓從無到有:Firebase Crash ReportingFirebase Crash Reporting
- JAVASCRIPT使用Firebase作為後臺支持Reginald Dawson