Giới thiệu dự án
Sự bùng nổ của các thiết bị di động thông minh giai đoạn 2010–2011 đã mở ra kỷ nguyên chuyển dịch từ điện thoại cơ bản (feature phone) sang điện thoại thông minh (smartphone). Theo thống kê của Gartner, thị phần hệ điều hành Android trong giai đoạn này tăng trưởng đột biến hơn 800% so với cùng kỳ các năm trước, trở thành nền tảng mã nguồn mở hàng đầu thách thức trực tiếp iOS, Symbian và BlackBerry OS. Người dùng không còn giới hạn nhu cầu ở nghe gọi hay gửi tin nhắn SMS đơn thuần, mà đòi hỏi khả năng xử lý truyền thông đa phương tiện toàn diện: nghe nhạc chất lượng cao, phát video độ phân giải chuẩn, duyệt tập tin từ thẻ nhớ ngoài và phát nhạc chạy nền đa nhiệm.
Tuy nhiên, trên các thiết bị di động cấu hình hạn chế (RAM từ 256MB–512MB, CPU đơn nhân 600MHz–1GHz), việc xây dựng một trình phát đa phương tiện vừa đảm bảo hiệu năng mượt mà, vừa quản lý bộ nhớ tối ưu và không bị rò rỉ tài nguyên hệ thống (memory leaks) là bài toán kỹ thuật phức tạp. Đề tài "Lập trình đa phương tiện trên nền Android" (do sinh viên Nông Thế Hiệp thực hiện, dưới sự hướng dẫn của TS. Đinh Đức Hùng – Khoa Công nghệ Thông tin, Trường Đại học Hòa Bình) giải quyết trực diện các thách thức này thông qua việc phân tích sâu kiến trúc Android OS và triển khai ứng dụng Media Player hoàn chỉnh.
+-------------------------------------------------------------------------+
| MỤC TIÊU CỐT LÕI CỦA ĐỒ ÁN |
+-------------------------------------------------------------------------+
| 1. Nghiên cứu toàn diện kiến trúc Android (Linux Kernel 2.6, DVM, API) |
| 2. Phân tích chu trình trạng thái và cơ chế hoạt động của MediaPlayer |
| 3. Xây dựng ứng dụng nghe nhạc và xem video tích hợp trên cùng một nền |
| 4. Triển khai Service chạy nền đảm bảo âm thanh phát liên tục khi ẩn UI |
| 5. Tối ưu hóa hiệu năng render Video bằng SurfaceView và SurfaceHolder |
+-------------------------------------------------------------------------+
Giải pháp tiếp cận của đề tài dựa trên việc tích hợp sâu các API cốt lõi trong gói android.media, tận dụng cơ chế đa luồng (multi-threading) của nhân Linux 2.6 và máy ảo Dalvik (Dalvik Virtual Machine - DVM). Thay vì sử dụng các thư viện cồng kềnh từ bên thứ ba, đồ án tập trung khai thác trực tiếp sức mạnh nguyên bản của bộ SDK mã nguồn mở do Google phát triển.
Chỉ số kết quả kỳ vọng đạt được:
- Thời gian quét (scan) và hiển thị danh mục bài hát/video từ bộ nhớ flash/SD Card: $\le 2.5\text{ giây}$ cho 500 tập tin.
- Dung lượng bộ nhớ RAM chiếm dụng khi phát nhạc nền: $\le 18.5\text{ MB}$.
- Tỷ lệ giật/trễ khung hình (frame dropping) khi phát video chuẩn MPEG-4/H.264: $< 1.5%$.
- Khả năng duy trì phát nhạc nền (background playback) không bị hệ điều hành tiêu diệt (kill process) khi chuyển đổi tác vụ.
Phạm vi giới hạn của đề tài tập trung vào việc lập trình xử lý đa phương tiện cục bộ (local storage) trên hệ điều hành Android phiên bản 1.5 (Cupcake) đến 2.3 (Gingerbread), thử nghiệm trên môi trường máy ảo AVD (Android Virtual Device) và thiết bị thực tế.
Phân tích và thiết kế giải pháp
Phân tích hiện trạng
Tại thời điểm nghiên cứu, các giải pháp phát đa phương tiện trên thiết bị di động phân hóa mạnh mẽ giữa các nền tảng đóng và mở:
| Tiêu chí so sánh |
Symbian S60 Media Player |
Windows Mobile Media Player |
Trình phát Media Player của đề tài |
| Bản quyền & Mã nguồn |
Đóng / Độc quyền Nokia |
Đóng / Phụ thuộc Microsoft |
Mã nguồn mở (Apache License 2.0) |
| Quản lý tiến trình nền |
Giới hạn đa nhiệm, tốn pin |
Xử lý đa nhiệm kém tối ưu |
Tách biệt Activity và Service |
| Khả năng mở rộng giao diện |
Cứng nhắc, khó tùy biến UI |
Phụ thuộc skin tĩnh |
Layout XML linh hoạt qua TabHost |
| Hỗ trợ Codec cơ bản |
MP3, AAC, 3GP |
WMA, WMV, MP3 |
MP3, OGG, WAV, AAC, MP4, 3GP |
| Mức tiêu hao tài nguyên |
Thấp nhưng thiếu linh hoạt |
Rất cao (> 35MB RAM) |
Tối ưu hóa trên máy ảo Dalvik (~18MB) |
Hệ thống yêu cầu người dùng được phân loại rõ ràng theo mô hình MoSCoW:
- Must Have (Bắt buộc): Tải tự động danh sách nhạc/video từ SD Card, phát/tạm dừng/chuyển bài, tua thời gian bằng SeekBar, phát nhạc chạy ngầm.
- Should Have (Nên có): Chế độ phát ngẫu nhiên (Shuffle), lặp lại (Repeat), hiển thị thời lượng thực và tổng thời gian phát.
- Could Have (Có thể có): Giao diện chia tab phân tách giữa âm thanh và video (
TabHost).
- Won't Have (Chưa thực hiện): Tải luồng trực tuyến từ máy chủ từ xa (Online streaming), chỉnh âm Equalizer nâng cao.
Thiết kế hệ thống
Kiến trúc hệ thống được thiết kế tuân theo mô hình phân tách tầng nghiêm ngặt của hệ điều hành Android, đảm bảo sự độc lập giữa lớp giao diện trực quan và lớp dịch vụ phát media ngầm.
+---------------------------------------------------------------------+
| KIẾN TRÚC HỆ THỐNG |
+---------------------------------------------------------------------+
| |
| [TẦNG ỨNG DỤNG / GIAO DIỆN (UI LAYER)] |
| +---------------------------------------------------------------+ |
| | MainActivity (TabHost) | |
| | +------------------------+ +-----------------------------+ | |
| | | SongListActivity | | VideoListActivity | | |
| | | (ListView + CustomUI) | | (ListView + MediaThumbnails)| | |
| | +------------------------+ +-----------------------------+ | |
| | +------------------------+ +-----------------------------+ | |
| | | AudioPlayerActivity | | VideoPlayerActivity | | |
| | | (SeekBar/ImageButton) | | (SurfaceView/SurfaceHolder) | | |
| | +------------------------+ +-----------------------------+ | |
| +---------------------------------------------------------------+ |
| | |
| Explicit Intent |
| v |
| [TẦNG ĐIỀU KHIỂN & XỬ LÝ NỀN (CONTROLLER & SERVICE LAYER)] |
| +---------------------------------------------------------------+ |
| | AudioService (android.app.Service) | |
| | - Quản lý trạng thái phát đa luồng | |
| | - Liên kết tương tác với UI qua BroadcastReceiver | |
| +---------------------------------------------------------------+ |
| | |
| Direct API Call |
| v |
| [TẦNG NỀN TẢNG ĐA PHƯƠNG TIỆN (CORE MULTIMEDIA FRAMEWORK)] |
| +---------------------------------------------------------------+ |
| | android.media.MediaPlayer (State Machine Engine) | |
| | +---------------------------------------------------------+ | |
| | | Codec Engine: PacketVideo OpenCORE / Stagefright | | |
| | | Audio Decoders: MP3 CBR/VBR, AAC-LC, Ogg Vorbis, PCM | | |
| | | Video Decoders: MPEG-4 Simple Profile, H.264 Baseline | | |
| | +---------------------------------------------------------+ | |
| +---------------------------------------------------------------+ |
| | |
| JNI Calls |
| v |
| [TẦNG HỆ ĐIỀU HÀNH & PHẦN CỨNG (LINUX KERNEL 2.6 & DRIVERS)] |
| +---------------------------------------------------------------+ |
| | ALSA Audio Driver | Framebuffer | SD Card Block Device Driver | |
| +---------------------------------------------------------------+ |
| |
+---------------------------------------------------------------------+
Technology Stack chi tiết:
- Môi trường phát triển tích hợp (IDE): Eclipse IDE for Java Developers (v3.5 Galileo / v3.6 Helios).
- Bộ công cụ phát triển: Android SDK (API Level 3 đến API Level 10), plugin ADT (Android Development Tools) v10.0.
- Ngôn ngữ lập trình: Java SE 6, Android XML Layout Specification.
- Máy ảo thực thi: Dalvik Virtual Machine (định dạng bytecode
.dex).
- Nền tảng nhân cốt lõi: Linux Kernel 2.6.29 / 2.6.32.
Yêu cầu an ninh và quyền hệ thống (AndroidManifest.xml):
android.permission.WAKE_LOCK: Giữ CPU hoạt động liên tục khi màn hình tắt trong quá trình phát nhạc.
android.permission.READ_PHONE_STATE: Tự động ngắt (pause) âm thanh khi có cuộc gọi thoại đến.
android.permission.WRITE_EXTERNAL_STORAGE: Truy xuất dữ liệu đa phương tiện từ thẻ nhớ ngoài SD Card.
Methodology
Quy trình phát triển được xây dựng dựa trên mô hình Thác nước kết hợp lặp linh hoạt (Iterative Waterfall Model) kéo dài trong 14 tuần:
Tuần 01 - 03: Khảo sát kiến trúc Android OS, DVM, chu trình sống Activity & Service.
Tuần 04 - 06: Thiết lập môi trường Eclipse, cấu hình Android SDK/AVD Manager, phân tích định dạng Codec.
Tuần 07 - 09: Xây dựng Module quét tập tin (MediaScanner) và Module Audio Player.
Tuần 10 - 11: Phát triển Module Video Player sử dụng SurfaceView và điều khiển giao diện TabHost.
Tuần 12 - 13: Kiểm thử tải, đo lường bộ nhớ, sửa lỗi rò rỉ tài nguyên, thử nghiệm trên máy thật.
Tuần 14: Hoàn thiện báo cáo, đóng gói bản dựng APK phát hành.
Chiến lược đánh giá rủi ro:
- Rủi ro rò rỉ bộ nhớ do không giải phóng
MediaPlayer: Khắc phục bằng cách gắn chặt phương thức release() vào sự kiện onDestroy() của Activity và Service.
- Rủi ro giật hình/treo giao diện (ANR - Application Not Responding): Đưa các tác vụ chuẩn bị dữ liệu nặng (
prepareAsync()) sang luồng phụ thay vì gọi prepare() trực tiếp trên Main UI Thread.
Implementation và kết quả
Development process
Quá trình xây dựng ứng dụng được phân chia thành 3 phân hệ chính: Quản lý danh mục lưu trữ, Động cơ giải mã âm thanh chạy nền, và Phân hệ kết xuất hình ảnh video.
1. Quản lý chu trình trạng thái của android.media.MediaPlayer
Trái tim của ứng dụng là cỗ máy trạng thái (State Machine) phức tạp của lớp MediaPlayer. Việc gọi hàm sai trạng thái (ví dụ gọi start() khi đang ở trạng thái Idle hoặc chưa gọi prepare()) sẽ dẫn đến ngoại lệ nghiêm trọng IllegalStateException.
Đoạn mã điều khiển cốt lõi của bộ phát đa phương tiện:
package com.mediaplayer.service;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.IBinder;
import java.io.IOException;
public class AudioPlaybackService extends Service implements
MediaPlayer.OnPreparedListener,
MediaPlayer.OnCompletionListener,
MediaPlayer.OnErrorListener {
private MediaPlayer mMediaPlayer = null;
private boolean isPaused = false;
@Override
public void onCreate() {
super.onCreate();
initializeMediaPlayer();
}
private void initializeMediaPlayer() {
if (mMediaPlayer == null) {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setOnPreparedListener(this);
mMediaPlayer.setOnCompletionListener(this);
mMediaPlayer.setOnErrorListener(this);
}
}
public void playMedia(String mediaPath) {
try {
mMediaPlayer.reset(); // Chuyển từ bất kỳ trạng thái nào về IDLE
mMediaPlayer.setDataSource(mediaPath); // Chuyển sang INITIALIZED
mMediaPlayer.prepareAsync(); // Chuyển sang PREPARING (Bất đồng bộ)
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onPrepared(MediaPlayer mp) {
// Chuyển sang PREPARED -> Sẵn sàng phát mà không treo UI Thread
mp.start(); // Chuyển sang STARTED
isPaused = false;
}
@Override
public void onCompletion(MediaPlayer mp) {
// Chuyển sang PLAYBACK COMPLETED -> Tự động chuyển bài tiếp theo
Intent intent = new Intent("MEDIA_PLAYER_ACTION_NEXT");
sendBroadcast(intent);
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// Trạng thái ERROR -> Khởi tạo lại tài nguyên
mp.reset();
return true;
}
@Override
public void onDestroy() {
if (mMediaPlayer != null) {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.stop();
}
mMediaPlayer.release(); // Giải phóng hoàn toàn vùng nhớ C++ Core
mMediaPlayer = null;
}
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
2. Kết xuất Video thời gian thực qua SurfaceView
Video đòi hỏi cơ chế vẽ trực tiếp xuống bộ nhớ đệm phần cứng (Hardware Framebuffer) để tránh tắc nghẽn giao diện đồ họa. Ứng dụng triển khai SurfaceHolder.Callback để đồng bộ kích thước khung hình video:
package com.mediaplayer.ui;
import android.app.Activity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class VideoPlayerActivity extends Activity implements SurfaceHolder.Callback {
private MediaPlayer mMediaPlayer;
private SurfaceView mSurfaceView;
private SurfaceHolder mHolder;
private String videoPath = "/sdcard/Movies/sample.mp4";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_player);
mSurfaceView = (SurfaceView) findViewById(R.id.video_surface);
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
// Thiết lập bộ nhớ đệm dạng Push Buffers cho phiên bản Android 2.x
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDisplay(holder); // Gắn kết Surface hiển thị
mMediaPlayer.setDataSource(videoPath);
mMediaPlayer.prepare();
mMediaPlayer.start();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mMediaPlayer != null) {
mMediaPlayer.release();
mMediaPlayer = null;
}
}
}
3. Thiết kế giao diện bằng XML (Layout & Buttons)
Cấu trúc giao diện bộ điều khiển phát nhạc (layout_player.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#1C1C1C"
android:padding="10dp">
<TextView
android:id="@+id/tv_track_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Đang tải tiêu đề bài hát..."
android:textColor="#FFFFFF"
android:textSize="18sp"
android:gravity="center"
android:layout_marginTop="20dp" />
<SeekBar
android:id="@+id/player_seekbar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:max="100" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
android:layout_marginTop="20dp">
<ImageButton
android:id="@+id/btn_previous"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_media_previous"
android:background="@null" />
<ImageButton
android:id="@+id/btn_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:src="@drawable/ic_media_play"
android:background="@null" />
<ImageButton
android:id="@+id/btn_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_media_next"
android:background="@null" />
</LinearLayout>
</LinearLayout>
Testing và validation
Quá trình kiểm thử được tiến hành trên môi trường giả lập AVD với nhiều độ phân giải (QVGA $240 \times 320$, HVGA $320 \times 480$, WVGA854 $480 \times 854$) và kiểm thử trên thiết bị thực tế.
+-------------------------------------------------------------------------+
| KỊCH BẢN KIỂM THỬ VÀ ĐỘ BAO PHỦ DỮ LIỆU |
+-------------------------------------------------------------------------+
| TC-01: Phát tệp âm thanh định dạng MP3 (CBR 320kbps & VBR). -> PASS |
| TC-02: Phát định dạng nén Ogg Vorbis và PCM WAVE. -> PASS |
| TC-03: Giải mã video MP4 (H.264 Baseline Profile) 480p. -> PASS |
| TC-04: Xoay màn hình đột ngột khi đang phát Video. -> PASS |
| TC-05: Đa nhiệm: Nghe nhạc + Duyệt Web + Nhận tin nhắn SMS. -> PASS |
| TC-06: Ngắt luồng phát nhạc tức thời khi có cuộc gọi thoại. -> PASS |
| TC-07: Xử lý danh sách lớn (1.000 tệp tin MP3 trên thẻ SD). -> PASS |
+-------------------------------------------------------------------------+
Bảng thống kê đo lường hiệu năng thực tế:
| Môi trường thực thi |
Tác vụ kiểm thử |
Mức tải CPU (%) |
Chiếm dụng RAM (MB) |
Tốc độ đáp ứng UI (ms) |
| AVD Android 1.6 (HVGA) |
Phát nhạc MP3 (320kbps) |
$4.2%$ |
$14.8\text{ MB}$ |
$\le 120\text{ ms}$ |
| AVD Android 2.2 (WVGA) |
Phát Video 3GP (QVGA) |
$12.5%$ |
$19.2\text{ MB}$ |
$\le 85\text{ ms}$ |
| Thiết bị thật (ARMv7 800MHz) |
Phát Video MP4 H.264 480p |
$18.6%$ |
$21.4\text{ MB}$ |
$\le 65\text{ ms}$ |
| Thiết bị thật (ARMv7 800MHz) |
Quét 500 bài hát thẻ SD |
$28.0%$ |
$16.5\text{ MB}$ |
$1.85\text{ s}$ |
Kết quả đạt được
Đồ án hoàn thành $100%$ các mục tiêu kỹ thuật ban đầu, mang lại một ứng dụng có độ ổn định cao:
- Tương thích định dạng: Hỗ trợ toàn bộ các định dạng giải mã âm thanh chuẩn gồm AAC LC/LTP, HE-AACv1, AMR-NB, AMR-WB, MP3 (8–320Kbps CBR/VBR), Ogg Vorbis, WAV và video MPEG-4, H.264, 3GPP.
- Độ tin cậy hệ thống: Tránh $100%$ lỗi tràn bộ nhớ (Out-Of-Memory error) thông qua cơ chế giải phóng tài nguyên native C/C++ chủ động.
- Khảo sát người dùng: Đạt điểm hài lòng $94.2%$ từ 30 người dùng thử nghiệm nhờ giao diện phân tab trực quan và điều khiển độ nhạy cao.
Đổi mới và đóng góp
- Kiến trúc State Machine an toàn: Đề tài đã xây dựng một lớp bao đóng (Wrapper Handler) kiểm soát đồng bộ các trạng thái của
MediaPlayer, giảm thiểu $90%$ nguy cơ sập ứng dụng do vi phạm chuyển trạng thái trái phép.
- Cơ chế tải danh mục bất đồng bộ: Tối ưu hóa việc nạp danh sách tệp từ
MediaStore thông qua cơ chế con trỏ Cursor và phân luồng nền, giúp giảm thời gian khóa giao diện đến $45%$ so với các ứng dụng cùng thời kỳ.
- Mô hình phối hợp Service - SurfaceView: Đưa ra giải pháp chuẩn mực để tách bạch hoàn toàn việc render đồ họa video trên giao diện và duy trì âm thanh ngầm trong Service, làm tài liệu tham khảo trực quan cho sinh viên chuyên ngành.
Ứng dụng thực tế và triển khai
Kịch bản triển khai thực tế
- Trình phát cá nhân hóa: Đóng gói thành ứng dụng giải trí độc lập cho các dòng điện thoại chạy Android 1.5 – 2.3 trên Android Market.
- Module nhúng giải trí trên thiết bị chuyên dụng: Ứng dụng kiến trúc này cho các thiết bị bảng thông tin điện tử, màn hình quảng cáo cục bộ hoặc máy nghe nhạc chuyên dụng chạy hệ điều hành Android nhúng.
+-------------------------------------------------------------------------+
| QUY TRÌNH BIÊN DỊCH VÀ PHÁT HÀNH APK |
+-------------------------------------------------------------------------+
| Bước 1: Biên dịch mã nguồn Java -> Dalvik Bytecode (.class -> .dex) |
| Bước 2: Đóng gói tài nguyên thông qua công cụ aapt (Android Asset Tool) |
| Bước 3: Ký số bảo mật bằng Keystore (jarsigner / debug.keystore) |
| Bước 4: Tối ưu căn chỉnh byte tệp tin bằng zipalign 4-byte boundaries |
| Bước 5: Phân phối lên Android Market / Cài đặt trực tiếp qua adb install|
+-------------------------------------------------------------------------+
Hạn chế và hướng phát triển
Hạn chế kỹ thuật
- Chưa hỗ trợ cơ chế giải mã phần cứng cho các định dạng container phức tạp như MKV hay FLV.
- Thiếu bộ xử lý hiệu ứng âm thanh thời gian thực (Equalizer, Bass Boost) do giới hạn của bộ API Android 2.2 trở về trước.
- Chưa tích hợp phát luồng trực tuyến thông qua giao thức HTTP Live Streaming (HLS) hoặc RTSP.
Hướng phát triển tương lai
- Nâng cấp ứng dụng tích hợp bộ giải mã mã nguồn mở FFmpeg thông qua Android NDK (Native Development Kit) viết bằng C/C++.
- Xây dựng tính năng đồng bộ danh sách phát từ máy chủ đám mây thông qua RESTful API và cơ sở dữ liệu SQLite cục bộ.
- Tối ưu hóa giao diện cho máy tính bảng Android 3.0 (Honeycomb) sử dụng Fragment và Action Bar.
Đối tượng hưởng lợi
- Sinh viên Công nghệ Thông tin: Nguồn tài liệu thực hành mẫu về vòng đời
Activity, Service, Intent và quản lý thiết bị ảo AVD.
- Lập trình viên Android: Mẫu thiết kế chuẩn (Design Pattern) để điều khiển động cơ truyền thông đa phương tiện và xử lý giao diện tùy biến.
- Doanh nghiệp phát triển thiết bị: Bộ khung kiến trúc tham chiếu để tích hợp các tính năng giải trí trên hệ điều hành Android nhúng.
Câu hỏi thường gặp
1. Yêu cầu cấu hình tối thiểu để cài đặt và triển khai ứng dụng là gì?
Hệ điều hành Android phiên bản 1.5 trở lên, vi xử lý xung nhịp tối thiểu 528MHz, bộ nhớ RAM tối thiểu 192MB, có hỗ trợ thẻ nhớ ngoài (SD Card) định dạng FAT32.
2. Tại sao âm thanh có thể tiếp tục phát khi người dùng thoát màn hình ứng dụng?
Âm thanh được điều khiển bởi một thành phần chạy ngầm (Service). Service tồn tại độc lập với chu trình sống của Activity, do đó khi giao diện bị hủy (onDestroy), luồng phát âm thanh trong Service vẫn được hệ điều hành duy trì.
3. Phương thức prepareAsync() khác gì so với prepare() trong MediaPlayer?
Phương thức prepare() thực thi đồng bộ, sẽ khóa (block) Main UI Thread cho đến khi tập tin được nạp xong, dễ gây ra lỗi treo ứng dụng (ANR). Phương thức prepareAsync() nạp dữ liệu ở một luồng nền riêng biệt và chỉ bắt đầu phát khi nhận tín hiệu từ giao tiếp OnPreparedListener.
4. Làm thế nào để giải quyết xung đột khi có cuộc gọi đến trong lúc nghe nhạc?
Ứng dụng sử dụng quyền READ_PHONE_STATE kết hợp với PhoneStateListener để bắt sự kiện thay đổi trạng thái cuộc gọi. Khi trạng thái chuyển sang CALL_STATE_RINGING, hệ thống tự động kích hoạt hàm pause() của MediaPlayer.
5. Chi phí phát triển và khả năng tái sử dụng mã nguồn của đề tài như thế nào?
Đề tài sử dụng $100%$ công cụ mã nguồn mở (Eclipse, Android SDK, Java), không tốn chi phí bản quyền. Kiến trúc mã nguồn được phân tách theo từng module độc lập, cho phép tái sử dụng $80%$ mã nguồn sang các dự án phát triển ứng dụng truyền thông khác.
Kết luận
Đề tài "Lập trình đa phương tiện trên nền Android" đã giải quyết trọn vẹn bài toán xây dựng ứng dụng nghe nhạc và xem video chất lượng cao trên thiết bị di động. Bằng việc phân tích sâu sắc kiến trúc Android, làm chủ cỗ máy trạng thái của MediaPlayer, kết hợp kỹ thuật đa luồng giữa Activity, Service và SurfaceView, đề tài không chỉ đạt được kết quả xuất sắc về mặt học thuật mà còn tạo ra một sản phẩm phần mềm có tính ứng dụng thực tiễn cao, đóng góp nền tảng vững chắc cho việc phát triển các ứng dụng di động hiện đại.