Membuat Aplikasi Chat Sederhana dengan Firebase di Android

Hai All, oya pas banget nih dengan peluncuran fitur baru, design baru dan logo barunya Firebase, karena pada postingan kali ini kita akan membahas apa itu firebase dan mencoba untuk mengimplementasikannya. Target dari sharing ini nantinya dapat menghasilkan aplikasi sederhana yang bisa melakukan komunikasi/chatting antara dua device.

Firebase ini merupakan cloud service provider dan backend as a service, yang artinya perusahaan Firebase ini menyediakan layanan cloud berupa backend seperti database, API, dsb more ..

Dengan Firebase, kita tidak perlu menyeting apapun perihal server, karena firebase menyediakan service layaknya server dan juga database. Nah yang membuatnya lebih menarik lagi, adalah karena Firebase ini mudah di gunakan untuk Android dan iOS, karena telah disediakan untuk Android SDK dan juga iOS SDK. Dan juga Developer tidak perlu repot-repot lagi membuat socket manual untuk memulai pengembangan aplikasi chat, dan baca selengkapnya disini dan juga ini.

Firebase Feature

Pertama yang harus kita lakukan untuk mengetahui lebih dalam tentang Firebase ini adalah membuat akun baru untuk Firebase. Kalau ditanya kapan menggunakan Firebase? Firebase akan sangat cocok digunakan pada aplikasi yang dikembangkan untuk menampilkan data yang dikirim secara realtime, seperti chat, social todo list, dsb. Nah sebelum memulainya lebih jauh, yang kita butuhkan adalah memahami tentang Android Life Cycle, terkoneksi dengan internet, dan memahami pengetahuan dasar tentang Firabase dan juga mengetahui tentang Github atau repository sejenis. So, langsung kita coba saja…

Pertama yang harus kita lakukan adalah membuat akun baru untuk Firebase. atau bisa SignUp menggunakan Google Account yang sudah ada.


Registrasi Firebase and Say Hello!

Saya asumsikan Anda telah mendaftar kan akun di Firebase, lalu buat Aplikasi baru dengan nama yang Anda inginkan, atau bisa menggunakan app card my first app yang telah dibuatkan secara default oleh firebase. Di sini saya memberi nama firebase baru sesuai dengan www.wirasetiawan29.firebase.io. Url itu adalahh base url yang akan kita gunakan dalam aplikasi yang akan kita buat dalam sharing kali ini. Nah setelah kita masuk kedalam card app yang telah kita buat tadi, firebase akan menyediakan beberapa baris fitur Data, Security & Rules, Simulator, Analytic, Login & Auth, Hosting, Secrets.

Dalam Firebase, kita menggunakan code berikut untuk mengambil data dan mengirimkan data ke Firebase servicenya:

Langkah – langkah untuk mengkoneksikan aplikasi ke Firebase :

  1. Instal Firebase
    Tambahkan code dibawah ini pada file Gradlle App Project

    Firebase Gradle Settings
    Firebase Gradle Settings
  2. Menambahkan Permission pada aplikasi (AndroidManifest.xml)
    Buka file AndroidManifest.xml pada project aplikasi, dan tambahkan Internet accese permisson code dibawah ini:

    <uses-permission android:name="android.permission.INTERNET" />
    
  3. Mengatur firebase pada method onCreate
    Ini bertujuan untuk membuat inisialisasi Firebase pada project, agar Firebase dapat dikenali pada aplikasi, yaitu pada file MainActivity.java

    public class MainActivity extends AppCompatActivity {
    
        TextView fireData; //Untuk menampilkan data dari firebase
        Firebase ref; //Initialiasi Firebase untuk project
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Firebase.setAndroidContext(this);
    
            fireData = (TextView) findViewById(R.id.firebase_textview);
            ref = new Firebase("https://wirasetiawan29.firebaseio.com/chat");
            ref.addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    String superData = (String) dataSnapshot.getValue();
                    fireData.setText(superData);
                }
    
                @Override
                public void onCancelled(FirebaseError firebaseError) {
    
                }
            });
        }
    }
    
  4. Menampikan data value Firbase
    Buat TextView baru pada file activity_main.xml dengan id firebase_textview seperti berikut:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout 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.logbook29.hellofirebase.MainActivity">
    
        <TextView android:id="@+id/firebase_textview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" />
    </RelativeLayout>
    

Kapanpun kita ingin berinteraksi dengan data Firebase, pertama kali yang harus kita lakukan adalah membuat object dari Firebase itu sendiri. Oleh karena itu kita harus membuat object Firebase pada aplikasi seperti code dibawah ini:

Firebase ref = new Firebase("URL Firebasenya");

Nantinya code akan seperti dibawah ini:

Contoh Syntax Firebase
Contoh Syntax Firebase

Selanjutnya mari kita simulasikan pada aplikasi, bagaimana aplikasi dapat bekerja dalam implementasi menggunakan Firebase.

Hello Firebase Demo
Hello Firebase Demo

Well, dari penjelasan sederhana diatas, kita seharunya telah memahami bagaimana firebase bekerja, mulai dari aplikasi push data ke firebase, dan retrive data dari firebase, dan project diatas dapat didownload disini.

Firebase Table Json
Firebase Table Json

Yang nantinya dashborad firebase di visualisasikan dalam bentuk JSON tree, nah object firebase yang ada di Android project kita tadi lah yang menjadi representasi dari object JSON tree diatas.

Firebase Data Realtime Dashboard


 

Membuat aplikasi Android Chat sederhana dengan Firebase

Nah base on sharing diatas, mari kita lanjutkan pengembangan aplikasi menjadi aplikasi chatting sederhana. Yang pertama kali dilakukan adalah menambahkan support recycler view pada gradle project. Karena untuk menampilkan list chat kita menggunakan Recycler View. Selanjutnya buat model terlebih dahulu, model ini nantinya berfungsi untuk menentukan value apa saja yang akan di tampilkan  pada konten text messagenya. Disini saya mempunyai 5 model, antara lain:

  • name
  • message
  • userId
  • timestamp
  • formattedTime

Sehingga class modelnya menjadi seperti berikut:


public class ChatModel {
private String name;
private String message;
private long userId;
private long timestamp;
private String formattedTime;
public ChatModel() {
name = "";
message = "";
userId = 32;
timestamp = 0;
}
public ChatModel(String message, String name, long uid, long time, String formattedTime) {
this.name = name;
this.message = message;
this.userId = uid;
this.timestamp = time;
this.formattedTime = formattedTime;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public void setTime(long time) {
this.timestamp = time;
long oneDayInMillis = 24 * 60 * 60 * 1000;
long timeDifference = System.currentTimeMillis() – time;
if(timeDifference < oneDayInMillis){
formattedTime = DateFormat.format("hh:mm a", time).toString();
}else{
formattedTime = DateFormat.format("dd MMM – hh:mm a", time).toString();
}
}
public void setFormattedTime(String formattedTime) {
this.formattedTime = formattedTime;
}
public String getFormattedTime(){
long oneDayInMillis = 24 * 60 * 60 * 1000;
long timeDifference = System.currentTimeMillis() – timestamp;
if(timeDifference < oneDayInMillis){
return DateFormat.format("hh:mm a", timestamp).toString();
}else{
return DateFormat.format("dd MMM – hh:mm a", timestamp).toString();
}
}
}

view raw

ChatModel.java

hosted with ❤ by GitHub

Selanjutnya membuat body chat, dan chat list nya. Buat 1 Drawable resource file baru pada res/layout, beri nama text_message.xml dan tambahkan code dibawah ini kedalamnya:


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android&quot;
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:id="@+id/message_container"
android:paddingTop="5dp"
android:paddingBottom="5dp">
<FrameLayout
android:id="@+id/left_arrow"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="@drawable/chat_message_arrow"
android:rotation="180"
android:layout_marginLeft="2dp"/>
<LinearLayout
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:orientation="vertical"
android:background="@drawable/chat_message_background"
android:id="@+id/message"
android:padding="10dp"
android:layout_marginLeft="26dp"
android:layout_marginRight="26dp">
<TextView android:id="@+id/message_text"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:textSize="16sp"
android:textColor="#FFFFFF"
android:textStyle="bold"/>
<TextView android:id="@+id/name_text"
android:textStyle="normal"
android:textColor="#E0E0E0"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:textSize="12sp"
android:layout_weight="1" />
<TextView android:id="@+id/time_text"
android:textStyle="normal"
android:textColor="#E0E0E0"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:textSize="12sp"
android:layout_weight="1" />
</LinearLayout>
<FrameLayout
android:id="@+id/right_arrow"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="@drawable/chat_message_arrow"
android:rotation="180"
android:layout_alignParentTop="true"
android:layout_alignRight="@+id/message"
android:layout_alignEnd="@+id/message"
android:layout_marginRight="-25dp"/>
</RelativeLayout>

Next membuat tampilan list chatnya menggunakan bantuan RecyclerView, dengan cara menambahkan syntax berikut pada file activity_main.xml.


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android&quot;
xmlns:tools="http://schemas.android.com/tools&quot;
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.logbook29.firebasechat.MainActivity">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/messagesList"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_above="@+id/footer" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true"
android:id="@+id/footer">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/messageEdit"
android:layout_weight="1" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send"
android:id="@+id/sendButton"
android:layout_gravity="bottom|right"/>
</LinearLayout>
</RelativeLayout>

Next, tambahkan 2 file ini pada folder drawable project Anda untuk melengkapi tampilan chat.

Terakhir, buat 2 class baru dengan nama FirebaseArray.java dan FirebaseRecyclerAdapter.java. Lalu tambahkan code dibawah ini pada masing-masing file tersebut:


class FirebaseArray implements ChildEventListener {
public interface OnChangedListener {
enum EventType { Added, Changed, Removed, Moved }
void onChanged(EventType type, int index, int oldIndex);
}
private Query mQuery;
private OnChangedListener mListener;
private ArrayList<DataSnapshot> mSnapshots;
public FirebaseArray(Query ref) {
mQuery = ref;
mSnapshots = new ArrayList<DataSnapshot>();
mQuery.addChildEventListener(this);
}
public void cleanup() {
mQuery.removeEventListener(this);
}
public int getCount() {
return mSnapshots.size();
}
public DataSnapshot getItem(int index) {
return mSnapshots.get(index);
}
private int getIndexForKey(String key) {
int index = 0;
for (DataSnapshot snapshot : mSnapshots) {
if (snapshot.getKey().equals(key)) {
return index;
} else {
index++;
}
}
throw new IllegalArgumentException("Key not found");
}
// Start of ChildEventListener methods
public void onChildAdded(DataSnapshot snapshot, String previousChildKey) {
int index = 0;
if (previousChildKey != null) {
index = getIndexForKey(previousChildKey) + 1;
}
mSnapshots.add(index, snapshot);
notifyChangedListeners(OnChangedListener.EventType.Added, index);
}
public void onChildChanged(DataSnapshot snapshot, String previousChildKey) {
int index = getIndexForKey(snapshot.getKey());
mSnapshots.set(index, snapshot);
notifyChangedListeners(OnChangedListener.EventType.Changed, index);
}
public void onChildRemoved(DataSnapshot snapshot) {
int index = getIndexForKey(snapshot.getKey());
mSnapshots.remove(index);
notifyChangedListeners(OnChangedListener.EventType.Removed, index);
}
public void onChildMoved(DataSnapshot snapshot, String previousChildKey) {
int oldIndex = getIndexForKey(snapshot.getKey());
mSnapshots.remove(oldIndex);
int newIndex = previousChildKey == null ? 0 : (getIndexForKey(previousChildKey) + 1);
mSnapshots.add(newIndex, snapshot);
notifyChangedListeners(OnChangedListener.EventType.Moved, newIndex, oldIndex);
}
public void onCancelled(FirebaseError firebaseError) {
// TODO: what do we do with this?
}
// End of ChildEventListener methods
public void setOnChangedListener(OnChangedListener listener) {
mListener = listener;
}
protected void notifyChangedListeners(OnChangedListener.EventType type, int index) {
notifyChangedListeners(type, index, -1);
}
protected void notifyChangedListeners(OnChangedListener.EventType type, int index, int oldIndex) {
if (mListener != null) {
mListener.onChanged(type, index, oldIndex);
}
}
}


public abstract class FirebaseRecyclerAdapter<T, VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> {
Class<T> mModelClass;
protected int mModelLayout;
Class<VH> mViewHolderClass;
FirebaseArray mSnapshots;
public FirebaseRecyclerAdapter(Class<T> modelClass, int modelLayout, Class<VH> viewHolderClass, Query ref) {
mModelClass = modelClass;
mModelLayout = modelLayout;
mViewHolderClass = viewHolderClass;
mSnapshots = new FirebaseArray(ref);
mSnapshots.setOnChangedListener(new FirebaseArray.OnChangedListener() {
@Override
public void onChanged(EventType type, int index, int oldIndex) {
switch (type) {
case Added:
notifyItemInserted(index);
break;
case Changed:
notifyItemChanged(index);
break;
case Removed:
notifyItemRemoved(index);
break;
case Moved:
notifyItemMoved(oldIndex, index);
break;
default:
throw new IllegalStateException("Incomplete case statement");
}
}
});
}
public FirebaseRecyclerAdapter(Class<T> modelClass, int modelLayout, Class<VH> viewHolderClass, Firebase ref) {
this(modelClass, modelLayout, viewHolderClass, (Query) ref);
}
public void cleanup() {
mSnapshots.cleanup();
}
@Override
public int getItemCount() {
return mSnapshots.getCount();
}
public T getItem(int position) {
return parseSnapshot(mSnapshots.getItem(position));
}
protected T parseSnapshot(DataSnapshot snapshot) {
return snapshot.getValue(mModelClass);
}
public Firebase getRef(int position) { return mSnapshots.getItem(position).getRef(); }
@Override
public long getItemId(int position) {
// http://stackoverflow.com/questions/5100071/whats-the-purpose-of-item-ids-in-android-listview-adapter
return mSnapshots.getItem(position).getKey().hashCode();
}
@Override
public VH onCreateViewHolder(ViewGroup parent, int viewType) {
ViewGroup view = (ViewGroup) LayoutInflater.from(parent.getContext()).inflate(mModelLayout, parent, false);
try {
Constructor<VH> constructor = mViewHolderClass.getConstructor(View.class);
return constructor.newInstance(view);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
@Override
public void onBindViewHolder(VH viewHolder, int position) {
T model = getItem(position);
populateViewHolder(viewHolder, model, position);
}
abstract protected void populateViewHolder(VH viewHolder, T model, int position);
}

Last, tambahkan code dibawah ini kedalam class MainActivity.java agar aplikasi siap untuk dijalankan.


public class MainActivity extends AppCompatActivity {
public static String TAG = "FirebaseUI.chat";
private Firebase mRef;
private Query mChatRef;
private long userId = 2;
private String mName = "Upin";
private String mTime;
private Button mSendButton;
private EditText mMessageEdit;
private RecyclerView mMessages;
private FirebaseRecyclerAdapter<ChatModel, ChatHolder> mRecycleViewAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Firebase.setAndroidContext(this);
mSendButton = (Button) findViewById(R.id.sendButton);
mMessageEdit = (EditText) findViewById(R.id.messageEdit);
mSendButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// showFirebaseLoginPrompt();
}
});
mRef = new Firebase("https://wirasetiawan29.firebaseio.com/chat&quot;);
mChatRef = mRef.limitToLast(50);
mSendButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ChatModel chat = new ChatModel(mMessageEdit.getText().toString(), mName, userId, System.currentTimeMillis(), mTime);
mRef.push().setValue(chat, new Firebase.CompletionListener() {
@Override
public void onComplete(FirebaseError firebaseError, Firebase firebase) {
if (firebaseError != null) {
Log.e(TAG, firebaseError.toString());
}
}
});
mMessageEdit.setText("");
}
});
mMessages = (RecyclerView) findViewById(R.id.messagesList);
LinearLayoutManager manager = new LinearLayoutManager(this);
manager.setReverseLayout(false);
mMessages.setHasFixedSize(false);
mMessages.setLayoutManager(manager);
mRecycleViewAdapter = new FirebaseRecyclerAdapter<ChatModel, ChatHolder>(ChatModel.class, R.layout.text_message, ChatHolder.class, mChatRef) {
@Override
public void populateViewHolder(ChatHolder chatView, ChatModel chat, int position) {
chatView.setText(chat.getMessage());
chatView.setName(chat.getName());
chatView.setTime(chat.getFormattedTime());
if (chat.getUserId() == 2) {
chatView.setIsSender(true);
} else {
chatView.setIsSender(false);
}
}
};
mMessages.setAdapter(mRecycleViewAdapter);
}
public static class ChatHolder extends RecyclerView.ViewHolder {
View mView;
public ChatHolder(View itemView) {
super(itemView);
mView = itemView;
}
public void setIsSender(Boolean isSender) {
FrameLayout left_arrow = (FrameLayout) mView.findViewById(R.id.left_arrow);
FrameLayout right_arrow = (FrameLayout) mView.findViewById(R.id.right_arrow);
RelativeLayout messageContainer = (RelativeLayout) mView.findViewById(R.id.message_container);
LinearLayout message = (LinearLayout) mView.findViewById(R.id.message);
if (isSender) {
left_arrow.setVisibility(View.GONE);
right_arrow.setVisibility(View.VISIBLE);
messageContainer.setGravity(Gravity.RIGHT);
} else {
left_arrow.setVisibility(View.VISIBLE);
right_arrow.setVisibility(View.GONE);
messageContainer.setGravity(Gravity.LEFT);
}
}
public void setName(String name) {
TextView field = (TextView) mView.findViewById(R.id.name_text);
field.setText(name);
}
public void setText(String text) {
TextView field = (TextView) mView.findViewById(R.id.message_text);
field.setText(text);
}
public void setTime(String time){
TextView field = (TextView) mView.findViewById(R.id.time_text);
field.setText(time);
}
}
}

Jika semuanya telah dilengkapi dan tidak ada error yang muncul, maka aplikasi sudah bisa dijalankan dan akan terlihat seperti simulasi dibawah ini. Pada simulasi dibawah ini saya menggunakan akun Budi dengan id 1 agar dapat berinteraksi dengan akun lainnya.

Firebase Chat Demo - Budi
Firebase Chat Demo – Budi

Dan pada simulasi dibawah ini saya menggunakan akun upin dengan id 2 yang dapat melihat chat yang ada di room yang sama, yaitu room chat.

Firebase Chat Demo - Upin
Firebase Chat Demo – Upin

Well mungkin cukup sekian pembahasan kita tentang Firebase, dan saya sangat yakin masih banyak kekurangan dari sharing kali ini. Karena namanya ilmu akan terus update dan dioptimasi, jadi jangan sungkan untuk berkomentar dan berbagi pengalamannya. Oya untuk source lengkapnya bisa di download disini.


Plus .. disarankan untuk mengikuti Video Firebase Esential dari Udacity itu, karena dapat membantu menjelaskan lebih detail tentang Firebase lengkap dengan simulasinya juga. Semoga sharing kali ini bermanfaat guys, fell free for question ya guys .. see you ..

19 thoughts on “Membuat Aplikasi Chat Sederhana dengan Firebase di Android

  1. ada erornya gan

    chatapps.firebase.com.chatapps.FirebaseRecyclerAdapter.onCreateViewHolder(FirebaseRecyclerAdapter.java:87)

    isinya

    Constructor constructor = mViewHolderClass.getConstructor(View.class);
    return constructor.newInstance(view);
    } catch (NoSuchMethodException e) {
    throw new RuntimeException(e);
    } catch (InvocationTargetException e) {
    throw new RuntimeException(e);
    } catch (InstantiationException e) {
    throw new RuntimeException(e);
    } catch (IllegalAccessException e) {
    throw new RuntimeException(e);
    }
    }

    tolong pencerahan gan

    Like

  2. Coding program ga ada error cuma pas running program ada error :
    10-16 08:25:01.741 301-615/? E/NetlinkEvent: NetlinkEvent::FindParam(): Parameter ‘INTERFACE’ not found
    10-16 08:25:01.741 301-615/? E/NetlinkEvent: NetlinkEvent::FindParam(): Parameter ‘TIME_NS’ not found
    10-16 08:25:01.743 626-651/? E/NetdConnector: Error handling ‘613 IfaceClass active (null)’: java.lang.NumberFormatException: Invalid int: “(null)”

    bisa kasih pencerahan mas?
    Tks b4

    Like

  3. wah terima kasih artikelnya. Lagi cari cara bikin aplikasi chat di android 😀
    btw, apakah database chat di firebase bisa dikirim ke database di server sendiri? Atau apakah firebase bisa hanya dijadikan sebagai perantara pengiriman pesan saja? sementara datanya tetap disimpan di database kita, di mysql misalnya.

    agak repot juga kalau ada dua database, satu di server sendiri, satu lagi di firebase nya 😀
    *maklum masih pra-newbie

    Like

  4. pak bikin tutorial upload foto ke database pak yang foto itu masuk ke storage dan database pak, seperti pada edit profil kan disuruh melengkapi data seperti name addrees dll serta penampilanya pak, soalnya gua udah cari-cari selama 2 hari tetep ga bisa, mau tanya di stackflow ga berani bhs.inggris semua klo ngikutin tutorial orang A ViewHoldernya itu ada yang di dalam adapter udah diikutin ttep fail, cari tutorial lagi sedangkan tutorial orang B ViewHolder-nya dipisah belum lagi setiap ora punya style beda-beda dan penamaan object beda-beda makasih pak

    Like

  5. gan ada tutorial yang langsung to the point read child data ga? w pusing T.T
    kalo read child data pake satu listener bisa tapi kalo 2 listener langsung FC Aplikasinya
    Padahal w mau pake 5 listener yang nantinya child datanya mau w tampilin di textview.

    Liked by 1 person

  6. Gan thx sblmya bwt tutorialny,alhamdulillah aplikasi sdh brhasil jln d hape dan sdh brhasil connect d database firebase. Tp kox ketika sya install d hp lain idnya tdk berubah ttp sperti id yg prtama sya bwt, jd seolah2 yg mngirim chat itu adalah ttp diri sya sndiri meski sdh sya install di 2 hp brbeda. Tlg gan pencerahannya. Thx

    Like

Good People write good comments ..