Xây dựng ứng dụng chụp ảnh và filter camera trên Android (p1)

Ngày nay, tính năng chụp và chỉnh sửa ảnh đã trở nên cực kỳ phổ biến trong các ứng dụng smart phone. Hôm qua nhân dịp vọc vạch nấu nướng mình có download và sử dụng app Feedy để thực hành theo. Chợt nhận ra Feedy cũng có 1 module cho phép user chụp ảnh (có filter camera) và chỉnh sửa ảnh. Mình thấy rất thú vị nên mình cũng clone luôn để làm 1 loạt bài tutorial về filter trên Android. Sau đây là demo ứng dụng của mình:

Các chức năng chính trong app mình xây dựng sẽ bao gồm:

  • Chụp ảnh (có filter camera, sử dụng camera trước hoặc camera sau)
  • Chỉnh sửa ảnh (lựa chọn filter)
  • Cắt ảnh, viết caption cho ảnh và chia sẻ
  • Đơn giản thôi đúng không nào. Giờ mình sẽ bắt tay vào làm nhé.

Các thư viện sử dụng trong dự án

Lưu ý: Link source code ở cuối bài viết 😉

Mình sẽ dùng các thư viện sau:

  • Android – GPU Image Plus: Đây là 1 thư viện filter khá mạnh với nhiều tính năng. Nó cung cấp cho ta các tính năng cơ bản như điều khiển độ sáng, độ phân giản, độ tương phản, … Ngoài ra thư viện này cung cấp cho ta tính năng sử dụng những file Lookup table (LUT) để áp dụng filter lên bitmap. Ngoài ra còn rất nhiều tính năng về xử lý ảnh khác nữa. Phần core của thư viện này viết bằng C/C++.
  • Glide: Thư viện load ảnh.
  • ButterKnife: Thư viện inject view, đỡ phải sử dụng findViewById rất dài dòng và nhàm chán.
  • SimpleCropView: Thư viện cho phép ta cắt 1 vùng của bitmap.
  • RoundedImageView: Thư viện bo góc cho imageview, do mình lười custom nên mình cũng dùng thư viện luôn cho nhanh.

Đó là những thư viện cơ bản mình dùng trong project.

Sơ lược về luồng đi của ứng dụng

Ứng dụng của chúng ta gồm 4 màn hình:

  • Splash screen hiển thị logo của ứng dụng đồng thời xin quyền đọc ghi trên bộ nhớ máy (để lưu ảnh), quyền sử dụng camera .
  • Camera screen: Chụp ảnh, lựa chọn hiệu ứng
  • Result screen: Sau khi chụp ảnh, hiển thị ảnh đầu ra, cắt ảnh, chỉnh sửa ảnh
  • Share screen: Hiển thị ảnh cuối cùng sau khi chỉnh sửa, viết caption và share ảnh.

Bắt đầu

Việc đầu tiên sẽ là… tạo project rồi. Tất nhiên, các bạn hãy tạo 1 project để code nhé 😀

Import thư viện

Mình sẽ import các thư viện kể trên vào dự án, thêm các lệnh này vào file build.gradle (level app):

Tạo base cho dự án

Permission

Ứng dụng cần quyền sử dụng camera và quyền đọc ghi file trên thiết bị Vì vậy ta cần thêm các dòng sau vào file AndroidManifest.xml:

Font chữ

Mình sử dụng font Roboto cho dự án này. Trong thư mục main, mình sẽ tạo 1 thư mục assets chứa thư mục con Fonts (là nơi mình đặt các file Font chữ)

Gói image filter

Trong dự án này mình sẽ sử dụng các file Lookup table (LUT) – là các file chứa các thông số filter để chỉnh sửa màu sắc cho ảnh. Các file này chứa trong thư mục assets mình đã tạo bên trên:

Đây là các file chứa các thông số cho các filter mình sử dụng trong app.

BaseActivity

Như ở phần trên mình đã phân tích, luồng đi của ứng dụng qua 4 màn hình. Mình sẽ sử dụng các Activity tương ứng với mỗi màn, vậy ta có tổng cộng 4 Activity. Để code được ngắn gọn và tường minh, mình sẽ viết 1 lớp BaseActivity.java. Lớp này chứa 1 số phương thức chung có thể sử dụng cho tất cả các Activity trong dự án. Mọi Activity sẽ kế thừa từ lớp BaseActivity này:

Utils

Trong ứng dụng, có những chức năng ta cần đến kích thước màn hình, hoặc cần mở App Setting để user cấp quyền cho app. Những chức năng này mình viết trong 1 lớp DeviceUtils.java. Mình sẽ tạo 1 package đặt tên là utils để chưa file DeviceUtils.java.

Màn hình splash

Khai báo layout

Sau khi tạo xong base dự án ta sẽ bắt  tay vào màn hình đầu tiên, là màn hình splash. Đây là màn hình có chức năng hiển thị ra 1 dòng text giới thiệu dưới dạng animation, đồng thời xin cấp các quyền mà ứng dụng sẽ sử dụng. Đây là file layout activity_spalsh.xml:

Đơn giản chỉ là 2 TextView giới thiệu về app thôi.

Khai báo SplashActivity trong AndroidManifest

Giờ ta sẽ tạo 1 file đặt tên là SplashActivity để viết nội dung cho màn hình splash. Class này sẽ kế thừa BaseActivity. Đồng thời trong AndroidManifest, ta khai báo SplashActivity là màn hình đầu tiên của ứng dụng (thay vì MainActivity mặc định):

Lớp SplashActivity:

Đơn giản là khai báo layoutId và khai báo 1 TextView thôi đúng không. Giờ ta muốn cho TextView này 1 animation. Khi kết thúc animation, ta sẽ kiểm tra các quyền đọc ghi file, camera được cấp chưa. Nếu chưa được cấp thì sẽ bật ra dialog xin cấp quyền. Ta sẽ viết hàm animate để làm điều này.

Animation

Như các bạn thấy mình sử dụng AnimationListener để lắng nghe sự kiện animation kết thúc. Giờ ta sẽ viết hàm askForPermission để thực hiện bật dialog xin quyền từ user trong trường hợp các quyền ta sử dụng chưa được cấp phép. Nếu được cấp rồi thì nhảy thẳng đến màn hình Camera.

Phương thức xin cấp permission

Quay lại với BaseActivity 1 chút. Trong app này, mình chỉ có 1 chỗ cần phải xin quyền từ user, đó là ở SplashScreen. Tuy nhiên trong thực tế, 1 app có thể có nhiều lớp cần implement tính năng xin cấp quyền. Vì vậy mình sẽ viết hàm askCompactPermissions thực hiện tính năng này trong lớp BaseActivity. Các lớp kế thừa lớp BaseActivity sẽ đều có thể sử dụng hàm askCompactPermissions này để xin cấp quyền.

Đầu tiên ta viết 1 lớp PermissionUtils trong package utils:

Lớp này chứa các quyền ta cần xin (đọc ghi file, camera) và 1 interface PermissionResult xử lý các hành động của người dùng.

Trong BaseActivity, mình khởi tạo các biến sử dụng cho việc xin cấp quyền:

Và viết hàm askCompactPermissions như sau:

Các hàm trên đảm nhiệm chức năng kiểm tra và hiển thị hộp thoại cấp quyền trong trường hợp người dùng chưa cấp quyền cho ứng dụng. Do đây ko phải trọng tâm ứng dụng nên mình sẽ ko nói quá kỹ phần này. Các bạn có thể tìm hiểu thêm hoặc sử dụng các thư viện hỗ trợ.

Sử dụng phương thức cấp permission

OK, đã viết hàm xin permission xong ở BaseActivity, giờ quay trở lại SplashScreen. Ta sẽ gọi hàm xin permission trong askForPermission:

Nội dung hàm này là: trong trường hợp permission được cấp, ta nhảy đến MainActivity (sẽ định nghĩa sau). Nếu không được cấp, thoát app. Nếu người dùng chọn option vĩnh viễn không cấp, ta sẽ hiện dialog yêu cầu người dùng bật App Setting và cấp lại quyền, nếu không sẽ thoát app.

Ngon rồi, giờ ta sẽ gọi hàm animate trong onResume của SplashActivity để thực hiện animation cho TextView:

Như vậy là mỗi khi vào app, hàm animate sẽ được gọi. Nó tạo ra 1 animation cho textview và khi animation kết thúc, kiểm tra trạng thái cấp quyền của ứng dụng.

Tổng kết

Ở phần đầu tiên của loạt bài hướng dẫn xây dựng app filter ảnh, mình đã giới thiệu tới các bạn các thư viện sử dụng trong app, cách tạo base project và xây dựng màn hình splash cho ứng dụng. Bài sau mình sẽ hướng dẫn xây dựng module chọn ảnh với các chức năng filter camera, và chức năng chọn ảnh trực tiếp từ bộ nhớ. Hãy theo dõi nhé.

Source code.

Hãy chia sẻ

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *