Android Firebase cho người mới bắt đầu

Android Firebase cho người mới bắt đầu

Firebase

I. Firebase là gì

Google Firebase là phần mềm phát triển ứng dụng được Google hỗ trợ cho phép các nhà phát triển phát triển ứng dụng iOS, Android và Web apps. Firebase cung cấp các công cụ để theo dõi phân tích, báo cáo và khắc phục sự cố ứng dụng, tạo thử nghiệm tiếp thị và sản phẩm. Firebase có nhiều dịch vụ và hôm nay mình sẽ viết về in-app messaging, cloud messages and real-time databases.

II. Thêm Firebase vào dự án

Trước khi thêm Firebase vào ứng dụng Android, chúng ta cần tạo một dự án Firebase để kết nối với ứng dụng Android của mình. Đăng nhập vào Firebase console ở liên kết này https://console.firebase.google.com/?hl=en

Bước 1: Sau khi đăng nhập vào Firebase, chọnCreate a project để tạo một dự án mới.
Bước 2: Thực hiện theo các bước trong Firebase để tạo một dự án mới, sau khi tạo thành công, bạn sẽ thấy giao diện người dùng này, nhấp vào biểu tượng Android
Bước 3: Bạn sẽ cần tên package trong dự án Android, bạn có thể tìm thấy tên package trong AndroidManifest
Bước 4: Tải file google-services.json và thêm vào project Android
Chọn mục project để có thể thấy thư mục gốc trong dự án, thêm file google-services.json mới tải xuống vào thư mục “Project -> app“.
Bước 5: Thêm SDK Firebase
1. Trong”build.gradle” (project):
2. Trong “build.gradle” (app):
Bước 6: Cài đặt ứng dụng và chờ Firebase kiểm tra, bạn sẽ thấy thông báo khi thành công, chọn Continue to console, bây giờ Firebase đã được thêm vào project của bạn.

III. In-App Message

1. Giới thiệu

Firebase In-App Messaging giúp ứng dụng của bạn có thể thu hút người dùng đang hoạt động bằng cách gửi cho họ những thông điệp tuỳ theo mục đích của bạn và khuyến khích họ sử dụng các tính năng chính của ứng dụng. Ví dụ: bạn có thể gửi tin nhắn trong ứng dụng để khiến người dùng đăng ký, xem video, hoàn thành cấp độ hoặc mua một mặt hàng nào đó. Bạn có thể tùy chỉnh tin nhắn dưới dạng cards, banners, modals, hoặc images, và bạn có thể cài đặt thời điểm hiển thị chính xác giúp cho chúng có thể mang lại lợi ích cho người dùng của bạn nhiều nhất.

2. Bắt đầu

Bước 1: Thêm “implementation ‘com.google.firebase:firebase-inappmessaging-display:19.0.3’ vào “build.gradle” (app) và “Sync Now”
Bước 2: Lấy Firebase instance ID (ID này được dùng để test in-app messaging trên Firebase)
private fun createInstanceId() {
    FirebaseInstanceId.getInstance().instanceId.addOnCompleteListener { task ->
        if (!task.isSuccessful) {
            Log.w(TAG, "getInstanceId failed", task.exception)
            return@addOnCompleteListener
        }

        //create new instance id Token
        val msg = task.result?.id
        Log.d(TAG, "token: $msg")
    }
}

Bước 3: Cài đặt ứng dụng và mở Logcat để lấy ID token
Bước 4: Sau khi lấy được ID token, vào Firebase Console và đi đến mục In-App Messaging, chọn Create your first campaign
Bước 5: Nhập “Message title” (vd: Hello I’m FireBase), “Body” (không bắt buộc), Images (vd: https://cdn.pixabay.com/photo/2015/10/12/14/54/coffee-983955_960_720.jpg)
Thêm “Button Text” (vd: ok)
Bước 6: Chọn “Test on Device”, và thêm ID token đã được hiển thị trong Logcat (Bước 3)
Firebase In-App Messaging sẽ gửi tin nhắn đến cho bạn ngay sau khi chọn Test. để thấy được tin nhắn, cho ứng dụng của bạn xuống background sau đó mở lại app.
Kết quả sau khi mở lại ứng dụng:
Bước 7: Sau khi test thành công , chọn “Next” để tiếp tục
Chọn “Review” để publish tin nhắn.
Khi chọn “Publish” tin nhắn sẽ được gửi đến ứng dụng của bạn.
Kết quả:
  

IV. Cloud Message

1. Giới thiệu

Firebase Cloud Messaging (FCM) là một giải pháp nhắn tin đa nền tảng cho phép bạn gửi tin nhắn một cách đáng tin cậy và hoàn toàn miễn phí. sử dụng FCM, bạn có thông báo đến cho người dùng rằng email mới hoặc dữ liệu khác đã có sẵn để đồng bộ hóa. Bạn có thể gửi tin nhắn thông báo để thúc đẩy sự tham gia và duy trì của người dùng. Đối với các trường hợp sử dụng như nhắn tin tức thời, tin nhắn có thể chuyển tải trọng lên tới 4KB cho ứng dụng.

2. Bắt đầu

Bước 1: Thêm “implementation ‘com.google.firebase:firebase-messaging:20.1.0’ ” vào “build.gradle” (app) và “Sync Now”

Bước 2 : Thêm service vào File AndroidManifest

<service
    android:name=".java.MyFirebaseMessagingService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

MyFirebaseMessagingService thừa kế từ FirebaseMessagingService. Đây là bắt buộc nếu bạn muốn xử lý bất kì tin nhắn thông báo nào trên ứng dụng của bạn chạy dưới background. Để nhận thông báo trong foreground ứng dụng, để nhận dữ liệu, để gửi các thư ngược lại và nhiều hơn nữa… Bạn phải thừa kế từ service này.

Bây giờ bạn sẽ thấy dòng 23 bị lỗi, bởi vì chưa có class MyFirebaseMessagingService trong project

đổi package name từ .java.MyFirebaseMessagingService thành <package>.MyFirebaseMessagingService.

Bước 3 (không bắt buộc): thêm icon mặc định và màu, bạn có thể bỏ qua bước này nếu như bạn ko cần

<!-- Set custom default icon. This is used when no icon is set for incoming notification messages.
     See README(https://goo.gl/l4GJaQ) for more. -->
<meta-data
    android:name="com.google.firebase.messaging.default_notification_icon"
    android:resource="@drawable/ic_stat_ic_notification" />
<!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
     notification message. See README(https://goo.gl/6BKBk7) for more. -->
<meta-data
    android:name="com.google.firebase.messaging.default_notification_color"
    android:resource="@color/colorAccent" />

Bước 4 (Không bắt buộc): Từ Android 8.0 (API level 26) và cao hơn, các thông báo đã được hỗ trợ và đề xuất. FCM cung cấp thông báo mặc định với cài đặt cơ bản. Còn nếu bạn muốn thông báo với giao diện của riêng mình, bạn hãy đặt default_notification_channel_id thành ID thông báo của bạn như hình bên dưới. FCM sẽ sử dụng giá trị này với bất cứ tin nhắn nào đến mà không thiết lập thông báo nào vào thư mục res/values/strings.xml và thêm dòng code này.

<string name="default_notification_channel_id">1</string>

Mở file AndroidMnifest và thêm đoạn code này.

<meta-data
    android:name="com.google.firebase.messaging.default_notification_channel_id"
    android:value="@string/default_notification_channel_id" />

 Bước 5: Vào file MainActivity để lấy token (dùng để test FCM)

private fun createInstanceId() {
    FirebaseInstanceId.getInstance().instanceId.addOnCompleteListener { task ->
        if (!task.isSuccessful) {
            Log.w(TAG, "getInstanceId failed", task.exception)
            return@addOnCompleteListener
        }

        //get id Token
        // Get new Instance ID token
        val token = task.result?.token

        // Log and toast
        Log.d(TAG, "token: $token")
        Toast.makeText(baseContext, "token: $token", Toast.LENGTH_SHORT).show()
    }
}

Cài app vào chạy, nếu thành công bạn sẽ nhận được Firebase instance ID.

Bước 6: Thiết lập file MyFirebaseMessagingService

class MyFirebaseMessagingService : FirebaseMessagingService() {
    companion object {
        private val TAG = this::class.java.simpleName
    }

    override fun onNewToken(token: String) {
        Log.d(TAG, "Refreshed token: $token")
        super.onNewToken(token)
    }

    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        super.onMessageReceived(remoteMessage)
        Log.d(TAG, "From: ${remoteMessage.from}")

        remoteMessage.data.isNotEmpty().let {
        }

        remoteMessage.notification?.let {
            Log.d(TAG, "Message Notification Body: ${it.body}")
            it.body?.let { body ->
                sendNotification(body)
            }
        }
    }

    private fun sendNotification(messageBody: String) {
        val intent = Intent(this, CloudMessageActivity::class.java)
        intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
        val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT)

        val channelId = getString(R.string.default_notification_channel_id)
        val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
        val notificationBuilder = NotificationCompat.Builder(this, channelId)
            .setSmallIcon(R.drawable.ic_notifications)
            .setContentTitle("Mess Title")
            .setContentText(messageBody)
            .setAutoCancel(true)
            .setSound(defaultSoundUri)
            .setContentIntent(pendingIntent)

        val notificationManager =
            getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                channelId, "Channel human readable title",
                NotificationManager.IMPORTANCE_DEFAULT
            )
            notificationManager.createNotificationChannel(channel)
        }

        notificationManager.notify(1, notificationBuilder.build())
    }
}

Bước 7: Test FCM trên Firebase

Nhập Title, textimage (không bắt buộc) vd https://cdn.pixabay.com/photo/2017/07/07/02/05/symbol-2480161_960_720.png

Thêm ID token đã lấy được trong Logcat (bước 5)

Kết quả test:

Bước 8: Tạo và gửi tin nhắn

Sau khi test thành công, chọn “Next“để tiếp tục

Sau khi chọn “Publish” Firebase sẽ gửi tin nhắn đến cho ứng dụng

Kết quả:

V. Realtime Database

1. Giới thiệu

Firebase Realtime Database là cơ sở dữ liệu lưu trữ trên mây. Dữ liệu được lưu trữ và đồng bộ hóa theo thời gian thực với mỗi client được kêt nối. Khi bạn xây dựng ứng dụng đa nền tảng với iOS, Android, và javascript SDK, tất cả các client của bạn chia sẽ một thể hiện Realtime Database và tự động tiếp nhận các thay đổi với dữ liệu mới nhất.

2. Bắt đầu

Bước 1: Thêm “implementation ‘com.google.firebase:firebase-database:19.2.1’  ” vào “build.gradle” (app) và “Sync Now”

Bước 2: Sửa “Rules” realtime database thành true

chi tiết về “Rules” của real time database bạn có thể xem ở link này

Bước 3: tạo class UserModel

data class UserModel(
    var id: String = "",
    var name: String = "",
    var age: Int = 0,
    var email: String = ""
) {
    override fun toString(): String {
        return "UserModel(id='$id', name='$name', age=$age, email='$email')"
    }
}

Bước 4: Tạo 1 layout gồm 3 edit text (name, age and email), 4 button (insert, get, update, delete), 1 recycler view để chứa dữ liệu User

Bước 5:

  • Thêm dữ liệu vào database:

Đầu tiên, khởi tạo biến databaseReference

private fun initDatabase() {
    databaseReference = FirebaseDatabase.getInstance().reference
}

Tiếp theo, lấy dữ liệu từ EditText và thêm vào database.

private fun insertUser() {
    if (edt_name.text.isNullOrEmpty() || edt_age.text.isNullOrEmpty() || edt_email.text.isNullOrEmpty()) {
        Toast.makeText(this, "Some field are missing.", Toast.LENGTH_SHORT).show()
        return
    }

    //get key
    val key = databaseReference.child("User").push().key

    //get user data from edit text
    val user = UserModel(
        name = edt_name.text.toString(),
        age = edt_age.text.toString().toInt(),
        email = edt_email.text.toString()
    )

    key?.let {
        user.id = key

        // Write a data to the database
        databaseReference.child("User").child(key).setValue(user).addOnSuccessListener {
            clearText()
            //get user data from database
            getUser()
            //scroll to new item
            recycler_user.scrollToPosition(recyclerAdapter.userList.size - 1)
        }
            .addOnFailureListener {
                Toast.makeText(this, "Upload Error", Toast.LENGTH_SHORT).show()
            }
    }
}

Ở sự kiện click của button_insert

btn_insert.setOnClickListener {
    insertUser()
}

sau khi chọn button_insert dữ liệu sẽ được thêm vào database ngay lập tức.

  • đọc dữ liệu trên database:
private fun getUser() {
    databaseReference.child("User").addValueEventListener(object : ValueEventListener {
        override fun onCancelled(dataError: DatabaseError) {
            Toast.makeText(this@DataBaseActivity, "Upload Error", Toast.LENGTH_SHORT).show()
        }

        override fun onDataChange(dataSnapshot: DataSnapshot) {

            //get user list from database
            val list = dataSnapshot.children.mapNotNull {
                it.getValue(UserModel::class.java)
            }
            list.forEach {
                Log.i("Users", it.toString())
            }
            //add to recycler view
            if (list.isNotEmpty()) {
                recyclerAdapter.userList.clear()
                recyclerAdapter.userList.addAll(list)
                recyclerAdapter.notifyDataSetChanged()
            }
        }
    })
}

  • Update dữ liệu trên database
private fun updateUser() {
    user?.let {
        //create new user object
        val user = UserModel(
            it.id,
            edt_name.text.toString(),
            edt_age.text.toString().toInt(),
            edt_email.text.toString()
        )
        //update user
        databaseReference.child("User/${it.id}").setValue(user)
    }
}

  • Delete  dữ liệu trên database
private fun deleteUser() {
    // get user id
    val query =
        databaseReference.child("User").orderByChild("id").equalTo(user?.id)

    query.addListenerForSingleValueEvent(object : ValueEventListener {
        override fun onDataChange(dataSnapshot: DataSnapshot) {
            for (user in dataSnapshot.children) {
                //remove user
                user.ref.removeValue().addOnSuccessListener {
                    clearText()
                }
            }
        }

        override fun onCancelled(databaseError: DatabaseError) {
            Log.e(
                TAG,
                "onCancelled",
                databaseError.toException()
            )
        }
    })
    getUser()
}

VI. Link tham khảo

https://firebase.google.com/docs/guides

https://github.com/firebase/quickstart-android/blob/995be41782f84b3c54e41d7d7e5d3a5048fe329e/messaging/app/src/main/java/com/google/firebase/quickstart/fcm/kotlin/MyFirebaseMessagingService.kt#L65-L77

https://proandroiddev.com/firebase-android-playground-realtime-database-560d4e18404a

https://www.learnhowtoprogram.com/android/data-persistence/firebase-reading-data-and-event-listeners