tài liệu về ứng dụng Java cho điện thoại di động
Trang 1CHƯƠNG 2 HƯỚNG TIẾP CẬN
Khi lập trình trên điện thoại di động, cần phải khai thác được các thế mạnh của điện thoại ngày nay là âm thanh và hình ảnh Trong phần này chúng em sẽ trình bày một số kỹ thuật xử lý âm thanh, một số kỹ thuật xử lý đồ họa và kỹ thuật xử lý phím cũng sẽ được trình bày chi tiết Tất cả các kỹ thuật này được thử nghiệm thành công trên các điện thoại của các hãng điện thoại lớn như Nokia, Samsung hay Sony Ericssion
2.1 Xử lý hình ảnh đồ hoạ
2.1.1 Tìm hiểu các đối tượng đồ họa
Ngày nay với sự phát triển nhanh chóng của công nghệ di động, chiếc điện thoại di động không còn đơn giản như trước đây là có nhiệm vụ thoại mà còn là phương tiện rất hữu hiệu trong công việc và giải trí Về hình ảnh, trước đây màn hình điện thoại di động chỉ là màn hình đen trắng nhưng ngày nay màn hình điện thoại là màn hình màu và ở một số loại điện thoại mới có đến vài trăm ngàn màu
Đó là những ưu điểm mà giúp điện thoại di động ngày càng thân thiết với người sử dụng hơn Với những ưu điểm đó, vậy thì làm sao để xây dựng các ứng dụng giải trí trên điện thoại di động hiệu quả Phần này sẽ trình bày những khía cạnh cơ bản giúp cho việc khai thác các điểm mạnh về đồ hoạ một cách hiệu quả hơn
Hầu hết các điện thoại di động ngày nay đều sử dụng công nghệ Java Thế mạnh của ngôn ngữ này là có thể chạy được trên các platform khác nhau Để xây dựng các ứng dụng giải trí mạnh về đồ hoạ, môi trường MIDP 1.0 cung cấp cho chúng ta hai mức đồ hoạ cơ bản là đồ họa mức thấp và đồ hoạ mức cao Đồ hoạ mức cao dùng cho văn bản hay form Đồ hoạ mức thấp dùng cho các ứng dụng trò chơi yêu cầu phải vẽ lên màn hình
Trang 2Hình sau biểu diễn hai mức độ đồ hoạ
Cả hai lớp đồ hoạ mức thấp và lớp đồ họa mức cao đều là con của lớp Displayable Trong MIDP chỉ có một lớp Displayable được hiển thị tại một thời điểm, có thể định nghĩa nhiều màn hình nhưng chỉ hiển thị một màn hình Public abstract class Canvas extends Displayable
Public abstract class Screen extends Displayable
- Đồ hoạ mức cao: là lớp con của lớp Screen Nó cung cấp các thành phần như Textbox, List, Form, Alert. Ta ít điều khiển việc sắp xếp các thành phần trên màn hình Việc sắp xếp phụ thuộc vào nhà sản xuất
Textbox: Cho phép người dùng nhập và soạn thảo văn bản Ta có thể định
nghĩa số ký tự tối đa, giới hạn loại dữ liệu nhập (số học, mật khẩu, email,…) và hiệu chỉnh nội dung textbox Kích thước thật sự của textbox có thể nhỏ hơn yêu cầu khi chạy trong thực tế (do giới hạn của thiết bị) Kích thước thật sự của textbox có thể lấy bằng phương thức getMaxSize()
List: Chứa danh sách các lựa chọn, người dùng có thể tương tác với danh sách
và chọn một hay nhiều item Có 3 loại danh sách là: IMPLICIT, EXCLUSIVE và MULTIPLE
Alert: hiển thị một màn hình pop-up trong một khoảng thời gian, nó được dùng
Trang 3hoặc được thiết lập là FOREVER cho đến khi người dùng nhấn phím bất kỳ để đóng lại
Form: Cho phép hiển thị nhiều item khác nhau trên một màn hình
- Đồ hoạ mức thấp: là lớp con của lớp Canvas Lớp này cung cấp các phương thức
đồ họa cho phép vẽ lên màn hình cùng với các phương thức xử lý sự kiện bàn phím Lớp này dùng cho các ứng dụng trò chơi cần điều khiển nhiều việc vẽ lên màn hình Khi có một ứng dụng đòi hỏi đồ họa mạnh chắc chắn ứng dụng đó phải sử dụng các lớp này Đây là những lớp đồ hoạ cấp thấp chạy được trên hầu hết các loại điện thoại di động hỗ trợ Java Một số thử nghiệm việc ứng dụng các hàm đồ họa cấp thấp của MIDP 1.0 đề xây dựng các ứng dụng yêu cầu khả năng đồ hoạ cao cho thấy tốc độ thực hiện nhanh hơn khi sử dụng MIDP 2.0
2.1.2 Kỹ thuật xử lý hoạt hình
Một trong những thành phần không kém phần quan trọng khi xây dựng các ứng dụng mạnh về đồ hoạ là tạo các hiệu ứng hoạt hình Để làm được điều đó, MIDP 1.0 cung cấp cho ta các đối tượng Timer, Thread, Runnable cho phép thực hiện các hiệu ứng theo chu kỳ thời gian định trước
2.1.2.1 Sử dụng đối tượng Timer đề tạo hoạt hình
Trong đồ án, các game sử dụng các lớp về đồ hoạ để biểu diễn các hình ảnh và
sử dụng Timer cho việc làm chuyển động các đối tượng cũng như tính thời gian Hoạt hình thực chất là sự luân phiên thay đổi các hình theo một khoảng thời gian xác định Tuỳ vào số lượng hình ảnh và khoảng thời gian mà hiệu ứng sẽ diễn ra đẹp hay không đẹp
Mô tả kỹ thuật xử lý hoạt hình sử dụng đối tượng Timer
Public class MainGame extends Canvas {
Trang 4tm.schedule(tt, 500,500); // Thiết lập thời gian hoạt hình
}
Protected void paint(Graphics g){
// Các thao tác vẽ hình ảnh
}
public class doAnimation extends TimerTask {
public final void run(){
// Cập nhật hình ảnh repaint(); // vẽ lại màn hình sau khi cập nhật
2.1.2.2 Sử dụng Thread đề tạo hoạt hình
Một hướng khác khi tạo hiệu ứng hoạt hình là ta có thể dùng thread đề định thời gian Thread được lớp java.lang.Thread cung cấp, nó có nhiều phương thức nhưng có phương thức quan trọng mà ta cần chú ý khi xây dựng ứng dụng là start() Start() – để khởi động thread
Kỹ thuật sử dụng thread được thực hiện như sau:
public class GameCanvas
{
private final int DELAY = 100;
private GameThread thread;
private boolean running;
public GameCanvas() {
} public void start()
Trang 5thread = new GameThread();
thread.start();
} public void stop() {
running = false;
} public class GameThread extends Thread {
public void run() {
while (running) {
// Cập nhật hình ảnh // Kiểm tra các điều kiện chuyển động // vẽ lại hình ảnh
try { Thread.sleep(DELAY);
} catch (Exception ex) { } }
} }
}
Cờ running cho biết thread có đang thực hiện hay không, thread sẽ dừng khi cờ này được gán bằng false khi gọi phương thức stop() DELAY cho biết thời gian lặp lại hành động của thread
2.1.2.3 Sử dụng giao diện Runnable đề tạo hoạt hình
Cách khác để tạo hoạt hình là sử dụng giao diện Runnable của lớp java.lang.Runnable Giao diện này được thiết kế để cung cấp những phương thức thông dụng cho những đối tượng hoạt hình và nó được kế thừa từ lớp Thread Giao diện Runnable có một phương thức duy nhất là run(). Khi một đối tuợng sử dụng giao diện Runnable đề tạo thread, phương thức run() được gọi để thực thi thread
Kỹ thuật sử dụng giao diện Runnable được cài đặt như sau:
public class GameCanvas implements Runnable
{
private final int DELAY = 100;
private Thread thread;
Trang 6} public void start() {
running = true;
thread = new Thread(this);
thread.start();
} public void stop() {
running = false;
} public void run() {
while (running)
{
// Cập nhật hình ảnh // Kiểm tra tương thích // vẽ lại hình ảnh
try {
Thread.sleep(DELAY);
} catch (Exception ex) { } }
} }
Do nó được kế thừa từ Thread nên cũng có cờ running cho biết giao diện có đang thực thi hay không, và nó sẽ ngừng khi cờ running được thiết lập là false khi phương thức stop() được gọi
Khi lập trình xử lý hoạt hình, chúng ta nên cân nhắc giữa việc sử dụng Thread
và sử dụng Timer Thread không thích hợp cho việc tạo các hiệu ứng hoạt hình theo từng frame (frame-rate), cách tốt nhất đối với hoạt hình dạng này là ta dùng đối tượng Timer vì đối tượng này không sử dụng trực tiếp đồng hồ hệ thống nên việc thực hiện hoạt hình sẽ hiệu quả hơn Timer dễ sử dụng hơn Thread nhưng do ban đầu Java chưa hỗ trợ lớp Timer nên có một số game sử dụng Thread đề thay thế
2.2 Xử lý thao tác bàn phím
Do chúng ta xây dựng ứng dụng dựa trên giao diện lập trình cấp thấp nên ta có thể dễ dàng kiểm soát thao tác phím dựa trên đối tượng Canvas Hầu hết các ứng dụng J2ME đều sử dụng Thread cho việc kiểm soát bàn phím Khi người dùng nhấn
Trang 7một phím trên điện thoại, một sự kiện được lập tức gửi cho ứng dụng, ứng dụng sẽ nhận sự kiện, phân tích phím nhấn và xử lý hành động tương ứng
Đối tượng Canvas cung cấp phương thức keyPressed (int keycode) để xử
lý phím nhấn, đây là cách xử lý sự kiện bấm phím
private int key;
public void keyPressed(int keyCode)
Trang 82.3 Đánh giá ưu khuyết điểm của việc sử dụng đối tượng
- Cho phép kiểm soát phím nhấn dễ dàng thông qua lớp Canvas
- Cho phép ứng dụng thực hiện với tốc độ nhanh vì thao tác trực tiếp trên màn hình thiết bị mà không qua đối tượng trung gian nào
2.4 Một số giải pháp khi xử lý đồ họa
- Cải tiến tốc độ vẽ hình ảnh trên màn hình thiết bị: Do việc nạp ảnh từ file
thường tốn nhiều thời gian nên ta không thể vừa thực hiện vẽ hình ảnh lên màn hình vừa đọc hình ảnh từ file, việc này sẽ làm hoạt hình bị giật Do đó chúng ta cần phải load hình vào bộ nhớ máy trước khi thực hiện thao tác vẽ như sau:
Load tất cả các hình ảnh cần thiết vào bộ nhớ máy trong phương thức constructor của đối tượng sử dụng hình ảnh một lần
Trong phương thức paint(), ta luân phiên vẽ các hình ảnh này theo khoảng thời gian xác định
Điều này sẽ giúp cho hoạt hình không bị giật, do hình ảnh đã được nạp vào trong bộ nhớ ngay từ đầu nhưng sẽ gây ra một khó khăn là tài nguyên hệ thống bị chiếm giữ
Trang 9- Vẽ những phần hình ảnh có thay đổi, không vẽ hết màn hình: Khi thực hiện
các thao tác hoạt hình ta nên vẽ những phần hình ảnh bị thay đổi không nên vẽ lại toàn bộ màn hình
- Thu dọn tài nguyên hệ thống sau khi dùng: Khi tạo ra các đối tượng đồ hoạ như
Image, hệ thống sẽ không tự động thu dọn tài nguyên mà các đối tượng này chiếm giữ cho đến khi kết thúc ứng dụng Điều này sẽ làm tốn tài nguyên của hệ thống J2ME cho phép chúng ta thu dọn tài nguyên hệ thống bằng tay bằng cách gọi System.gc(). Nhưng trước khi gọi phương thức này các đối tượng bạn muốn thu hồi tài nguyên phải được gán bằng null
Có một chú ý là ta nên giải phóng hết tài nguyên trước khi chuyển sang thực hiện thao tác kế tiếp
Trang 10Về mặt cú pháp thì không có gì sai, nhưng về mặt thực thi, do máy điện thoại
có tốc độ thấp nên trình Garbage Collector không thể thực hiện việc xoá bộ nhớ ngay lập tức, nó cần một khoảng thời gian nhất định Chính vì thế bạn nên dùng theo cách của method "freeMemory()"
2.5 Xử lý âm thanh trong ứng dụng
2.5.1 Vấn đề hỗ trợ âm thanh trên điện thoại di động
Một khó khăn rất lớn khi lập trình các ứng dụng trên điện thoại di động sử dụng MIDP 1.0 là phần xử lý âm thanh Do MIDP 1.0 không hỗ trợ việc xứ lý âm thanh nên các nhà sản xuất phải cung cấp thêm các hàm API chuyên dùng cho việc này Đây là một cố gắng của nhà sản xuất để cải tiến chất lượng các điện thoại tuy nhiên nó lại gây khó khăn cho các lập trình viên khi xây dựng các ứng dụng Do phải phụ thuộc vào các API của nhà sản xuất cung cấp nên tính chất “Viết một lần – Chạy trên nhiều nền“ không còn đúng nữa Điều này đã được SUN cố gắng khắc phục trong phiên bản MIDP 2.0, nhưng hiện nay chỉ có một số ít điện thoại hỗ trợ phiên bản này Trong phần này chúng em sẽ trình bày một số giải pháp khi xử lý âm thanh cho các ứng dụng trên điện thoại di động
Bảng mô tả một số API của một số nhà sản xuất điện thoại di động cung cấp cho việc xử lý âm thanh
2 Samsung com.samsung.util.AudioClip;
3 Sony Ericssion javax.microedition.media.*;
javax.microedition.media.control.*; (gói của SUN)
2.5.1.1 Đối với điện thoại Nokia:
Hiện nay Nokia có rất nhiều dòng sản phẩm nhưng ta có thể phân thành hai nhóm chính sau: nhóm thuộc Series 40 và nhóm thuộc series 60 Nhóm thuộc Series
40 gồm một số loại sau: 7210,6610, 7250, 6800, 3300,3200,3100,… sử dụng công
Trang 11nghệ MIDP 1.0 Nhóm thuộc Series 60 như: 6600,7610, 3650, 3660, nhóm này sử dụng công nghệ MIDP 2.0 Do hiện nay số dòng sản phẩm hỗ trợ MIDP 2.0 tương đối ít nên chúng em viết ứng dụng dựa trên MIDP 1.0 Do MIDP 1.0 không hỗ trợ
âm thanh nên để sử dụng được âm thanh, hãng Nokia cung cấp một số API chuyên dụng cho việc này Các API mà nhà sản xuất Nokia cung cấp chỉ hỗ trợ cho việc phát các âm thanh dạng TONE, dạng WAV TONE được lưu trữ theo dạng mảng các byte biểu diễn cho tần số Node nhạc như ví dụ sau:
byte[] dataIntro = {
// Thiết lập thông số cho Tone (byte)0x02, (byte)0x4a, (byte)0x3a, (byte)0x40,
(byte)0x04, (byte)0x00, (byte)0x19, (byte)0x2a,
(byte)0xa2, (byte)0x34, (byte)0x49, (byte)0xaa,
(byte)0x17, (byte)0xa1, (byte)0x6a, (byte)0x12,
(byte)0xa1, (byte)0x1a, (byte)0x20, (byte)0xd5,
(byte)0x0b, (byte)0x50, (byte)0x00
};
hoặc được lưu trữ trong file ott (ví dụ amnhac.ott) Dạng WAV do kích thước quá lớn không phù hợp với việc lập trình trên điện thoại di động nên chúng em không trình bày trong phần này
Cách phát âm thanh dạng TONE:
private Sound introSnd=null;
introSnd=new Sound(dataIntro, Sound.FORMAT_TONE);
Trang 12Có một khó khăn khi sử dụng cách phát âm thanh dạng này là ta không thể phát song song nhiều hiệu ứng âm thanh cùng một lúc được Đây là một trong những nhược điểm của MIDP 1.0, nó gây khó khăn cho việc tạo các hiệu ứng âm thanh cho ứng dụng Hiện nay các loại Nokia sử dụng MIDP 1.0 không cung cấp các API phục vụ cho việc chơi các tập tin MIDI mặc dù là một số điện thoại Nokia
đã hỗ trợ chơi nhạc MIDI
Cách kiểm tra điện thoại có hỗ trợ chơi âm thanh không: dùng phương
thức className để tìm gói com.nokia.mid.soung.Sound, nếu tìm thấy tức là điện thoại có hỗ trợ chơi âm thanh
private static TonePlayer makeTonePlayer() {
TonePlayer player;
try {
Class.forName("com.nokia.mid.sound.Sound");
// Tạo lớp chơi âm thanh
Class class = Class.forName("example.tones.NokiaTonePlayer"); player = (TonePlayer)(clas.newInstance());
} catch (Exception e) {
System.out.print(“ Không hỗ trợ âm thanh.”);
} return player;
}
Lớp chơi âm thanh trên Nokia
Package example.tones;
import com.nokia.mid.sound.*; // import gói chơi âm thanh
class NokiaTonePlayer extends TonePlayer {
private final Sound sound; NokiaTonePlayer() {
sound = new Sound(0, 1L);
} void play(int frequency) {
sound.init(frequency, 2000L);
sound.play(1);
} void stop() {
sound.stop();
} }
Trang 13Vì không thể phát cùng lúc nhiều kênh âm thanh nên trong chỉ chọn một trong hai cách sau: một là sử dụng âm thanh cho các hiệu ứng, hai là sử dụng âm thanh làm nhạc nên mà không có âm thanh cho phần hiệu ứng
2.5.1.2 Đối với điện thoại SAMSUNG:
Các dòng sản phẩm của SAMSUNG sử dụng MIDP 1.0 và MIDP 2.0 điều được cung cấp lớp com.samsung.util.AudioClip để lập trình âm thanh Hiện nay điện thoại SAMSUNG chỉ hỗ trợ âm thanh dạng mmf (TYPE_MMF=1) Để tạo đối tượng AudioClip, ta dùng Constructor sau:
Public AudioClip(int type, String filename) throws java.io.IOException Trong đó type luôn luôn bằng 1 (kiểu định dạng mmf) và filename là tên tập tin mmf Tập tin mmf thật chất là tập tin MIDI đặc biệt được SAMSUNG sử dụng cho dòng sản phầm của họ
Để kiểm tra điện thoại có hỗ trợ âm thanh không, ta dùng phương thức tĩnh AudioClip.isSupported(). AudioClip còn hỗ trợ 4 phương thức điều khiển là play() để chơi nhạc, stop() dừng nhạc, pause() tạm dừng và resume() chơi tiếp đoạn nhạc đã tạm dừng trước đó SAMSUNG cũng tương tự như Nokia là ở mỗi thời điểm chỉ có một đối tượng AudioClip chơi nhạc và đó là đối tượng được gọi là play() sau cùng
Cách chơi nhạc được SAMSUNG xây dựng như sau:
import com.samsung.util.AudioClip;
private AudioClip audioClip=null;
public void playAudioClip(String filename){