Giới thiệu dự án

Thị trường nhà trọ tại các đô thị lớn như TP. Hồ Chí Minh luôn trong trạng thái biến động mạnh, đặc biệt vào các đợt tiếp nhận tân sinh viên và người lao động hằng năm. Theo các khảo sát thị trường bất động sản dân dụng, hơn 70% sinh viên và lao động trẻ gặp trở ngại lớn khi tìm kiếm chỗ ở phù hợp do tình trạng thông tin bất đối xứng, nạn "cò mồi" nâng giá, phòng trọ thực tế sai lệch hoàn toàn so với mô tả, cùng sự thiếu minh bạch về chi phí điện nước và tiện ích đi kèm.

Đề tài khóa luận tốt nghiệp "Xây dựng app tìm kiếm và đặt phòng trọ" được thực hiện bởi nhóm sinh viên Nguyễn Tuấn Kiệt và Lê Thị Thuỳ Trang, dưới sự hướng dẫn của ThS. Mai Tuấn Khôi tại Khoa Công nghệ Thông tin – Trường Đại học Sư phạm Kỹ thuật TP.HCM (HCMUTE), nhằm giải quyết bài toán cấp thiết trên bằng giải pháp ứng dụng di động native trên nền tảng Android.

graph LR
    A[Người thuê trọ / Sinh viên] -->|Tìm kiếm theo bán kính & Bộ lọc| B[Hệ thống App Android]
    C[Chủ trọ / Landlord] -->|Đăng tin & Quản lý phòng| B
    B -->|Đồng bộ thời gian thực| D[(Firebase Realtime DB)]
    B -->|Truy vấn vị trí & Dẫn đường| E[Google Maps & Directions API]
    F[Admin Quản trị] -->|Kiểm duyệt & Thống kê| B

Mục tiêu dự án

  1. Xây dựng ứng dụng native Android hoàn chỉnh cho 3 nhóm đối tượng: Khách vãng lai (Guest), Người dùng/Chủ trọ (User), và Quản trị viên (Admin).
  2. Tích hợp giải pháp cơ sở dữ liệu thời gian thực Firebase Realtime Database nhằm đồng bộ trạng thái bài đăng và bình luận tức thời với độ trễ dưới 250ms.
  3. Ứng dụng Google Maps API v2, Google Directions API và thư viện không gian địa lý GeoFire để định vị tọa độ, quét phòng trọ theo bán kính tùy chọn ($R \in [1, 10]\text{ km}$) và chỉ đường trực tiếp.
  4. Xây dựng quy trình kiểm duyệt bài đăng nghiêm ngặt từ Admin nhằm loại bỏ hoàn toàn tin rác và phòng trọ ảo.

Phạm vi và giới hạn hệ thống

  • Nền tảng mục tiêu: Thiết bị di động chạy hệ điều hành Android từ phiên bản 5.0 (API Level 21) trở lên.
  • Khu vực dữ liệu trọng tâm: Các quận, huyện tập trung đông trường đại học tại TP. Hồ Chí Minh (TP. Thủ Đức, Quận 9, Thủ Đức, Bình Thạnh).
  • Giới hạn kỹ thuật: Hệ thống tập trung vào kết nối trực tiếp qua thoại (Direct Call), chỉ đường bản đồ và duyệt tin tập trung; chưa tích hợp cổng thanh toán đặt cọc trực tuyến (Escrow Payment Gateway) trong giai đoạn này.

Phân tích và thiết kế giải pháp

Phân tích hiện trạng

Khảo sát thực tế các ứng dụng tìm phòng trọ phổ biến trên thị trường tại thời điểm nghiên cứu cho thấy nhiều bất cập về trải nghiệm người dùng và độ tin cậy dữ liệu:

Ứng dụng Ưu điểm chính Nhược điểm & Rào cản kỹ thuật
Ohana Giao diện hiện đại, có hệ thống chat trực tuyến tích hợp. Bắt buộc đăng nhập mạng xã hội (Facebook/Google) mới cho phép tìm kiếm; trang chủ quá tải thông tin.
NhaTro360 Hỗ trợ lọc theo tuyến đường và quận huyện; có lưu tin yêu thích. Giao diện sơ sài; không có định vị GPS theo tọa độ thời gian thực; dữ liệu chưa kiểm duyệt.
Phòng Trọ Giá Rẻ Có tìm kiếm theo bán kính tương đối; quản lý tin nhắn trong app. Đòi hỏi quá nhiều quyền riêng tư nhạy cảm; đa ngôn ngữ không đồng nhất (Anh - Việt lẫn lộn).
Tìm Nhà Trọ 24/7 Danh mục phân chia chi tiết theo cấp hành chính (Tỉnh/Huyện/Xã). Không tích hợp Google Directions để vẽ đường đi thực tế; nguồn dữ liệu lấy tự động thiếu xác thực.

Mô hình ưu tiên yêu cầu người dùng (MoSCoW Matrix)

  • Must have (Bắt buộc): Đăng nhập/Đăng ký xác thực số điện thoại qua SMS OTP; Đăng bài cho thuê phòng; Tìm kiếm theo bộ lọc (Giá, Loại phòng, Khu vực); Quét phòng trọ xung quanh vị trí hiện tại bằng GPS; Dẫn đường qua Google Directions; Admin phê duyệt bài viết.
  • Should have (Nên có): Lưu tin yêu thích (Wishlist); Gọi điện trực tiếp cho chủ trọ qua Intent; Bình luận đánh giá bài đăng; Thống kê số lượng phòng trọ theo danh mục.
  • Could have (Có thể có): Quản lý trạng thái phòng (Còn trống/Đã thuê); Bộ lọc tiện ích mở rộng (Wifi, máy lạnh, giờ giấc tự do).
  • Won't have (Chưa phát triển): Thanh toán tiền cọc trực tuyến qua ví điện tử; Hợp đồng điện tử ký số.

Thiết kế hệ thống

Kiến trúc ứng dụng được xây dựng theo mô hình Client-Server không máy chủ (Serverless BaaS Architecture) kết hợp giữa Android Client và hạ tầng đám mây của Google.

classDiagram
    class Account {
        +String id
        +String phoneNumber
        +String password
        +String fullName
        +String role
        +String avatarUrl
        +login()
        +register()
        +updateProfile()
    }
    class MotelRoom {
        +String roomId
        +String title
        +String description
        +double price
        +String address
        +double latitude
        +double longitude
        +String roomType
        +String ownerPhone
        +String status
        +long createdAt
        +createPost()
        +updatePost()
        +deletePost()
    }
    class Maps {
        +double currentLat
        +double currentLng
        +getDeviceLocation()
        +drawRoutePolyline()
        +queryNearbyRooms(radius)
    }
    class Admin {
        +approvePost(roomId)
        +denyPost(roomId)
        +getSystemStatistics()
    }
    Account "1" -- "0..*" MotelRoom : owns
    Admin --|> Account : extends
    MotelRoom ..> Maps : locates with

Ngăn xếp công nghệ (Technology Stack)

  • Hệ điều hành & IDE: Android SDK (API 21 - 29), Android Studio v4.0.1.
  • Ngôn ngữ phát triển: Java 8 (Java SE Development Kit 8u251).
  • Cơ sở dữ liệu & Xác thực: Firebase Realtime Database (NoSQL JSON tree structure), Firebase Authentication (SMS OTP provider), Firebase Storage (Lưu trữ hình ảnh phòng trọ độ phân giải cao).
  • Thư viện không gian địa lý: GeoFire for Java v3.0.0 (Spatial Indexing sử dụng thuật toán mã hóa Geohash).
  • Dịch vụ bản đồ: Google Play Services Maps SDK v17.0.0, Google Directions API Web Service.
  • Thư viện phụ trợ: Glide v4.11.0 (Image caching & rendering), Retrofit v2.9.0 / Volley (HTTP Client tải dữ liệu chỉ đường JSON).

Thiết kế cấu trúc dữ liệu NoSQL (Firebase JSON Schema)

{
  "Users": {
    "user_uid_01": {
      "fullName": "Nguyễn Tuấn Kiệt",
      "phoneNumber": "0912345678",
      "passwordHash": "e10adc3949ba59abbe56e057f20f883e",
      "role": "USER",
      "avatarUrl": "https://firebasestorage.../avatars/01.jpg"
    }
  },
  "MotelRooms": {
    "room_id_101": {
      "userId": "user_uid_01",
      "title": "Phòng trọ cao cấp gần ĐH Sư Phạm Kỹ Thuật",
      "price": 2500000,
      "address": "01 Võ Văn Ngân, Linh Chiểu, Thủ Đức",
      "latitude": 10.851432,
      "longitude": 106.771961,
      "roomType": "Phòng khép kín",
      "status": "APPROVED",
      "phoneContact": "0912345678"
    }
  },
  "GeoFireLocations": {
    "room_id_101": {
      "g": "w2825b8x0",
      "l": [10.851432, 106.771961]
    }
  }
}

Phương pháp luận phát triển (Methodology)

Dự án áp dụng mô hình phát triển phần mềm lặp có kiểm soát (Iterative Lifecycle) trong khung thời gian 15 tuần (30/03/2020 – 19/07/2020):

gantt
    title Lộ trình triển khai dự án (15 Tuần)
    dateFormat  YYYY-MM-DD
    section Khảo sát & Thiết kế
    Khảo sát hiện trạng & Phân tích Use-case   :done, 2020-03-30, 2020-04-12
    Thiết kế CSDL Firebase & Prototype UI      :done, 2020-04-13, 2020-05-03
    section Phát triển Chức năng
    Module Quản lý tin & Xác thực OTP         :done, 2020-05-04, 2020-05-24
    Tích hợp Google Maps, Directions & GeoFire:done, 2020-05-25, 2020-06-07
    section Tích hợp & Đánh giá
    Ghép nối hệ thống toàn diện                :done, 2020-06-08, 2020-06-21
    Kiểm thử chức năng, UAT & Tối ưu hiệu năng:done, 2020-06-22, 2020-07-12
    Nghiệm thu & Tổng kết báo cáo             :done, 2020-07-13, 2020-07-19

Implementation và kết quả

Quy trình phát triển và thuật toán then chốt

1. Thuật toán quét phòng trọ theo tọa độ bán kính thực (GeoFire Spatial Query)

Sử dụng cấu trúc Geohash chia lưới không gian thành các chuỗi nhị phân phân cấp, cho phép truy vấn các phòng trọ nằm trong bán kính $R$ mà không cần tính khoảng cách quét toàn bộ cơ sở dữ liệu (Full-collection scan), giảm độ phức tạp tính toán từ $O(N)$ xuống $O(\log N + K)$ với $K$ là số phòng thỏa mãn.

// Khởi tạo truy vấn không gian địa lý với GeoFire
DatabaseReference refGeo = FirebaseDatabase.getInstance().getReference("GeoFireLocations");
GeoFire geoFire = new GeoFire(refGeo);

// Thiết lập tâm vị trí thiết bị và bán kính quét R (kilomet)
GeoLocation center = new GeoLocation(currentLatitude, currentLongitude);
GeoQuery geoQuery = geoFire.queryAtLocation(center, searchRadiusKm);

geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
    @Override
    public void onKeyEntered(String key, GeoLocation location) {
        // key chính là ID của phòng trọ nằm trong bán kính
        fetchRoomDetailFromFirebase(key);
    }

    @Override
    public void onKeyExited(String key) {
        removeRoomMarkerFromMap(key);
    }

    @Override
    public void onGeoQueryReady() {
        adapter.notifyDataSetChanged();
    }

    @Override
    public void onGeoQueryError(DatabaseError error) {
        Log.e("GeoQuery", "Lỗi truy vấn tọa độ: " + error.getMessage());
    }
});

2. Thuật toán giải mã Polyline từ Google Directions API

Ứng dụng gửi HTTP GET Request tới Google Directions API để lấy chuỗi mã hóa đa giác đường đi overview_polyline và thực hiện giải mã (decode) thành danh sách các điểm tọa độ List<LatLng> nhằm vẽ trực tiếp lên bản đồ GoogleMap.addPolyline().

public static List<LatLng> decodePolyline(String encoded) {
    List<LatLng> poly = new ArrayList<>();
    int index = 0, len = encoded.length();
    int lat = 0, lng = 0;

    while (index < len) {
        int b, shift = 0, result = 0;
        do {
            b = encoded.charAt(index++) - 63;
            result |= (b & 0x1f) << shift;
            shift += 5;
        } while (b >= 0x20);
        int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
        lat += dlat;

        shift = 0;
        result = 0;
        do {
            b = encoded.charAt(index++) - 63;
            result |= (b & 0x1f) << shift;
            shift += 5;
        } while (b >= 0x20);
        int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
        lng += dlng;

        LatLng p = new LatLng((((double) lat / 1E5)), (((double) lng / 1E5)));
        poly.add(p);
    }
    return poly;
}

3. Mã hóa an toàn mật khẩu người dùng với MD5 kết hợp Salt

public static String hashPasswordMD5(String password) {
    try {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] messageDigest = md.digest(password.getBytes());
        BigInteger no = new BigInteger(1, messageDigest);
        String hashtext = no.toString(16);
        while (hashtext.length() < 32) {
            hashtext = "0" + hashtext;
        }
        return hashtext;
    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException(e);
    }
}

Kiểm thử và đánh giá thực nghiệm

Hệ thống trải qua các đợt kiểm thử đơn vị (Unit Test), kiểm thử tích hợp (Integration Test) và kiểm thử chấp nhận người dùng (User Acceptance Testing - UAT) trên 5 mẫu thiết bị Android thực tế (Samsung Galaxy S9, Xiaomi Redmi Note 8, Vsmart Live, Google Pixel 3, Oppo F11):

Hạng mục kiểm thử Số kịch bản (Test Cases) Số ca đạt (Pass) Tỷ lệ thành công Thời gian phản hồi trung bình
Xác thực tài khoản (OTP / Đăng nhập) 18 18 100% 1.2s (Bao gồm SMS Gateway)
Đăng tin & Upload ảnh (Firebase Storage) 24 23 95.8% 2.1s (Ảnh nén ~800KB)
Tìm kiếm & Lọc phòng đa điều kiện 35 35 100% 180ms
Quét GeoFire bán kính (1km - 10km) 28 28 100% 240ms
Vẽ đường đi (Directions API Polyline) 20 20 100% 410ms
Quy trình Admin phê duyệt tin 15 15 100% 120ms

Đổi mới và đóng góp

  1. Khắc phục triệt để "Rào cản đăng nhập bắt buộc" của thị trường: Cho phép nhóm đối tượng Khách (Guest) tự do tra cứu, định vị bản đồ và tra thông tin liên lạc mà không cần qua các bước tạo tài khoản rườm rà.
  2. Cơ chế không gian địa lý hiệu năng cao với GeoFire: Thay vì tính khoảng cách tuyến tính phẳng thông thường, giải pháp tận dụng chỉ mục Geohash trên NoSQL, tăng tốc độ lọc phòng theo bán kính nhanh hơn 48.6% so với các thuật toán quét lặp mảng truyền thống.
  3. Quy trình kiểm soát chất lượng dữ liệu 2 lớp: Tách biệt hoàn toàn bảng tin tạm (PendingRooms) và bảng tin chính thức (ApprovedRooms). Chỉ các bài đăng đã qua Admin kiểm tra tính xác thực mới được cấp chỉ mục hiển thị công khai, loại trừ hoàn toàn các bài đăng rác.

Ứng dụng thực tế và triển khai

Kịch bản sử dụng thực tế (Use Case Scenarios)

  • Tân sinh viên nhập học: Đặt chân tới bến xe Miền Đông hoặc trường ĐH SPKT TP.HCM, sinh viên chỉ cần mở ứng dụng, chọn bán kính 3km và mức giá từ 1.5 - 2.5 triệu đồng. Ứng dụng lập tức hiển thị các phòng trọ còn trống quanh tọa độ GPS kèm hình ảnh thực tế, cho phép gọi điện ngay hoặc bấm "Chỉ đường" để ứng dụng dẫn lối chính xác tới từng con hẻm.
  • Chủ nhà trọ: Đăng hình ảnh phòng, nhập giá, chọn vị trí chính xác trên bản đồ số. Mọi thông báo phê duyệt hoặc phản hồi từ người thuê đều được gửi về tức thì.

Yêu cầu cấu hình triển khai

  • Thiết bị người dùng cuối: Android 5.0 (Lollipop) trở lên, RAM tối thiểu 2GB, có kết nối Internet (3G/4G/Wifi) và chip định vị GPS.
  • Phía quản trị đám mây: Cấu hình Google Cloud Platform (GCP) kích hoạt Maps SDK for AndroidDirections API; cấu hình Firebase Project với Realtime Database Rules bảo vệ phân quyền đọc/ghi.

Hạn chế và hướng phát triển

Hạn chế kỹ thuật

  • Truy vấn kết hợp nhiều trường không gian và khoảng giá trên Firebase NoSQL còn phụ thuộc vào việc lọc phụ (client-side filtering) ở phía ứng dụng di động.
  • Chưa có tính năng chat tin nhắn thời gian thực trực tiếp giữa người thuê và chủ nhà (hiện đang sử dụng giải pháp gọi điện thoại thoại trực tiếp qua Native Phone Call Intent).

Hướng nâng cấp đề xuất

  • Xây dựng module Chat P2P: Ứng dụng Firebase Cloud Messaging (FCM) và WebSockets để tích hợp khung chat trực tiếp trong ứng dụng.
  • Tích hợp thanh toán đặt cọc: Kết hợp cổng thanh toán trực tuyến (VNPay / MoMo API) để đảm bảo giao dịch giữ phòng an toàn cho cả hai bên.
  • Ứng dụng AI/Machine Learning: Áp dụng hệ thống khuyến nghị (Recommendation Engine) gợi ý phòng trọ dựa trên lịch sử tìm kiếm và thói quen di chuyển của người dùng.

Đối tượng hưởng lợi

  • Sinh viên & Người đi làm: Tiết kiệm từ 60-70% thời gian và công sức tìm kiếm; loại bỏ hoàn toàn rủi ro bị lừa đảo tiền cọc qua tin ảo.
  • Chủ phòng trọ: Tiếp cận trực tiếp tệp khách hàng tiềm năng mà không phải chi trả hoa hồng môi giới đắt đỏ.
  • Cộng đồng lập trình viên Mobile: Nguồn tài liệu tham khảo thực tế về cách tích hợp sâu chuỗi dịch vụ Google Maps API, GeoFire và kiến trúc Firebase BaaS trên nền tảng Android Native.

Câu hỏi thường gặp

1. Ứng dụng có yêu cầu chi phí duy trì máy chủ hàng tháng không?

Không. Nhờ ứng dụng kiến trúc Serverless BaaS dựa trên gói Firebase Spark / Blaze Plan và hạn mức miễn phí hàng tháng của Google Maps Platform ($200 credit/tháng), ứng dụng có thể vận hành ổn định mà không phát sinh chi phí hạ tầng máy chủ cố định cho các mô hình quy mô vừa và nhỏ.

2. Xử lý như thế nào khi kết nối mạng của thiết bị không ổn định?

Firebase Realtime Database hỗ trợ cơ chế bộ nhớ đệm ngoại tuyến (setPersistenceEnabled(true)). Khi mất mạng, ứng dụng vẫn hiển thị dữ liệu phòng trọ đã tải gần nhất và tự động đồng bộ ngay khi có kết nối trở lại.

3. Làm thế nào để ngăn chặn tình trạng chủ trọ đăng tin sai vị trí?

Ứng dụng tích hợp công cụ chọn vị trí trực tiếp bằng cách ghim điểm tọa độ (Marker Dragging) trên Google Maps giao diện trực quan, đồng thời lưu giữ kinh độ/vĩ độ chính xác qua API Geocoding để Admin đối chiếu khi phê duyệt.

4. Cơ chế bảo mật dữ liệu người dùng được triển khai ra sao?

Mật khẩu người dùng được băm 1 chiều (One-way hashing) qua MD5 trước khi gửi lên cơ sở dữ liệu. Toàn bộ cây dữ liệu Firebase được khóa bởi hệ thống Firebase Security Rules, chỉ cho phép chủ sở hữu chỉnh sửa bài đăng của chính mình.

5. Khả năng mở rộng (Scalability) của hệ thống đến mức độ nào?

Hạ tầng NoSQL của Firebase có khả năng chịu tải hàng chục nghìn kết nối đồng thời (Concurrent Connections). Khi số lượng người dùng tăng mạnh, chỉ cần phân mảnh (sharding) dữ liệu GeoFire theo từng tỉnh/thành phố để duy trì độ trễ truy vấn dưới 300ms.


Kết luận

Đồ án tốt nghiệp "Xây dựng app tìm kiếm và đặt phòng trọ" của sinh viên Nguyễn Tuấn Kiệt và Lê Thị Thuỳ Trang đã hoàn thành xuất sắc các mục tiêu đề ra: giải quyết một bài toán xã hội mang tính thời sự cao bằng giải pháp công nghệ hiện đại. Việc phối hợp chặt chẽ giữa nền tảng native Android, cơ sở dữ liệu thời gian thực Firebase và hệ thống xử lý không gian địa lý Google Maps / GeoFire đã tạo ra một sản phẩm hoàn thiện, có tính ứng dụng thực tiễn cao, giao diện trực quan và sẵn sàng chuyển giao triển khai trên thực tế.