使用Firebase ,创建实时社交应用程序就像在公园里散步一样。 最好的事情是:您不必编写任何一行服务器端代码。
在本教程中,我将向您展示如何利用Firebase UI创建可以与朋友共享的gro聊天应用程序。 这将是一个非常简单的应用程序,只有一个聊天室,并且向所有用户开放。
您可能已经猜到了,该应用将依靠Firebase Auth来管理用户注册和登录。它还将使用Firebase的实时数据库来存储群聊消息。
先决条件
为了能够按照本分步教程进行操作,您需要满足以下条件:
- 最新版本的Android Studio
- Firebase帐户
1.创建一个Android Studio项目
启动Android Studio并创建一个名为MainActivity的空活动的新项目。
要将项目配置为使用Firebase平台,请通过单击工具> Firebase打开Firebase助手窗口。
使用Firebase平台时,通常最好将Firebase Analytics添加到项目中。 因此,在Firebase Assistant窗口中,转到“ 分析”部分,然后按“ 记录分析事件” 。
接下来,按“ 连接到Firebase”按钮,并确保已选中“ 创建新的Firebase项目”选项。 建立连接后,请按添加分析到您的应用程序按钮。
此时,Android Studio项目不仅已与Firebase Analytics集成,还可以使用所有其他Firebase服务。
2.添加依赖项
在此项目中,我们将使用两个库:Firebase UI和Android设计支持库。 因此,打开app
模块的build.gradle文件,并向其添加以下compile
依赖项:
compile 'com.android.support:design:23.4.0'
compile 'com.firebaseui:firebase-ui:0.6.0'
按立即同步按钮以更新项目。
3.定义布局
已经绑定到MainActivity
的activity_main.xml文件定义了应用程序主屏幕的内容。 换句话说,它将代表聊天室。
像今天可用的大多数其他群聊应用一样,我们的应用将具有以下UI元素:
- 以时间顺序显示所有群聊消息的列表
- 用户可以在其中输入新消息的输入字段
- 用户可以按下以发布消息的按钮
因此, activity_main.xml必须具有ListView
, EditText
和FloatingActionButton
。 将它们全部放置在RelativeLayout
小部件中后,布局XML应该如下所示:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
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.tutsplus.mychatapp.MainActivity">
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:src="@drawable/ic_send_black_24dp"
android:id="@+id/fab"
android:tint="@android:color/white"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
app:fabSize="mini" />
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/fab"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Input"
android:id="@+id/input"
/>
</android.support.design.widget.TextInputLayout>
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_above="@id/fab"
android:dividerHeight="16dp"
android:divider="@android:color/transparent"
android:id="@+id/list_of_messages"
android:layout_marginBottom="16dp"/>
</RelativeLayout>
请注意,我已将EditText
小部件放置在TextInputLayout
小部件内。 这样做会在EditText
添加一个浮动标签,如果您要遵守材质设计准则,则这很重要。
现在主屏幕的布局已准备就绪,我们可以继续创建聊天消息的布局,该布局将是ListView
项目。 首先创建一个名为message.xml的新布局XML文件,其根元素为RelativeLayout
。
布局必须具有TextView
小部件以显示聊天消息的文本,发送时间和其作者。 您可以自由地以任何顺序放置它们。 这是我将要使用的布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:id="@+id/message_user"
android:textStyle="normal|bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/message_user"
android:layout_alignParentEnd="true"
android:id="@+id/message_time" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/message_user"
android:layout_alignParentStart="true"
android:layout_marginTop="5dp"
android:id="@+id/message_text"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textSize="18sp" />
</RelativeLayout>
4.处理用户身份验证
允许用户匿名将消息发布到聊天室将是一个非常糟糕的主意。 这可能会导致垃圾邮件,安全性问题,并给用户带来不太理想的聊天体验。 因此,让我们现在配置我们的应用程序,以便只有注册用户才能阅读和发布消息。
首先转到Firebase控制台的“身份验证”部分,然后将“ 电子邮件/密码”启用为登录提供程序。
也可以随意启用OAuth 2.0登录提供程序。 但是,FirebaseUI v0.6.0无缝地仅支持Google登录和Facebook登录。
步骤1:处理用户登录
该应用程序启动后,必须检查用户是否已登录。如果已登录,则该应用程序应继续并显示聊天室的内容。 否则,它必须将用户重定向到登录屏幕或注册屏幕。 使用FirebaseUI,创建这些屏幕所需的代码比您想象的要少得多。
在MainActivity
的onCreate()
方法中,通过检查当前FirebaseUser
对象是否不为null
来检查用户是否已经登录。 如果为null
,则必须创建并配置一个Intent
对象,该对象打开登录活动。 为此,请使用SignInIntentBuilder
类。 准备好意图后,您必须使用startActivityForResult()
方法启动登录活动。
请注意,登录活动还允许新用户注册。 因此,您无需编写任何其他代码来处理用户注册。
将以下代码添加到onCreate()
方法中:
if(FirebaseAuth.getInstance().getCurrentUser() == null) {
// Start sign in/sign up activity
startActivityForResult(
AuthUI.getInstance()
.createSignInIntentBuilder()
.build(),
SIGN_IN_REQUEST_CODE
);
} else {
// User is already signed in. Therefore, display
// a welcome Toast
Toast.makeText(this,
"Welcome " + FirebaseAuth.getInstance()
.getCurrentUser()
.getDisplayName(),
Toast.LENGTH_LONG)
.show();
// Load chat room contents
displayChatMessages();
}
如您在上面的代码中看到的,如果用户已经登录,我们首先显示Toast
欢迎用户,然后调用名为displayChatMessages的方法。 现在,只需为其创建一个存根即可。 稍后我们将向其添加代码。
private void displayChatMessages() {
}
用户登录后, MainActivity
将收到一个Intent
形式的结果。 要处理它,您必须重写onActivityResult()
方法。
如果结果的代码为RESULT_OK
,则表示用户已成功登录。 如果是这样,则必须再次调用displayChatMessages()
方法。 否则,请调用finish()
以关闭应用程序。
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == SIGN_IN_REQUEST_CODE) {
if(resultCode == RESULT_OK) {
Toast.makeText(this,
"Successfully signed in. Welcome!",
Toast.LENGTH_LONG)
.show();
displayChatMessages();
} else {
Toast.makeText(this,
"We couldn't sign you in. Please try again later.",
Toast.LENGTH_LONG)
.show();
// Close the app
finish();
}
}
}
此时,您可以运行该应用程序并查看登录和注册屏幕。
步骤2:处理使用者登出
默认情况下,FirebaseUI使用“ 智能锁定”作为“密码” 。 因此,一旦用户登录,即使重新启动该应用程序,他们也将保持登录状态。 为了允许用户注销,我们现在将注销选项添加到MainActivity
的溢出菜单中。
创建一个名为main_menu.xml的新菜单资源文件,并向其中添加一个item
,其title
属性设置为Sign out 。 该文件的内容应如下所示:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:title="Sign out" app:showAsAction="never"
android:id="@+id/menu_sign_out"/>
</menu>
要实例化MainActivity
内部的菜单资源,请重写onCreateOptionsMenu()
方法并调用MenuInflater
对象的MenuInflater
inflate()
方法。
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
return true;
}
接下来,重写onOptionsItemSelected()
方法以处理菜单项上的单击事件。 在该方法内部,可以调用AuthUI
类的AuthUI
signOut()
方法将用户注销。 由于注销操作是异步执行的,因此我们还将向其添加一个OnCompleteListener
。
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == R.id.menu_sign_out) {
AuthUI.getInstance().signOut(this)
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
Toast.makeText(MainActivity.this,
"You have been signed out.",
Toast.LENGTH_LONG)
.show();
// Close activity
finish();
}
});
}
return true;
}
用户退出后,该应用应会自动关闭。 这就是为什么您在上面的代码中看到对finish()
方法的调用的原因。
5.建立模型
为了将聊天消息存储在Firebase实时数据库中,您必须为它们创建一个模型。 我们在本教程前面创建的聊天消息的布局具有三个视图。 为了能够填充这些视图,模型也必须至少具有三个字段。
创建一个名为ChatMessage.java的新Java类, 并向其中添加三个成员变量: messageText
, messageUser
和messageTime
。 还添加一个构造函数来初始化这些变量。
为了使模型与FirebaseUI兼容,还必须向其中添加默认构造函数,以及所有成员变量的getter和setter方法。
此时, ChatMessage
类应如下所示:
public class ChatMessage {
private String messageText;
private String messageUser;
private long messageTime;
public ChatMessage(String messageText, String messageUser) {
this.messageText = messageText;
this.messageUser = messageUser;
// Initialize to current time
messageTime = new Date().getTime();
}
public ChatMessage(){
}
public String getMessageText() {
return messageText;
}
public void setMessageText(String messageText) {
this.messageText = messageText;
}
public String getMessageUser() {
return messageUser;
}
public void setMessageUser(String messageUser) {
this.messageUser = messageUser;
}
public long getMessageTime() {
return messageTime;
}
public void setMessageTime(long messageTime) {
this.messageTime = messageTime;
}
}
6.发布聊天消息
现在模型已经准备就绪,我们可以轻松地将新的聊天消息添加到Firebase实时数据库。
要发布新消息,用户将按下FloatingActionButton
。 因此,必须向其添加OnClickListener
。
在侦听器内部,您必须首先使用FirebaseDatabase
类的getReference()
方法获取一个DatabaseReference
对象。 然后,您可以调用push()
和setValue()
方法,将ChatMessage
类的新实例添加到实时数据库中。
当然,必须使用EditText
的内容和当前登录用户的显示名称来初始化ChatMessage
实例。
因此,将以下代码添加到onCreate()
方法中:
FloatingActionButton fab =
(FloatingActionButton)findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
EditText input = (EditText)findViewById(R.id.input);
// Read the input field and push a new instance
// of ChatMessage to the Firebase database
FirebaseDatabase.getInstance()
.getReference()
.push()
.setValue(new ChatMessage(input.getText().toString(),
FirebaseAuth.getInstance()
.getCurrentUser()
.getDisplayName())
);
// Clear the input
input.setText("");
}
});
Firebase实时数据库中的数据始终存储为键值对。 但是,如果您观察上面的代码,则会看到我们在不指定任何键的情况下调用setValue()
。 之所以允许这样做,是因为在调用setValue()
方法之前先调用了push()
方法,该方法会自动生成一个新密钥。
7.显示聊天消息
FirebaseUI有一个非常方便的类,称为FirebaseListAdapter ,该类大大减少了使用Firebase实时数据库中存在的数据填充ListView
所需的工作。 我们现在将使用它来获取和显示数据库中存在的所有ChatMessage
对象。
将FirebaseListAdapter
对象添加为MainActivity
类的新成员变量。
private FirebaseListAdapter<ChatMessage> adapter;
在displayChatMessages()
方法内部,使用其构造函数初始化适配器,该构造函数需要以下参数:
- 对
Activity
的引用
- 您感兴趣的对象的
class
- 列表项的布局
-
DatabaseReference
对象
FirebaseListAdapter
是一个抽象类,并具有一个抽象populateView()
方法,该方法必须被覆盖。
顾名思义, populateView()
用于填充每个列表项的视图。 如果您熟悉ArrayAdapter
类,则可以将populateView()
视为getView()
方法的替代方法。
在方法内部,必须首先使用findViewById()
获取对message.xml布局文件中存在的每个TextView
的引用。 然后,您可以调用它们的setText()
方法,并使用ChatMessage
类的getter填充它们。
此时, displayChatMessages()
方法的内容应如下所示:
ListView listOfMessages = (ListView)findViewById(R.id.list_of_messages);
adapter = new FirebaseListAdapter<ChatMessage>(this, ChatMessage.class,
R.layout.message, FirebaseDatabase.getInstance().getReference()) {
@Override
protected void populateView(View v, ChatMessage model, int position) {
// Get references to the views of message.xml
TextView messageText = (TextView)v.findViewById(R.id.message_text);
TextView messageUser = (TextView)v.findViewById(R.id.message_user);
TextView messageTime = (TextView)v.findViewById(R.id.message_time);
// Set their text
messageText.setText(model.getMessageText());
messageUser.setText(model.getMessageUser());
// Format the date before showing it
messageTime.setText(DateFormat.format("dd-MM-yyyy (HH:mm:ss)",
model.getMessageTime()));
}
};
listOfMessages.setAdapter(adapter);
群聊应用已准备就绪。 运行它并发布新消息,以查看它们立即在ListView
弹出。 如果您与朋友共享该应用程序,那么他们发布后也应该能够看到他们的消息。
结论
在本教程中,您学习了如何使用Firebase和FirebaseUI创建一个非常简单的群聊应用程序。 您还看到了使用FirebaseUI中可用的类来快速创建新屏幕并实现复杂功能的过程非常容易。
翻译自: https://code.tutsplus.com/tutorials/how-to-create-an-android-chat-app-using-firebase--cms-27397