Android

Firebase Q&A, #1

Nhận thấy các bạn độc giả của EITGUIDE cũng như các anh chị em coder khác đã đọc qua loạt bài về Firebase của chúng tôi, đang ở mức tìm hiểu cũng như vận dụng, nhưng gặp một số vấn đề lớn cũng có mà nhỏ cũng nhiều, nên chúng tôi làm một “quả” hỏi đáp nhanh về “Ngọn lửa”. Nếu bạn chưa biết gì về Firebase, vui lòng đọc qua các bài viết trước.

Firebase_logo

1. “Tôi vừa bắt đầu áp dụng Firebase, mà mục đích chính là sẽ sử dụng Realtime Database và Cloud Storage, vậy tôi có buộc/nên dùng Auth không?”

Không phải vô cớ mà chúng tôi giới thiệu Firebase Auth trước nhất. Nó là cái bạn nên sử dụng. Việc đọc và ghi trong Realtime Database cũng như Cloud Storage hoàn toàn không thể diễn ra một cách bừa bãi, ai cũng có thể vào để xem, đọc và thay đổi dữ liệu được. Do đó, nếu không dùng từ “bắt buộc”, tôi sẽ dùng từ “nghiêm túc khuyến nghị” các bạn sử dụng Firebase Authentication để giới hạn việc đọc-ghi dữ liệu. Và dù cho bạn có hẳn một hệ thống Authentication của riêng bạn, thì bạn “rất nên” kết hợp với Firebase Auth nếu bạn có sử dụng Realtime Database cũng như Cloud Storage.

2. “Tôi đang làm một ứng dụng giống như chat, vậy làm sao lấy được chat history?”

Mở rộng nội dung câu hỏi này ra, thì nó sẽ tương đương với “Làm sao để tôi có thể lấy tất cả dữ liệu của Firebase Realtime Database từ một vị trí đã xác định?”.

Đó là một thắc mắc khá hay, vì thực chất có khá nhiều bạn biết đưa dữ liệu lên Firebase Realtime Database, biết lấy Value của một Object rồi, nhưng để lấy tất cả các dữ liệu đã có sẵn thì lại gặp rắc rối. Chẳng hạn, tôi minh họa với CSDL “thần thánh” bên dưới:

FirebaseRealtimeDatabase-Example

Tức là bạn đã có thể lấy và thay đổi dữ liệu tại vị trí fieldName trong KI2GLhv… của b797bdd4… Nhưng khi yêu cầu bạn lấy hết các cái children của b797bdd4 kia thì bạn gặp rắc rối, vì bạn quen việc gắn data với các vị trí đã biết key, còn đối với những vị trí khác thì chưa nghĩ ra.

Câu trả lời là đơn giản thôi. Bạn sẽ dùng ValueEvents hay ChildEvents. Tại sao lại dùng Events, trong khi dữ liệu bên trên đã có rồi mà, có thêm child nào mới đâu chứ? Đơn giản là như sau, sau khi thoát hẳn ứng dụng, thì bạn biết rồi, các dữ liệu tạm sẽ được dọn dẹp, mất đi, bao gồm các dữ liệu về Firebase Realtime Database. Tức là dữ liệu về Database của ứng dụng sẽ tạm thời “trở về trang giấy trắng”. Khi ứng dụng được chạy lại, thì ứng dụng sẽ tiến hành đồng bộ với Firebase Database trên Firebase server. Và do đó, các children có sẵn trên “mây” sẽ được tuần tự add vào database của ứng dụng client. Và như vậy, nếu bạn dùng ChildEvents, thì các DatabaseReference sẽ gọi AddEvent đúng số lần ứng với số children, và mỗi added child là một Object con.

Dưới đây là phần minh họa. Yêu cầu là biến dbRef sẽ trỏ vào users/users/. Code cho Android sẽ như bên dưới:

Với iOS cũng tương tự, chỉ các syntax mà thôi.

Và mọi chuyện cũng không quá khác biệt với Javascript khi làm ứng dụng web.

Tóm lại, bạn lưu ý chỗ này: Các events được thực thi dưới client, chứ không phải trên Firebase Realtime Database đâu, bạn à. Mỗi đoạn chat chính là một snapshot. Bao nhiêu đoạn chat thì sẽ có bấy nhiêu snapshot được gọi.

3.”Tôi có thể dùng chung một Firebase project cho một ứng dụng khả dụng cho cả ba nền tảng là Android, iOS và Web không?”

Dĩ nhiên là được, và thực tế thì bạn hoàn toàn không nên tạo project mới tương ứng với một nền tảng cho cùng một ứng dụng đa nền tảng. Chẳng hạn, bạn đang có một ứng dụng cho Android và muốn mở rộng sang iOS và Web, hãy dùng đúng project đó mà thêm nền tảng mới vào mà thôi, để dễ kiểm soát, cũng như dữ liệu được chia sẻ và đồng bộ. Vd đơn giản nhất, cơ bản nhất là chat. Có lẽ tới đây thì bạn đã quá hiểu rồi, và tôi không cần nói gì thêm.

4. “Tôi có thể dùng hai ứng dụng khác nhau (cùng hoặc khác nền tảng đích) cho một Firebase project không?”

Câu trả lời là được, tuy nhiên bạn phải có cách quản lí dữ liệu, để tránh việc dữ liệu của ứng dụng này gây thay đổi, ảnh hưởng tới dữ liệu của ứng dụng khác. Tốt nhất, nếu là hai ứng dụng độc lập, thì bạn nên làm hai projects độc lập, hoặc nếu dùng một project thì phải cẩn thận trong việc quản lí dữ liệu cũng như authentication, tránh gây xung đột giữa các ứng dụng.

5. “Tôi đang làm ứng dụng tương tự như chat, có cho phép gửi ảnh. Vậy tôi nên lưu ảnh vào Realtime Database hay Cloud Storage?”

Đây là một thắc mắc rất hay ho. Tất nhiên, điều này còn phụ thuộc vào ý tưởng của bạn. Tuy nhiên, theo tôi thì bạn nên lưu ảnh vào Cloud Storage và lưu link tới ảnh qua Realtime Database. Phần lấy link ảnh thì bạn sẽ cần tham khảo lại bài viết về Cloud Storage của tôi. Lí do, là bạn có tới 5GB cho Cloud Storage trong khi chỉ có 1GB cho Realtime Database nếu dùng gói miễn phí, và ảnh thì bao giờ cũng “nặng kí lô” hơn so với text. Và do đó, sẽ tốt hơn nếu bạn lưu nội dung ảnh vào Cloud Storage. Lưu ý là bạn cần phải có hướng xử lí thích hợp để giải quyết các tình huống phát sinh, chẳng hạn như việc tải ảnh sẽ tốn thời gian, đặc biệt là khi một phần cáp quang AAG đã bị cá mập “cắn cho bỏ ghét”.

6. “Tôi đang làm ứng dụng chat, làm sao để báo có tin nhắn mới tới khi Firebase Realtime Database có sự thay đổi? Và thông báo chỉ tới đúng thiết bị cần nhận mà thôi?”

Đây có lẽ là thắc mắc và là vấn đề hết sức nan giải của các bạn mới thao tác, “thử việc” với Firebase chưa lâu. Tôi đã có giải thích với một số bạn, nhưng có lẽ sự thật rất khó chấp nhận, là chỉ một Firebase là chưa đủ, chí ít là tới thời điểm hiện tại.

Thực tế, là Mr. Laurence Moroney, một Developer Advocate của Firebase, có hướng dẫn mang tính “chính chủ” về vấn đề này: Bạn sẽ cần một server của riêng bạn. Server build bằng gì cũng được, từ PHP + MySQL tới Java hay NodeJS. Tuy nhiên, quan trọng nhất là việc lấy Token của thiết bị, và việc gửi cloud message xuống thiết bị nhận chính là gửi thông qua Token đó, tức là thiết bị đang được cấp Token đó. Giống như khi ngân hàng chuyển tiền lương vào tài khoản của bạn là chuyển theo mã số vậy.

Server này có ít nhất ba (tức 03) trách nhiệm: Một là lưu các device tokens, hai là quan sát sự thay đổi của database để phát hiện cần gửi notification cho device nào thông qua tokens được lưu trữ, và ba là gửi thông báo lên Firebase Cloud Messaging. Firebase server sẽ gửi thông báo qua deviceToken đó. Về chi tiết, bạn có thể tham khảo hướng dẫn đó tại đâyđây. Đó là hướng dẫn cho Android, nhưng vẫn áp dụng được cho iOS. Đối với Android, bạn sẽ lấy deviceToken qua method String token = FirebaseInstanceId.getInstance().getToken() và iOS là let token = Messaging.messaging().fcmToken. Lưu ý là đối với iOS thì bạn cần một số thao tác cấu hình với APNS nữa, mặc dù phần nhiều các thao tác đã được làm tự động sẵn cho bạn bởi Firebase team.

Tuy nhiên, chúng ta cũng có cách “lách luật” là tạo một Service trên Android hay một Background Execution trên iOS để lắng nghe/quan sát sự thay đổi dữ liệu tại đúng một vị trí nhất định. Nhưng điều này cũng có mặt trái là gây hao pin cho thiết bị, cũng như các processes bên trên dễ bị hệ thống tiêu diệt để lấy lại bộ nhớ hoặc để đảm bảo thời lượng pin cho thiết bị. Bạn chỉ nên dùng cách này trong một số trường hợp, chẳng hạn như ứng dụng đang trong trạng thái foreground, hoặc thời gian thực hiện tác vụ là không lớn.

Hiện tại, thì Firebase đang có triển khai Cloud Functions và tôi nhận thấy cũng có đôi chút hứa hẹn. Tuy nhiên, vì ý định “mời mộc” sử dụng Google Cloud Platform nên Cloud Functions sẽ có những giới hạn nhất định. Cũng đúng thôi, “của ngoại đâu dễ ăn” mà. Vì vậy, tốt hơn hết, nếu muốn làm ứng dụng dạng cần notification mang tính dày đặc, thì tầm cỡ nó cũng phải lớn, và bạn cần một server của riêng bạn, chí ít là cũng để lưu trữ và mã hóa các deviceToken cũng như các thông tin người dùng, ngoài các thông tin của Firebase cung cấp sẵn cũng như mã hóa các thông tin trên để đảm bảo an toàn cho người dùng.

Loạt bài này không chỉ dừng ở đây, mà khi nào chúng tôi nhận thấy có đủ số lượng các vấn đề như hiện tại thì sẽ viết tiếp một bài khác. Nếu bạn có thắc mắc, hãy để lại bình luận bên dưới.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.