In this tutorial you will learn to build an android real time chat application using firebase database.
在本教程中,您将学习使用firebase数据库构建一个android实时聊天应用程序。
Before reading this tutorial I hope you are already familiar with basic read and write operations on firebase. If you don’t know then I would recommend you to follow below link to get basic overview about firebase.
在阅读本教程之前,我希望您已经熟悉Firebase上的基本读写操作。 如果您不知道,那么我建议您点击以下链接以获取有关Firebase的基本概述。
Read: https://firebase.google.com/docs/database/android/start/
阅读: https : //firebase.google.com/docs/database/android/start/
I have developed a very basic and simple chat app in which user can login and register in the system and can do one to one chat with other users.
我开发了一个非常简单的基本聊天应用程序,用户可以在该系统中登录和注册,并且可以与其他用户进行一对一聊天。
影片示范 (Video Demo)
Watch below video to see how the app works.
观看下面的视频以了解该应用程序的工作原理。
使用Firebase教程的Android实时聊天应用程序 (Android Real Time Chat Application Using Firebase Tutorial)
火力基地 (Firebase)
Go to firebase console and create a new project.
转到firebase控制台并创建一个新项目。
Link: https://console.firebase.google.com/
链接: https : //console.firebase.google.com/
Select Database option in left sidebar. The database structure used in this project looks as shown in below image.
在左侧边栏中选择数据库选项。 该项目中使用的数据库结构如下图所示。
In my case the database base url is https://android-chat-app-e711d.firebaseio.com/. It will be different in your case so make sure to change the url wherever used in the code.
在我的情况下,数据库基本URL为https://android-chat-app-e711d.firebaseio.com/ 。 您的情况将有所不同,因此请确保在代码中使用的任何地方都更改URL。
You can access the child in form of json data by just adding .json at the end of parent url. For example in this app I have accessed users data by url https://android-chat-app-e711d.firebaseio.com/users.json.
您可以通过在父URL末尾添加.json来以json数据的形式访问子级。 例如,在此应用中,我已通过url https://android-chat-app-e711d.firebaseio.com/users.json访问了用户数据。
Read more about it here https://firebase.google.com/docs/reference/rest/database/
在这里了解更多有关它的信息https://firebase.google.com/docs/reference/rest/database/
Security Rules
安全规则
By default only authenticated user can access the database. When you will go to Rules tab in firebase console project then it may look like this.
默认情况下,只有经过身份验证的用户才能访问数据库。 当您转到Firebase控制台项目中的“规则”选项卡时,它可能看起来像这样。
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
When you try to run the app you may get authentication failure error.
当您尝试运行该应用程序时,可能会收到身份验证失败错误。
So change rules to as shown below.
因此,将规则更改为如下所示。
{
"rules": {
".read": true,
".write": true
}
}
Note: Above security rules will allow anyone to read, write and edit data. That means any user can edit data of any other user. This must not be allowed. So use this security rule only for testing purpose. Don’t use it if you are making the app live in market. To learn more about firebase security rules visit below link.
注意:以上安全规则将允许任何人读取,写入和编辑数据。 这意味着任何用户都可以编辑任何其他用户的数据。 绝对不允许这样做。 因此,仅将此安全规则用于测试目的。 如果您要在市场上发布该应用程序,请不要使用它。 要了解有关Firebase安全规则的更多信息,请访问下面的链接。
https://firebase.google.com/docs/database/security/
https://firebase.google.com/docs/database/security/
Android Studio (Android Studio)
Create a new android studio project with package name com.androidchatapp
使用包名称com.androidchatapp创建一个新的android studio项目
Now add dependency for firebase database and volley in build.gradle (Module: app) file. Add following lines under dependency section and sync the project.
现在,在build.gradle(模块:app)文件中为firebase数据库和volley添加依赖项。 在“依赖项”部分下添加以下行,并同步项目。
compile 'com.firebase:firebase-client-android:2.5.2+'
compile 'com.android.volley:volley:1.0.0'
Add internet access permission in AndroidManifest.xml file.
在AndroidManifest.xml文件中添加Internet访问权限。
<uses-permission android:name="android.permission.INTERNET" />
The android studio project has following structure.
android studio项目具有以下结构。
Add following code in respective files.
在相应的文件中添加以下代码。
AndroidManifest.xml
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.androidchatapp">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".Login">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".Register" />
<activity android:name=".Users" />
<activity android:name=".Chat" />
</application>
</manifest>
rounded_corner1.xml
rounded_corner1.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#dddddd" />
<stroke
android:width="0dip"
android:color="#dddddd" />
<corners android:radius="10dip" />
<padding
android:bottom="5dip"
android:left="5dip"
android:right="5dip"
android:top="5dip" />
</shape>
rounded_corner2.xml
rounded_corner2.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#f0f0f0" />
<stroke
android:width="0dip"
android:color="#f0f0f0" />
<corners android:radius="10dip" />
<padding
android:bottom="5dip"
android:left="5dip"
android:right="5dip"
android:top="5dip" />
</shape>
activity_chat.xml
activity_chat.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:background="#ffffff"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.androidchatapp.Chat">
<ScrollView
android:layout_width="match_parent"
android:layout_weight="20"
android:layout_height="wrap_content"
android:id="@+id/scrollView">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="@+id/layout1">
</LinearLayout>
</ScrollView>
<include
layout="@layout/message_area"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="bottom"
android:layout_marginTop="5dp"/>
</LinearLayout>
activity_login.xml
activity_login.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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.androidchatapp.Login"
android:orientation="vertical"
android:gravity="center">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Login"
android:textSize="30dp"
android:gravity="center"
android:layout_marginBottom="20dp"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/username"
android:inputType="text"
android:maxLines="1"
android:hint="enter username"
android:layout_marginBottom="10dp"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/password"
android:inputType="textPassword"
android:maxLines="1"
android:hint="enter password"
android:layout_marginBottom="10dp"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Login"
android:id="@+id/loginButton"
android:layout_marginBottom="20dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Click here to register"
android:textSize="20dp"
android:gravity="center"
android:id="@+id/register"/>
</LinearLayout>
activity_register.xml
activity_register.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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.androidchatapp.Register"
android:orientation="vertical"
android:gravity="center">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Register"
android:textSize="30dp"
android:gravity="center"
android:layout_marginBottom="20dp"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/username"
android:inputType="text"
android:maxLines="1"
android:hint="enter username"
android:layout_marginBottom="10dp"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/password"
android:inputType="textPassword"
android:maxLines="1"
android:hint="enter password"
android:layout_marginBottom="10dp"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Register"
android:id="@+id/registerButton"
android:layout_marginBottom="20dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Click here to login"
android:textSize="20dp"
android:gravity="center"
android:id="@+id/login"/>
</LinearLayout>
activity_users.xml
activity_users.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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.androidchatapp.Users"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="No users found!"
android:id="@+id/noUsersText"
android:visibility="gone"/>
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/usersList"/>
</LinearLayout>
message_area.xml
message_area.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimaryDark"
android:gravity="bottom"
android:orientation="horizontal">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColorHint="#CFD8DC"
android:textColor="#CFD8DC"
android:hint="Write a message..."
android:id="@+id/messageArea"
android:maxHeight="80dp"
/>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="4"
android:padding="4dp"
android:src="@android:drawable/ic_menu_send"
android:id="@+id/sendButton"/>
</LinearLayout>
Chat.java
聊天室
package com.androidchatapp;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import com.firebase.client.ChildEventListener;
import com.firebase.client.DataSnapshot;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import java.util.HashMap;
import java.util.Map;
public class Chat extends AppCompatActivity {
LinearLayout layout;
ImageView sendButton;
EditText messageArea;
ScrollView scrollView;
Firebase reference1, reference2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
layout = (LinearLayout)findViewById(R.id.layout1);
sendButton = (ImageView)findViewById(R.id.sendButton);
messageArea = (EditText)findViewById(R.id.messageArea);
scrollView = (ScrollView)findViewById(R.id.scrollView);
Firebase.setAndroidContext(this);
reference1 = new Firebase("https://android-chat-app-e711d.firebaseio.com/messages/" + UserDetails.username + "_" + UserDetails.chatWith);
reference2 = new Firebase("https://android-chat-app-e711d.firebaseio.com/messages/" + UserDetails.chatWith + "_" + UserDetails.username);
sendButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String messageText = messageArea.getText().toString();
if(!messageText.equals("")){
Map<String, String> map = new HashMap<String, String>();
map.put("message", messageText);
map.put("user", UserDetails.username);
reference1.push().setValue(map);
reference2.push().setValue(map);
}
}
});
reference1.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Map map = dataSnapshot.getValue(Map.class);
String message = map.get("message").toString();
String userName = map.get("user").toString();
if(userName.equals(UserDetails.username)){
addMessageBox("You:-\n" + message, 1);
}
else{
addMessageBox(UserDetails.chatWith + ":-\n" + message, 2);
}
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}
public void addMessageBox(String message, int type){
TextView textView = new TextView(Chat.this);
textView.setText(message);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lp.setMargins(0, 0, 0, 10);
textView.setLayoutParams(lp);
if(type == 1) {
textView.setBackgroundResource(R.drawable.rounded_corner1);
}
else{
textView.setBackgroundResource(R.drawable.rounded_corner2);
}
layout.addView(textView);
scrollView.fullScroll(View.FOCUS_DOWN);
}
}
Login.java
Login.java
package com.androidchatapp;
import android.app.ProgressDialog;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONException;
import org.json.JSONObject;
public class Login extends AppCompatActivity {
TextView register;
EditText username, password;
Button loginButton;
String user, pass;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
register = (TextView)findViewById(R.id.register);
username = (EditText)findViewById(R.id.username);
password = (EditText)findViewById(R.id.password);
loginButton = (Button)findViewById(R.id.loginButton);
register.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(Login.this, Register.class));
}
});
loginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
user = username.getText().toString();
pass = password.getText().toString();
if(user.equals("")){
username.setError("can't be blank");
}
else if(pass.equals("")){
password.setError("can't be blank");
}
else{
String url = "https://android-chat-app-e711d.firebaseio.com/users.json";
final ProgressDialog pd = new ProgressDialog(Login.this);
pd.setMessage("Loading...");
pd.show();
StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>(){
@Override
public void onResponse(String s) {
if(s.equals("null")){
Toast.makeText(Login.this, "user not found", Toast.LENGTH_LONG).show();
}
else{
try {
JSONObject obj = new JSONObject(s);
if(!obj.has(user)){
Toast.makeText(Login.this, "user not found", Toast.LENGTH_LONG).show();
}
else if(obj.getJSONObject(user).getString("password").equals(pass)){
UserDetails.username = user;
UserDetails.password = pass;
startActivity(new Intent(Login.this, Users.class));
}
else {
Toast.makeText(Login.this, "incorrect password", Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
pd.dismiss();
}
},new Response.ErrorListener(){
@Override
public void onErrorResponse(VolleyError volleyError) {
System.out.println("" + volleyError);
pd.dismiss();
}
});
RequestQueue rQueue = Volley.newRequestQueue(Login.this);
rQueue.add(request);
}
}
});
}
}
Register.java
注册.java
package com.androidchatapp;
import android.app.ProgressDialog;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.firebase.client.Firebase;
import org.json.JSONException;
import org.json.JSONObject;
public class Register extends AppCompatActivity {
EditText username, password;
Button registerButton;
String user, pass;
TextView login;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
username = (EditText)findViewById(R.id.username);
password = (EditText)findViewById(R.id.password);
registerButton = (Button)findViewById(R.id.registerButton);
login = (TextView)findViewById(R.id.login);
Firebase.setAndroidContext(this);
login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(Register.this, Login.class));
}
});
registerButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
user = username.getText().toString();
pass = password.getText().toString();
if(user.equals("")){
username.setError("can't be blank");
}
else if(pass.equals("")){
password.setError("can't be blank");
}
else if(!user.matches("[A-Za-z0-9]+")){
username.setError("only alphabet or number allowed");
}
else if(user.length()<5){
username.setError("at least 5 characters long");
}
else if(pass.length()<5){
password.setError("at least 5 characters long");
}
else {
final ProgressDialog pd = new ProgressDialog(Register.this);
pd.setMessage("Loading...");
pd.show();
String url = "https://android-chat-app-e711d.firebaseio.com/users.json";
StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>(){
@Override
public void onResponse(String s) {
Firebase reference = new Firebase("https://android-chat-app-e711d.firebaseio.com/users");
if(s.equals("null")) {
reference.child(user).child("password").setValue(pass);
Toast.makeText(Register.this, "registration successful", Toast.LENGTH_LONG).show();
}
else {
try {
JSONObject obj = new JSONObject(s);
if (!obj.has(user)) {
reference.child(user).child("password").setValue(pass);
Toast.makeText(Register.this, "registration successful", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(Register.this, "username already exists", Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
pd.dismiss();
}
},new Response.ErrorListener(){
@Override
public void onErrorResponse(VolleyError volleyError) {
System.out.println("" + volleyError );
pd.dismiss();
}
});
RequestQueue rQueue = Volley.newRequestQueue(Register.this);
rQueue.add(request);
}
}
});
}
}
UserDetails.java
UserDetails.java
package com.androidchatapp;
public class UserDetails {
static String username = "";
static String password = "";
static String chatWith = "";
}
Users.java
Users.java
package com.androidchatapp;
import android.app.ProgressDialog;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Iterator;
public class Users extends AppCompatActivity {
ListView usersList;
TextView noUsersText;
ArrayList<String> al = new ArrayList<>();
int totalUsers = 0;
ProgressDialog pd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_users);
usersList = (ListView)findViewById(R.id.usersList);
noUsersText = (TextView)findViewById(R.id.noUsersText);
pd = new ProgressDialog(Users.this);
pd.setMessage("Loading...");
pd.show();
String url = "https://android-chat-app-e711d.firebaseio.com/users.json";
StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>(){
@Override
public void onResponse(String s) {
doOnSuccess(s);
}
},new Response.ErrorListener(){
@Override
public void onErrorResponse(VolleyError volleyError) {
System.out.println("" + volleyError);
}
});
RequestQueue rQueue = Volley.newRequestQueue(Users.this);
rQueue.add(request);
usersList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
UserDetails.chatWith = al.get(position);
startActivity(new Intent(Users.this, Chat.class));
}
});
}
public void doOnSuccess(String s){
try {
JSONObject obj = new JSONObject(s);
Iterator i = obj.keys();
String key = "";
while(i.hasNext()){
key = i.next().toString();
if(!key.equals(UserDetails.username)) {
al.add(key);
}
totalUsers++;
}
} catch (JSONException e) {
e.printStackTrace();
}
if(totalUsers <=1){
noUsersText.setVisibility(View.VISIBLE);
usersList.setVisibility(View.GONE);
}
else{
noUsersText.setVisibility(View.GONE);
usersList.setVisibility(View.VISIBLE);
usersList.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, al));
}
pd.dismiss();
}
}
Screenshots
屏幕截图
Check this article for Top 10 Best Live Chat Software Solutions Compared
You can download the apk and source code from below link.
您可以从下面的链接下载apk和源代码。
Apk: http://www.mediafire.com/file/jwurkc69pag2u6w/Android+Chat+App_V1.0.apk
APK: http : //www.mediafire.com/file/jwurkc69pag2u6w/Android+Chat+App_V1.0.apk
Source Code: http://www.mediafire.com/file/djl5s58sbw5kpma/AndroidChatApp.rar
源代码: http : //www.mediafire.com/file/djl5s58sbw5kpma/AndroidChatApp.rar
Feel free to ask your queries by commenting below.
请在下面发表评论,随时提出您的问题。