Push notification trong Flutter với Firebase Cloud Messaging

Mục lục bài viết (18)
- Push notification hoạt động qua những lớp nào?
- Chuẩn bị dự án Firebase và cấu hình nền tảng
- Cài đặt và cấu hình trong ứng dụng Flutter
- Xin quyền thông báo đúng thời điểm
- Lấy token thiết bị và gửi lên máy chủ
- Nhận thông báo theo ba trạng thái của ứng dụng
- Xử lý khi người dùng bấm thông báo: mở đúng màn hình
- Hai loại nội dung: thông báo hiển thị và thông báo dữ liệu
- Gửi thông báo từ máy chủ
- Kênh thông báo trên Android và nhóm thông báo
- Gỡ lỗi: gửi thành công mà máy không hiện gì
- Kiểm thử tính năng thông báo
- Những lỗi phổ biến khi làm tính năng thông báo
- Đo hiệu quả của thông báo
- Câu hỏi thường gặp
- Kiểm soát tần suất và thời điểm gửi
- Thông báo cục bộ: khi nào dùng thay vì thông báo đẩy
- Kết luận

Thông báo đẩy là tính năng hầu như ứng dụng nào cũng cần, nhưng cũng là tính năng khiến nhiều người phải mất vài ngày để làm cho đúng — vì nó phụ thuộc vào ba lớp khác nhau: mã ứng dụng, dịch vụ trung gian và hệ điều hành. Sai ở bất kỳ lớp nào thì triệu chứng đều giống nhau: không nhận được thông báo.
Bài này đi từ cơ chế hoạt động đến từng bước triển khai, kèm phần gỡ lỗi chi tiết cho trường hợp phổ biến nhất là "gửi thành công mà máy không hiện gì".
Push notification hoạt động qua những lớp nào?
Hiểu ba lớp này giúp bạn biết cần kiểm tra ở đâu khi thông báo không tới:
- Máy chủ gửi yêu cầu. Ở đây là Firebase Cloud Messaging. Bạn gửi một yêu cầu kèm nội dung thông báo và định danh thiết bị cần nhận.
- Hệ thống phân phối của nền tảng. Trên Android là dịch vụ của Google, trên iOS là dịch vụ thông báo của Apple. Hai hệ thống này khác nhau về cách xử lý, và đây là nguồn gốc của phần lớn khác biệt hành vi giữa hai nền tảng.
- Ứng dụng nhận và xử lý. Ứng dụng có thể hiển thị thông báo, xử lý dữ liệu đi kèm trong nền, hoặc mở một màn hình cụ thể khi người dùng bấm vào.
Điểm khác biệt quan trọng nhất so với việc tự tải dữ liệu: thông báo đi qua hạ tầng của hệ điều hành, không qua kết nối của ứng dụng. Ứng dụng không cần đang chạy để nhận thông báo, và điều này cũng có nghĩa là mã xử lý của bạn không phải lúc nào cũng được chạy.
Chuẩn bị dự án Firebase và cấu hình nền tảng
Ba việc cần làm trước khi viết dòng code đầu tiên:
1. Tạo dự án Firebase và thêm hai ứng dụng. Bạn cần thêm cả ứng dụng Android và iOS vào cùng dự án, vì mỗi nền tảng có tệp cấu hình riêng.
2. Đặt tệp cấu hình vào đúng vị trí. Android cần tệp cấu hình Google dịch vụ ở thư mục ứng dụng của module Android; iOS cần tệp cấu hình tương ứng ở thư mục gốc của project iOS. Tệp đặt sai chỗ là lỗi phổ biến nhất trong bước này.
3. Cho iOS: bật khả năng nhận thông báo và tải khoá. iOS cần bật khả năng push notification trong phần cấu hình project, và bạn phải tải khoá xác thực (dạng khoá APNs) lên phần cài đặt của dự án Firebase. Thiếu bước tải khoá này, thông báo sẽ không bao giờ tới iOS dù mọi thứ khác đúng.
Với Android, cũng cần chú ý tới biểu tượng thông báo: biểu tượng mặc định sẽ là một hình vuông trắng nếu bạn không chuẩn bị biểu tượng dạng đơn sắc riêng. Đây là lỗi nhỏ nhưng nhìn rất thiếu chuyên nghiệp.
Cài đặt và cấu hình trong ứng dụng Flutter
Thêm thư viện vào dự án:
[object Object]Sau đó khởi tạo Firebase trước khi chạy ứng dụng:
[object Object]Với Android, cần khai báo quyền thông báo trong tệp manifest (yêu cầu từ Android 13):
[object Object]Một chi tiết thường bị bỏ qua: nếu ứng dụng có nhiều môi trường (phát triển và sản phẩm), hãy tách dự án Firebase cho từng môi trường ngay từ đầu. Gửi thông báo thử nghiệm tới người dùng thật là lỗi khó sửa về mặt danh tiếng.
Xin quyền thông báo đúng thời điểm
Đây là phần quyết định tỷ lệ người dùng đồng ý, và tỷ lệ đó ảnh hưởng trực tiếp tới tính năng.
Nguyên tắc quan trọng: đừng xin quyền ngay khi ứng dụng mở lần đầu. Khi đó người dùng chưa biết ứng dụng sẽ gửi gì, nên phần lớn sẽ từ chối — và trên iOS, bạn chỉ có một lần để hỏi.
Cách làm đúng là xin quyền ở thời điểm người dùng vừa thực hiện một hành động cho thấy họ muốn được nhắc, ví dụ sau khi họ đăng ký nhận tin hoặc bật thông báo cho một hạng mục cụ thể.
[object Object]Trên iOS, còn một lựa chọn đáng biết là quyền tạm thời: hệ thống gửi thông báo im lặng tới màn hình khoá mà không cần hỏi người dùng. Cách này giúp bạn có dữ liệu thật để thuyết phục người dùng bật thông báo đầy đủ ở bước sau.
Nếu người dùng đã từ chối, việc xin lại không có tác dụng — bạn cần hướng dẫn họ vào phần cài đặt của hệ điều hành. Hãy kiểm tra trạng thái trước khi hiển thị lời nhắc đó, thay vì lặp lại lời nhắc gây khó chịu.
Lấy token thiết bị và gửi lên máy chủ
Token là địa chỉ để hệ thống biết gửi thông báo tới thiết bị nào. Token không cố định vĩnh viễn: nó có thể thay đổi khi ứng dụng được cài lại, dữ liệu ứng dụng bị xoá, hoặc ứng dụng được phục hồi sang thiết bị mới.
[object Object]Ba điểm cần xử lý đúng, và đây là nơi phát sinh lỗi khó tìm:
- Gắn token với người dùng. Trong ứng dụng có đăng nhập, máy chủ cần biết token này thuộc tài khoản nào. Nếu không, bạn không thể gửi thông báo tới một người dùng cụ thể.
- Xoá token khi đăng xuất. Nếu không xoá, người dùng đăng xuất vẫn nhận thông báo của tài khoản cũ — đây là lỗi về quyền riêng tư nghiêm trọng, không chỉ là lỗi trải nghiệm.
- Xử lý nhiều thiết bị cho một tài khoản. Người dùng có thể đăng nhập trên điện thoại và máy tính bảng. Máy chủ nên lưu danh sách token theo tài khoản, và loại bỏ token không còn hợp lệ khi hệ thống báo lỗi.
Nhận thông báo theo ba trạng thái của ứng dụng
Đây là phần gây nhầm lẫn nhiều nhất, vì mỗi trạng thái dùng một hàm khác nhau.
[object Object]Ba hành vi cần ghi nhớ:
- Ứng dụng đang mở: hệ thống không tự hiển thị thông báo. Nếu bạn muốn người dùng thấy, phải tự hiển thị bằng thông báo trong ứng dụng. Nhiều người tưởng tính năng hỏng vì đang thử khi ứng dụng mở.
- Ứng dụng ở nền: hệ thống hiển thị thông báo, và hàm xử lý mở màn hình chỉ chạy khi người dùng bấm vào.
- Ứng dụng đã bị tắt: cần hàm lấy thông báo khởi động trước khi dựng giao diện. Nếu xử lý muộn, người dùng sẽ thấy màn hình chính rồi mới bị chuyển đi, gây cảm giác giật.
Một lưu ý nữa: khi ứng dụng đang ở nền hoặc đã tắt, mã xử lý chạy trong một luồng riêng biệt. Đây là lý do mã xử lý đó phải được khai báo ở cấp cao nhất của tệp, không nằm trong lớp hay hàm lồng nhau. Nếu không, bạn sẽ gặp lỗi khó hiểu hoặc hàm không bao giờ được gọi.
Xử lý khi người dùng bấm thông báo: mở đúng màn hình
Thông báo mà bấm vào chỉ mở trang chủ là thông báo gây thất vọng. Cách làm đúng là đọc dữ liệu đi kèm và chuyển tới đúng màn hình.
[object Object]Hai điều cần chú ý:
- Đừng đặt toàn bộ đường dẫn trong dữ liệu thông báo. Hãy gửi định danh và để ứng dụng tự dựng đường dẫn. Nếu gửi đường dẫn trực tiếp, mọi thay đổi cấu trúc đường dẫn sẽ làm hỏng các thông báo đã phát đi — mà thông báo thì đã nằm trên thiết bị người dùng, bạn không sửa lại được.
- Chờ điều hướng sẵn sàng. Thông báo khởi động ứng dụng đến trước khi giao diện dựng xong. Cần xếp hàng đợi các yêu cầu điều hướng và xử lý sau khi ứng dụng sẵn sàng.
Với ứng dụng dùng router khai báo, hãy dùng liên kết nội bộ thay vì tự gọi điều hướng, để nhất quán với luồng điều hướng còn lại — chi tiết ở bài so sánh Navigation 1.0 và 2.0 và bài deep link.
Hai loại nội dung: thông báo hiển thị và thông báo dữ liệu
Đây là khái niệm quan trọng nhất trong FCM, và hiểu sai nó dẫn tới việc thông báo "không chạy" trong một số trạng thái.
- Thông báo hiển thị (notification): hệ thống tự hiển thị khi ứng dụng không mở. Bạn không cần viết mã để nó xuất hiện.
- Thông báo dữ liệu (data): không tự hiển thị. Ứng dụng phải xử lý và quyết định làm gì — hiển thị, cập nhật dữ liệu cục bộ, hoặc cả hai.
Bảng chọn nhanh theo mục đích:
- Chỉ muốn nhắc người dùng — dùng thông báo hiển thị kèm dữ liệu đi kèm để biết mở màn hình nào.
- Muốn cập nhật dữ liệu trong nền mà không làm phiền — dùng thông báo dữ liệu. Ví dụ đồng bộ danh sách đơn hàng mới, làm mới số tin chưa đọc.
- Muốn kiểm soát hoàn toàn cách hiển thị (màu, nút hành động, nhóm thông báo) — dùng thông báo dữ liệu rồi tự dựng thông báo cục bộ.
Lưu ý thực tế: cách xử lý khác nhau giữa Android và iOS, đặc biệt với thông báo dữ liệu khi ứng dụng đã bị tắt. Đừng giả định hành vi giống nhau trên hai nền tảng — hãy thử trên cả hai.
Gửi thông báo từ máy chủ
Ba cách gửi, phù hợp với ba mức độ kiểm soát:
1. Gửi từ bảng điều khiển Firebase. Chỉ nên dùng để thử nghiệm và cho các thông báo thủ công. Không dùng cho luồng tự động.
2. Gửi tới nhóm chủ đề (topic). Thiết bị đăng ký nhận theo chủ đề, ví dụ theo khoá học hoặc theo khu vực. Cách này phù hợp khi bạn muốn gửi cùng một nội dung cho nhiều người. Hạn chế: bạn không biết chính xác ai nhận và không thể cá nhân hoá nội dung.
3. Gửi tới từng token qua API. Kiểm soát đầy đủ, cho phép cá nhân hoá nội dung và gửi theo điều kiện nghiệp vụ. Đây là cách dùng cho sản phẩm thật.
Một số điểm cần làm đúng khi gửi từ máy chủ:
- Xác thực bằng khoá dịch vụ, không bằng khoá cũ trong ứng dụng. Khoá dùng để gửi thông báo là quyền rất cao; không bao giờ đặt trong mã ứng dụng di động.
- Xử lý token không còn hợp lệ. Hệ thống sẽ trả về lỗi cho những token đã bị xoá; hãy đánh dấu và loại bỏ chúng khỏi cơ sở dữ liệu, thay vì thử lại nhiều lần.
- Giới hạn số lượng thông báo cho một người dùng. Gửi quá nhiều sẽ khiến người dùng tắt thông báo, và bạn mất kênh liên lạc đó vĩnh viễn.
- Ghi lại nội dung và thời điểm gửi. Khi người dùng phản hồi "tôi nhận được thông báo lạ", bạn cần tra cứu được đã gửi gì.
Kênh thông báo trên Android và nhóm thông báo
Từ Android 8, mỗi thông báo thuộc một kênh và người dùng có thể tắt riêng từng kênh. Đây là cơ hội để chia nhóm hợp lý:
- Một kênh cho giao dịch quan trọng (đơn hàng, thanh toán) — mức ưu tiên cao.
- Một kênh cho cập nhật nội dung — mức ưu tiên mặc định.
- Một kênh cho tin tiếp thị — mức ưu tiên thấp.
Chia kênh rõ ràng giúp người dùng tắt phần họ không muốn nhưng vẫn giữ phần quan trọng. Nếu bạn dùng một kênh duy nhất cho mọi thứ, người dùng sẽ tắt tất cả.
Ngoài ra, âm thanh và rung của kênh không đổi được sau khi đã tạo. Nếu bạn đổi tệp âm thanh, người dùng cũ vẫn nghe âm cũ. Cách xử lý là đặt tên kênh có hậu tố phiên bản khi cần thay đổi.
Với iOS, cơ chế tương tự nhưng ở mức ứng dụng: người dùng tắt thông báo thì tắt cho toàn ứng dụng, không chia nhóm chi tiết như Android.
Gỡ lỗi: gửi thành công mà máy không hiện gì
Đây là triệu chứng phổ biến nhất. Hãy kiểm tra theo thứ tự sau, dừng lại ngay khi tìm được nguyên nhân:
- Ứng dụng đang mở? Hệ thống không tự hiển thị thông báo khi ứng dụng đang mở. Hãy thoát ứng dụng hoặc chuyển sang nền rồi thử lại.
- Người dùng đã tắt thông báo? Kiểm tra trong cài đặt hệ điều hành của ứng dụng. Đây là nguyên nhân đứng đầu trong thực tế.
- Quyền thông báo chưa được hỏi? Trên Android 13 trở lên, quyền là quyền lúc chạy; chưa xin là chưa có.
- Token có đúng không? Token có thể đã bị thay thế. Hãy xoá token cũ trong cơ sở dữ liệu và lấy lại token mới từ thiết bị.
- Đúng dự án Firebase chưa? Tệp cấu hình của môi trường phát triển thường bị dùng nhầm cho bản sản phẩm.
- iOS: đã tải khoá xác thực lên chưa? Thiếu khoá thì thông báo không bao giờ tới iOS.
- Kênh thông báo bị tắt riêng? Trên Android, người dùng có thể tắt riêng một kênh.
- Nội dung thông báo có trường bắt buộc bị thiếu? Một số cấu hình yêu cầu có tiêu đề hoặc nội dung mới hiển thị.
- Đang chạy bản gỡ lỗi trên trình mô phỏng iOS? Trình mô phỏng xử lý thông báo ở mức hệ điều hành khác thiết bị thật; hãy thử trên máy thật.
- Chế độ tiết kiệm pin? Trên Android, nhiều hãng siết chặt ứng dụng chạy nền khi bật tiết kiệm pin, khiến thông báo tới muộn.
Một mẹo gỡ lỗi hiệu quả: bật chế độ ghi nhật ký của thư viện khi chạy bản gỡ lỗi. Nhật ký này thường chỉ ra ngay lỗi thiếu cấu hình hoặc token không hợp lệ, thay vì bạn phải đoán.
Kiểm thử tính năng thông báo
Ba mức kiểm thử nên có, từ dễ đến khó:
- Thử bằng bảng điều khiển Firebase với token của một thiết bị thật, ở cả ba trạng thái: ứng dụng đang mở, đang ở nền, đã bị tắt. Bước này phát hiện phần lớn lỗi cấu hình.
- Kiểm tra xử lý dữ liệu đi kèm bằng test đơn vị. Phần đọc dữ liệu và dựng đường dẫn là logic thuần, dễ test và rất đáng test vì đây là chỗ hay sai nhất. Cách viết test cho phần này giống như bài hướng dẫn mock API.
- Thử luồng thật từ đầu tới cuối trên cả Android và iOS, máy thật: đăng ký nhận thông báo, gửi từ hệ thống của bạn, bấm vào thông báo và kiểm tra màn hình mở ra đúng.
Điều đáng lưu ý: đừng chỉ thử khi ứng dụng mở. Phần lớn lỗi chỉ xuất hiện ở hai trạng thái còn lại, và đó cũng là hai trạng thái mà người dùng thật gặp nhiều nhất.
Những lỗi phổ biến khi làm tính năng thông báo
- Xin quyền ngay khi mở ứng dụng — mất cơ hội duy nhất trên iOS.
- Không xoá token khi đăng xuất — người dùng nhận thông báo của tài khoản khác.
- Không xử lý token thay đổi — thông báo im lặng ngừng tới với một số thiết bị.
- Đặt đường dẫn trong dữ liệu thông báo — hỏng toàn bộ thông báo cũ khi đổi cấu trúc.
- Coi thông báo dữ liệu và thông báo hiển thị là giống nhau — dẫn tới thông báo không xuất hiện ở một số trạng thái.
- Không có kênh thông báo riêng trên Android — người dùng tắt hết thay vì tắt phần họ không muốn.
- Gửi thông báo vào giờ không hợp lý — ảnh hưởng trực tiếp tới việc người dùng tắt thông báo.
- Không xử lý thông báo mở từ trạng thái ứng dụng đã tắt — người dùng bấm thông báo nhưng chỉ thấy trang chủ.
Đo hiệu quả của thông báo
Sau khi tính năng đã chạy ổn, ba chỉ số đáng theo dõi:
- Tỷ lệ người dùng bật thông báo. Nếu thấp, vấn đề nằm ở thời điểm xin quyền hoặc ở nội dung bạn hứa.
- Tỷ lệ mở thông báo. Chỉ số này cho biết tiêu đề và nội dung có đáng để bấm hay không. Thấp một cách bất thường thường là do nội dung chung chung.
- Tỷ lệ tắt thông báo theo kênh. Đây là dấu hiệu sớm cho biết bạn đang gửi quá nhiều hoặc gửi sai nhóm người dùng.
Cách cải thiện hiệu quả nhất không nằm ở kỹ thuật mà ở nội dung: nói rõ chuyện gì đã xảy ra và người dùng nên làm gì, thay vì những câu chung chung như "Bạn có thông báo mới".
Câu hỏi thường gặp
Thông báo có tới khi ứng dụng đã bị người dùng tắt hoàn toàn không?
Với thông báo hiển thị, có — hệ thống hiển thị mà không cần ứng dụng chạy. Với thông báo dữ liệu, hành vi khác nhau tuỳ nền tảng và không đảm bảo, nên đừng thiết kế luồng nghiệp vụ phụ thuộc vào việc này.
Có cần máy chủ riêng để gửi thông báo không?
Không bắt buộc. Bạn có thể dùng hàm đám mây của Firebase để gửi theo sự kiện. Khi hệ thống đã lớn, việc gửi từ máy chủ của bạn thường linh hoạt hơn, nhưng giai đoạn đầu dùng hàm đám mây giúp tiết kiệm thời gian.
Thông báo có hoạt động trên trình mô phỏng không?
Android thì có, iOS thì hạn chế. Hãy dùng thiết bị thật cho mọi buổi kiểm tra quan trọng, vì đây là loại tính năng mà sự khác biệt giữa trình mô phỏng và máy thật rất lớn.
Có thể gửi thông báo theo múi giờ của người dùng không?
Bạn cần tự xử lý ở phía máy chủ: lưu múi giờ của người dùng và lên lịch gửi theo giờ địa phương. Hệ thống gửi không biết múi giờ của từng người.
Nên gửi bao nhiêu thông báo mỗi tuần?
Không có con số đúng cho mọi ứng dụng, nhưng nguyên tắc là: mỗi thông báo phải mang thông tin người dùng cần hoặc hành động họ có thể làm ngay. Nếu một thông báo không đáp ứng được điều đó, nó đang làm giảm giá trị của những thông báo sau.
Kiểm soát tần suất và thời điểm gửi
Hai yếu tố này ảnh hưởng tới tỷ lệ người dùng tắt thông báo nhiều hơn cả nội dung. Ba quy tắc nên có ngay từ phiên bản đầu:
1. Giới hạn số thông báo cho một người dùng trong một ngày. Khi hệ thống có nhiều luồng sự kiện (đơn hàng, tin nhắn, khuyến mãi), số lượng thông báo rất dễ tăng nhanh vì mỗi nhóm chỉ nhìn vào luồng của mình. Cần một điểm kiểm soát chung ở tầng gửi.
2. Gộp thông báo thay vì gửi liên tiếp. Nếu trong mười phút có năm sự kiện cùng loại, hãy gửi một thông báo tổng hợp: "5 đơn hàng mới đang chờ bạn xử lý". Trên Android và iOS đều có cơ chế nhóm thông báo để hiển thị gọn, nhưng gộp ở phía máy chủ vẫn tốt hơn.
3. Tôn trọng giờ nghỉ. Thông báo tiếp thị gửi lúc nửa đêm là cách nhanh nhất để người dùng tắt thông báo vĩnh viễn. Hãy chỉ gửi trong khoảng thời gian hợp lý theo múi giờ của người dùng, và cho phép họ chọn giờ nhận.
Về mặt kỹ thuật, hãy ghi lại thời điểm gửi cuối cùng của mỗi người dùng và kiểm tra trước khi gửi. Chi phí cho việc này nhỏ, nhưng nó là khác biệt giữa một kênh liên lạc còn dùng được và một kênh đã bị tắt.
Thông báo cục bộ: khi nào dùng thay vì thông báo đẩy
Không phải thông báo nào cũng cần đi qua máy chủ. Thông báo cục bộ do chính ứng dụng lên lịch trên thiết bị, và nó phù hợp với những trường hợp sau:
- Nhắc theo thời gian do người dùng đặt — nhắc uống thuốc, nhắc học bài, nhắc hạn công việc. Những thông báo này không cần máy chủ, hoạt động cả khi không có mạng, và đáng tin cậy hơn.
- Nhắc khi người dùng chưa hoàn thành việc gì đó — ví dụ nhắc hoàn tất hồ sơ sau vài ngày. Vẫn cần máy chủ cho logic, nhưng phần hiển thị có thể đặt cục bộ.
- Nhắc ngay trong phiên sử dụng — ví dụ nhắc lưu bản nháp sau một khoảng không thao tác.
Ngược lại, thông báo đẩy cần thiết khi nội dung đến từ bên ngoài thiết bị: tin nhắn mới, đơn hàng được duyệt, nội dung mới được phát hành. Đây là những việc chỉ máy chủ biết.
Cách phân chia thực dụng: dùng thông báo cục bộ cho mọi thứ có thể tính trước trên thiết bị, dùng thông báo đẩy cho phần còn lại. Nhờ vậy bạn giảm tải cho máy chủ, giảm chi phí, và có trải nghiệm ổn định hơn khi mạng yếu.
Kết luận
Push notification là tính năng có chi phí ẩn cao: mã ứng dụng chỉ là một phần, phần còn lại nằm ở cấu hình nền tảng, quản lý token và gỡ lỗi trong môi trường thật. Bốn việc quyết định tính năng có dùng được hay không:
- Xin quyền vào đúng thời điểm, sau khi người dùng đã thấy giá trị.
- Quản lý token theo tài khoản, gồm cả việc xoá khi đăng xuất.
- Xử lý đủ ba trạng thái của ứng dụng khi nhận thông báo.
- Kiểm tra trên thiết bị thật, ở cả ba trạng thái đó.
Nếu bạn muốn đi theo lộ trình có hướng dẫn từ nền tảng đến lúc phát hành sản phẩm thật, xem các khoá học theo cấp độ:
- Flutter Cơ Bản — nền tảng ngôn ngữ, widget, giao diện và dự án đầu tiên.
- Flutter Nâng Cao — quản lý trạng thái, gọi API, Firebase và thông báo.
- Flutter Chuyên Sâu — tối ưu hiệu năng, kiểm thử và phát hành.
- Lịch khai giảng — các lớp sắp mở và cách đăng ký.
- Cam kết đầu ra & cơ hội việc làm — hỗ trợ thực tập và giới thiệu việc làm sau khoá học.
Các bài liên quan cùng chủ đề Firebase: xác thực người dùng với Firebase và xây dựng ứng dụng chat thời gian thực. Nếu bạn đang chuẩn bị phỏng vấn, phần câu hỏi về xử lý thông báo và trạng thái ứng dụng nằm trong bộ câu hỏi phỏng vấn Flutter.
