Hiện nay, cộng đồng Java trên thếgiới mà đi đầu là hãng Sun Microsystems đã xây dựng nhiều nhánh mới choJava như: JavaMail thư điện tử, Java TAPI viễn thông, Java3D đồ họa 3chiều, J2ME ứ
Trang 1LỜI CẢM ƠN
Để hoàn thành được đồ án này, tôi đã nhận được sự chỉ bảo tận tình của các Thầy Cô giáo trong khoa Công nghệ Thông tin trường Đại học Bách Khoa, sự giúp đỡ động viên của gia đình và bạn bè.
Trước tiên tôi xin chân thành cảm ơn tất cả các thầy cô của trường Đại học Bách Khoa, Đại học Đà Nẵng đã dạy dỗ và truyền đạt kiến thức cho tôi trong thời gian học tại trường.
Tôi xin chân thành cám ơn thầy PGS TS Phan Huy Khánh Cám ơn thầy đã tận tình hướng dẫn góp ý cho tôi trong quá trình thực hiện đồ án này Nhờ đó mà tôi có thể hoàn thành theo đúng yêu cầu về nội dung của một đồ án tốt nghiệp.
Tôi cũng xin được cám ơn những người bạn cùng ngành đã động viên giúp đỡ tôi trong suốt thời gian làm đồ án.
Cuối cùng, con xin cảm ơn gia đình đã tạo mọi điều kiện tốt nhất để bản thân có thể hoàn thành được đồ án đúng hạn.
Mặc dù đã cố gắng hết sức, nhưng vì khả năng và thời gian có hạn, đề tài nghiên cứu chắc chắn còn nhiều khiếm khuyết Rất mong các Thầy Cô giáo chỉ bảo giúp đỡ Rất mong sự góp ý của bạn bè, đồng nghiệp.
Sinh viên
Lê Thị Mỹ Nhung
Trang 2LỜI CAM ĐOAN
Tôi xin cam đoan:
1 Những nội dung trong báo cáo này là do tôi thực hiện dưới sự hướng dẫn trực tiếp của thầy PGS TS Phan Huy Khánh
2 Mọi tham khảo dùng trong báo cáo này đều được trích dẫn rõ ràng tên tác giả, tên công trình, thời gian, địa điểm công bố.
3 Mọi sao chép không hợp lệ, vi phạm quy chế đào tạo, hay gian trá,tôi xin chịu hoàn toàn trách nhiệm.
Sinh viên
Lê Thị Mỹ Nhung
Trang 3NHẬN XÉT CỦA CÁN BỘ HƯỚNG DẪN
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
Đà Nẵng, Ngày….tháng….năm 2011
Cán bộ hướng dẫn PGS TS Phan Huy Khánh
Trang 4NHẬN XÉT CỦA CÁN BỘ PHẢN BIỆN
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
………
Đà Nẵng, Ngày….tháng….năm 2011
Cán bộ phản biện
Trang 5MỤC LỤC
TỔNG QUAN VỀ ĐỀ TÀI 1
I Đặt vấn đề 1
II Mục đích của đề tài 1
III Nhiệm vụ 2
IV Phạm vi 2
CHƯƠNG 1: CƠ SỞ LÝ THUYẾT 3
I Giới thiệu ngôn ngữ JAVA 3
II Công nghệ J2ME 4
II.1 Giới thiệu về J2ME và lập trình trên thiết bị động 4
II.2 Kiến trúc của J2ME 5
II.2.1 Giới thiệu các thành phần trong nền tảng J2ME: 6
II.2.2 Định nghĩa về Profile: 8
II.3 Phát triển ứng dụng 9
II.3.1 Biên dịch, kiểm tra lỗi và chạy thử 9
II.3.2 Đóng gói và triển khai ứng dụng thành tập tin jar 9
II.3.3 Tập tin manifest.mf và tập tin JAD 10
II.3.4 Tối ưu mã chương trình và giảm kích thước ứng dụng 10
II.4 Lập trình với J2ME 11
II.4.1 MIDlet và đối tượng Display 11
II.4.2 Giao diện người dùng cấp thấp 13
II.4.3 Record Management System - RMS 21
II.4.4 Sound, Music and Video: 27
CHƯƠNG 2: BÀI TOÁN VÀ HƯỚNG GIẢI QUYẾT 30
I Bài toán 30
II Mô tả bài toán 30
III Giải quyết bài toán 31
III.1 Cấu trúc chương trình 31
III.2 Xây dựng các thuật toán giải quyết bài toán 32
CHƯƠNG 3: CÀI ĐẶT VÀ DEMO CHƯƠNG TRÌNH 37
I Cài đặt hệ thống 37
I.1 Môi trường phát triển và công cụ lập trình 37
I.2 Hướng dẫn cài đặt hệ thống 37
II Cài đặt thuật toán 37
II.1 Khởi tạo ma trận trạng thái của khối gạch 38
II.2 Tạo khối tiếp theo 43
II.3 Kiểm tra qua trái, phải, đi xuống 43
II.4 Quay khối gạch 45
III Kết quả 47
KẾT LUẬN 53
I Kết luận 53
II Hướng phát triển đề tài 53
Trang 6MỤC LỤC HÌNH
Hình 1: Các tầng của J2ME trên CLDC 4
Hình 2: Kiến trúc tổng quát của nền tảng Java 5
Hình 3: Thành phần trong nền tảng J2ME 7
Hình 4: Profile 9
Hình 5: Vòng đời của một MIDlet 12
Hình 6: Vẽ cung 17
Hình 7: Điểm neo(1) 18
Hình 8: Điểm neo(2) 19
Hình 9: Điểm neo(3) 19
Hình 10: Vẽ ảnh 20
Hình 11: MIDlet suite 23
Hình 12: Sơ đồ âm thanh 27
Hình 13: Mô hình chuyển đổi trạng thái của Player 29
Hình 14: Logo 47
Hình 15: Loading 47
Hình 16: Ask for sound 48
Hình 17: Splash 48
Hình 18: MainMenu 49
Hình 19: In game (1) 49
Hình 20: In game (2) 50
Hình 21: Game over 50
Hình 22: About 51
Hình 23: Help 51
Hình 24: Promotion (1) 52
Hình 25: Promotion (2) 52
Trang 7TỔNG QUAN VỀ ĐỀ TÀI
.I Đặt vấn đề
Công nghệ thông tin ngày nay có vai trò rất quan trọng trong cuộc sống hàngngày của chúng ta Hiện nay có rất nhiều công nghệ mới phát triển song song vớiviệc phát triển công nghệ thông tin như Bluetooth, Wireless, WAP, SOAP,
… nhằm giúp công nghệ thông tin ngày càng thân thiết với người dùng hơn Mộttrong những công nghệ góp phần không nhỏ trong việc kết nối con người vớithông tin cũng như con người với con người là công nghệ di động Với tốc
độ phát triển hiện nay và những lợi ích to lớn của công nghệ di động, có thểthấy nó có ảnh hưởng rất lớn đến cuộc sống của con người Không giống nhưtrước đây những chiếc điện thoại chỉ có chức năng rất đơn giản là đàm thoại,điện thoại hiện nay còn có thêm rất nhiều chức năng, ứng dụng khác như: email,truy cập Internet, video, nghe nhạc, chơi game, … đồng thời với nó là sự phát triển
vũ bão của các dịch vụ gia tăng trên điện thoại di động dựa trên công nghệ WAP
và SOAP
Vì vậy tôi chọn đề tài là “Ứng dụng công nghệ J2ME, xây dựng phần mềm
trò chơi xếp gạch trên điện thoại di động” nhằm khai thác các tính năng của điện
thoại di động Qua đó tôi sẽ cố gắng nắm bắt và ứng dụng được tốt các kỹ thuậtlập trình trên điện thoại di động mà chủ yếu là lập trình game
.II Mục đích của đề tài
Khi thực hiện đề tài này, mục tiêu mà tôi mong muốn đạt được là:
Xây dựng game Zentris nhằm hiểu rõ và sâu hơn về J2ME
Nắm được cách xây dựng một game trên điện thoại di động
Cách xử lý âm thanh, hình ảnh, phím, cảm ứng … trong lập trình game
Trang 8.III Nhiệm vụ
Tìm hiểu về các công cụ hỗ trợ lập trình với J2ME
Tìm hiểu về JAVA và J2ME
Xây dựng phần mềm trò chơi xếp gạch trên điện thoại di động
.IV Phạm vi
Trong phạm vi đề tài này tôi đã nghiên cứu về J2ME, mô hình phát triển game,các kỹ thuật xử lý âm thanh, phím, hiệu ứng … Tuy nhiên tôi chưa đi sâu vào tìmhiểu kỹ về chúng Ví dụ như chưa xử lý được nhiều hiệu ứng phức tạp, chưa tìmhiểu vê cách xử lý phím và các kỹ thuật khác trong J2ME
Lê Thị Mỹ Nhung, Lớp 06T4 4
Trang 9CHƯƠNG 1
CƠ SỞ LÝ THUYẾT
.I Giới thiệu ngôn ngữ JAVA
Java là một công nghệ được hãng Sun Microsystems xây dựng từ cuốinăm1990 với cái tên Oak và hiện nay đang phát triển vượt bậc với sự đóng gópcủa hàng vạn lập trình viên trên thế giới Ban đầu, Oak được kỹ sư JamesGosling và các cộng sự xây dựng với mục đích lập trình cho các mặt hàng điện dândụng với mục tiêu nhỏ gọn và tương thích được với nhiều loại thiết bị phần cứngkhác nhau Sau đó Oak được sử dụng trong nhiều dự án như dự án Xanh (BlueProject), dự án Phim theo yêu cầu (Video on demand Project) Sau một chuyến dulịch tới đảo Java của Indonesia, nhóm phát triển Oak đã đổi tên Oak thành Java.Java mà tiền thân là Oak được xây dựng chủ yếu dựa trên bộ công cụ pháttriển (Java Development Kit - JDK) như là bộ thư viện chuẩn trong đó chưatrình biên dịch, trình thông dịch, trình đóng gói, tài liệu,… Đây chính là nềntằng cho việc phát triển các ứng dụng Java Hiện nay, cộng đồng Java trên thếgiới mà đi đầu là hãng Sun Microsystems đã xây dựng nhiều nhánh mới choJava như: JavaMail (thư điện tử), Java TAPI (viễn thông), Java3D (đồ họa 3chiều), J2ME (ứng dụng cho thiết bị di động),…
Hiện nay Java có các phiên bản sau:
- J2SETM (Java 2 Platform, Standart Edition): Phiên bản chuẩn gồm bộ công cụthông dụng dùng để chạy trên các máy PC hoặc các mạng máy tính nhỏ
- J2EETM (Java 2 Platform, Enterprise Edition): Phiên bản dành cho các máy chủvới bộ nhớ lớn Bao gồm các kiến trúc nâng cao như Web, EJB, Transaction,…dùng để xây dựng các ứng dụng có quy mô lớn
- J2METM
(Java 2 Platform, Micro Edition): Bao gồm môi trường và thư việnJava dùng để phát triển các ứng dụng trên các thiết bị có bộ nhớ nhỏ nhưđiện thoại di động, PDA, các đồ gia dụng,…
Lê Thị Mỹ Nhung, Lớp 06T4 5
Trang 10.II Công nghệ J2ME
.II.1 Giới thiệu về J2ME và lập trình trên thiết bị động
J2ME được phát triển từ kiến trúc JavaCard, EmbededJava và PersonalJava củaphiên bản Java 1.1 Đến dự ra đời của phiên bản Java 2 thì Sun quyết định thaythế PersonalJava bằng một phiên bản mới có tên Java 2 Micro Edition, viết tắt làJ2ME J2ME được sử dụng cho các thiết bị nhỏ gọn với dung lượng bộ nhớ bé
và khả năng xử lý thấp
Mục tiêu của Java là cho phép người lập trình viết các ứng dụng độc lập vớithiết bị di động, không cần quan tâm đến phần cứng thật sự Để làm được nhưthế, J2ME được xây dựng bằng các tầng khác nhau để che giấu đi việc tương táctrực tiếp với phần cứng của thiết bị Các tầng của J2ME được xây dựng trênCLDC (Connected Limited Device Configuration):
Hình 1: Các tầng của J2ME trên CLDC
Tầng dưới cùng là tầng Phần cứng thiết bị - đây là tầng vật lý bao gồm phầncứng của thiết bị di động Các tầng bên trên tầng Phần cứng thiết bị là các tầngtrừu tượng, chúng cung câp cho lập trình viên nhiều giao diện lập trình thân thiện
và dễ dàng hơn mà không cần quan tâm đến phần cứng Nói các khác chúng đóngvai trò trung gian giúp cho lập trình viên tương tác được với phần cứng mà khôngcần quan tâm đến các chi tiết thực sự của phần cứng của thiết bị
Tầng Phần cứng thiết bị (Device Hardware Layer): đây là thiết bị di độngthật sự với bộ nhớ và tốc độ xử lý cụ thể Các thiết bị di động khác nhau có thể
Lê Thị Mỹ Nhung, Lớp 06T4 6
Trang 11có bộ vi xử lý và các tập lệnh rất khác nhau Mục tiêu của J2ME là cung cấp cholập trình viên khả năng giao tiếp giống nhau với tất cả các loại thiết bị di độngkhác nhau.
Tầng máy ảo Java (Java Virtual Machine Layer): đây là tầng đóng vai tròthông ngôn giữa chương trình và thiết bị Nó sẽ thông dịch các mã bytecode (mã
có được sau khi biên dịch mã nguồn chương trình) thành mã máy của các thiết bị
di động Tầng này bao gồm KVM (K Virtual Machine) là bộ biên dịch mãbytecode thành mã máy Nó cung cấp một sự chuẩn hóa cho các thiết bị di động
để ứng dụng J2ME sau khi biên dịch có thể chạy được trên bất kỳ thiết bị di độngnào hỗ trợ KVM
Tầng cấu hình (Configuration Layer): Tầng này cung cấp các hàm API cơ bản
là nhân của J2ME Lập trình viên có thể sử dụng các lớp và các phương thức củacác API này tuy nhiên nó không thực sự phong phú bằng tập API của tầng hiệntrạng
Tầng hiện trạng (Profile Layer): Tầng này cung cấp các hàm API hữu dụnghơn cho việc lập trình Mục đích của tầng này xây dựng nên lớp cấu hình và cungcấp nhiều thư viện ứng dụng hơn
.II.2 Kiến trúc của J2ME
Phần này sẽ trình bày kiến trúc tổng quát của nền tảng Java :
Hình 2: Kiến trúc tổng quát của nền tảng Java
Trang 12.II.2.1Giới thiệu các thành phần trong nền tảng J2ME:
Định nghĩa về Configuration (Cấu hình): là đặc tảđịnh nghĩa một môi trườngphần mềm cho một dòng các thiết bịđược phân loại bởi tập hợp các đặc tính, ví dụnhư:
CLDC (Connected Limited Device Configuration (Cấu hình thiết bị kết
nối giới hạn): được thiết kếđể nhắm vào thị trường các thiết bị cấp thấp(low-end), các thiết bị này thông thường là máy điện thọai di động và PDAvới khoảng 512 KB bộ nhớ Vì tài nguyên bộ nhớ hạn chế nên CLDCđược gắn với Java không dây (Java Wireless ), dạng như cho phép người
sử dụng mua và tải về các ứng dụng Java, ví dụ như là Midlet
CDC- Connected Device Configuration (Cấu hình thiết bị kết nối): CDC
được đưa ra nhắm đến các thiết bị có tính năng mạnh hơn dòng thiết bịthuộc CLDC nhưng vẫn yếu hơn các hệ thống máy để bàn sử dụng J2SE.Những thiết bị này có nhiều bộ nhớ hơn (thông thường là trên 2Mb) và
có bộ xử lý mạnh hơn Các sản phẩm này có thể kểđến như các máy PDAcấp cao, điện thoại web, các thiết bị gia dụng trong gia đình …
Cả 2 dạng Cấu hình kể trên đều chứa máy ảo Java (Java Virtual Machine)
và tập hợp các lớp (class) Java cơ bản để cung cấp một môi trường cho các ứngdụng J2ME Tuy nhiên, bạn chú ý rằng đối với các thiết bị cấp thấp, do hạn chế
về tài nguyên như bộ nhớ và bộ xử lý nên không thể yêu cầu máy ảo hổ trợ tất cả
Trang 13các tính năng như với máy ảo của J2SE, ví dụ, các thiết bị thuộc CLDC không
có phần cứng yêu cầu các phép tính toán dấu phẩy động, nên máy ảo thuộcCLDC không được yêu cầu hỗ trợ kiểu float và double
Trang 14.II.2.2 Định nghĩa về Profile:
Profile mở rộng Configuration bằng cách thêm vào các class để bổ trợ cáctính năng cho từng thiết bị chuyên biệt Cả 2 Configuration đều có những profileliên quan và từ những profile này có thể dùng các class lẫn nhau Đến đây ta có thểnhận thấy do mỗi profile định nghĩa một tập hợp các class khác nhau, nên thường
ta không thể chuyển một ứng dụng Java viết cho một profile này và chạy trên mộtmáy hỗ trợ một profile khác Cũng với lý do đó, bạn không thể lấy một ứng dụngviết trên J2SE hay J2EE và chạy trên các máy hỗtrợ J2ME Sau đây là các profiletiêu biểu:
Mobile Information Device Profile (MIDP): profile này sẽ bổ sung các
tính năng như hỗtrợ kết nối, các thành phần hỗ trợ giao diện người dùng
… vào CLDC Profile này được thiết kế chủ yếu để nhắm vào điện thọai
di động với đặc tính là màn hình hiển thị hạn chế, dung lượng chứa cóhạn Do đó MIDP sẽ cung cấp một giao diện người dùng đơn giản và cáctính năng mạng đơn giản dựa trên HTTP Có thể nói MIDP là profile nổitiếng nhất bởi vì nó là kiến thức cơ bản cho lập trình Java trên các máy diđộng (Wireless Java)
PDA Profile: tương tự MIDP, nhưng với thị trường là các máy PDA với
màn hình và bộ nhớ lớn hơn
Foundation Profile: cho phép mở rộng các tính năng của CDC với phần
lớn các thư viện của bộ Core Java2 1.3 Ngoài ra còn có Personal BasisProfile, Personal Profile, RMI Profile, Game Profile
Trang 15Hình 4: Profile.
.II.3 Phát triển ứng dụng
.II.3.1 Biên dịch, kiểm tra lỗi và chạy thử
Mã nguồn chương trình có thể được biên dịch bằng các trình biên dịchchuẩn cảu Java, chúng tạo ra các file class Ta có thể biên dịch từ các trình soạnthảo hoặc biên dịch trực tiếp từ dòng lệnh
Chúng ta sử dụng các công cụ như WTK để kiểm tra lỗi và chạy thửchương trình vì việc này nếu tiến hành trên thiết bị thật rất mất thời gian Việc sửdụng các giả lập giúp nhanh chóng phát hiện các lỗi Ngoài ra nó còn giúp lậptrình viên có những cái nhìn cảm quan về chương trình của mình
.II.3.2 Đóng gói và triển khai ứng dụng thành tập tin jar
Các lớp đã được biên dịch của ứng dụng J2ME được đóng gói trong tập tinJAR cùng với các tài nguyên khác như hành ảnh, âm thanh,… Tập tin JAR nàychính là tập tin được cài vào thiết bị di động
Người sử dụng có thể tải tập tin JAR vào máy di động bằng các cách sau:Kết nối điện thoại di động với máy tính bằng cáp truyền dữ liệu: Việc này
Trang 16yêu cầu người dùng phải có tập tin JAR thật sự và phần mềm truyền thông để tảiứng dụng vào điện thoại thông qua cáp dữ liệu
Cổng hồng ngoại: Yêu cầu thiết bị di động và nguồn chưa file JAR phải hỗtrợ hồng ngoại và người dùng có file JAR thật sự
Sử dụng mạng không dây: tải ứng dụng thông qua mạng GPRS, người dùngchỉ cần biết địa chỉ URL của tập tin JAR
.II.3.3 Tập tin manifest.mf và tập tin JAD
Tập tin manifest.mf và tập tin JAD mô tả các đặc điểm của ứng dụng Tậptin manifest.mf nằm bên trong tập tin JAR còn tập tin JAD nằm ngoài tập tin JAR.Tập tin JAD giúp cho người dùng có thể biết được đặc điểm của ứng dụng trướckhi tải Việc này giúp làm giảm lãng phí tài nguyên và tiền bạc vì trên thực tế,một ứng dụng J2ME nào đó chỉ có thể chạy trên một số máy nhất định
Tập tin manifest.mf có nội dung như sau:
- Manifest-Version: //Phiên bản tập tin manifest.mf
- MIDlet-Name: //Tên bộ MIDlet
- MIDlet-Version: //Phiên bản của bộ MIDlet
- MIDlet-Vendor: //Nhà sản xuất
- MIDlet-<n>: //Tên của MIDlet chính
- MicroEdition-Profile: //Phiên bản hiện trạng
- MicroEdition-Configuration: //Phiên bản cấu hình
.II.3.4 Tối ưu mã chương trình và giảm kích thước ứng dụng
Sau khi đóng gói chương trình thành tập tin JAR chúng ta thấy rằng các file
dữ liệu đã được nén lại một cách đáng kể Tuy nhiên ta có thể giảm kích thước fileJAR này thêm một lần nữa bằng cách dùng một công cụ Công cụ này thườngbao gồm các đặc tính sau:
Loại bỏ các class không dùng đến
Loại bỏ các hàm và biến không dùng đến
Đổi tên class, package, hàm và biến thành các tên đơn giản và ngắn
Trang 17gọn hơn.
Thêm vào file class một số mã để chương trình khó bị dịch ngược hơn
Ba đặc tính đầu dùng để giảm kích thước các file class trong khi đóđặc tính thứ 3 và thứ 4 dùng để bảo vệ chương trình khó bị dịchngược lại thành mã nguồn Ngay cả khi bị dịch ngược lại thành mãnguồn thì chương trình cũng khó bị đọc hơn vì các tên lớp, biến ,hàm, package đã bị thay đổi Các công cụ thường được dùng để tối
ưu mã chương trình là Jbuilder 9X, Retroguard, Jshrink
.II.4 Lập trình với J2ME
Chắc hẳn chúng ta đã biết nhiều về J2ME nhưng theo tôi được biết trong lậptrình game, tất cả mọi thứ đều được xử lý trên lớp canvas, Graphics kết hợp với các
kỹ xử lý âm thanh, cách lưu trữ bảng ghi(highScore), phím và cảm ứng (Touch) Tất cả những tài liệu về J2ME có rất nhiều và bạn có thể đọc trong file index(filedoc) của J2ME Sau đây tôi xin gới thiệu đôi nét cơ bản về J2ME, cụ thể là tôi giớithiệu về những thứ mà tôi được học trong khi lập trình game trên điện thoại diđộng
.II.4.1 MIDlet và đối tượng Display
.II.4.1.1 MIDlet – Vòng đời của một MIDlet (Mobile Information Device applet)
Một MIDlet kế thừa từ lớp javax.microedition.midlet.MIDlet và thực thi ít nhấtcác phương thức cơ bản sau: startApp(), pauseApp(), và destroyApp()
Trong một ứng dụng của bạn gồm có nhiều lớp thì có thể chỉ cần một lớp kếthừa MIDlet
- startApp():
Trang 18Phương thức startApp() được gọi khi MIDlet được khởi tạo, và mỗi khi MIDlettrở về từ trạng thái tạm dừng (pause) Các biến toàn cục sẽ được khởi tạo lại trừhàm tạo bởi vì các biến đã được giải phóng trong hàm pauseApp() Nếu không thìchúng sẽ không được khởi tạo lại bởi ứng dụng.
- pauseApp():
Phương thức pauseApp() được gọi mỗi khi ứng dụng cần được tạm dừng (ví
dụ, trong trường hợp có cuộc gọi hoặc tin nhắn đến) Cách thích hợp để sử dụngpauseApp() là giải phóng tài nguyên và các biến để dành cho các chức năng kháctrong điện thoại trong khi MIDlet được tạm dừng Cần chú ý rằng khi nhận cuộcgọi đến, hệ điều hành trên điện thoại di động có thể dừng KVM thay vì dừngMIDlet Việc này do nhà sản xuất thiết bị quyết định sẽ chọn cách nào
- destroyApp(boolean un):
Phương thức destroyApp() được gọi khi thoát MIDlet (ví dụ khi nhấn nút exittrong ứng dụng) Nó chỉ đơn thuần là thoát MIDlet Phương thức destroyApp() chỉnhận một tham số Boolean Nếu tham số này là true, MIDlet được tắt vô điều kiện.Nếu tham số là false, MIDlet có thêm tùy chọn từ chối thoát bằng cách ném ra mộtngoại lệ MIDletStateChangeException
Dưới đây là vòng đời của một MIDlet:
Hình 5: Vòng đời của một MIDlet
- resumeRequest(),
- notifyPaused(),
Trang 19- notifyDestroyed()
.II.4.1.2 Đối tượng Display
Mỗi MIDlet có một tham chiếu đến một đối tượng Display Đối tượng này cungcấp các thông tin về màn hình cũng như một số phương thức cần cho việc hiển thịcác đối tượng khác trên màn hình Có thể xem Display là đối tượng có nhiệm vụquản lý việc hiển thị của màn hình Chức năng của nó là quyết định danh sách cácthành phần cần xuất hiện trên màn hình cũng như thời điểm phù hợp để hiển thịchúng
.II.4.1.3 Đối tượng Displayable
Mặc dù mỗi MIDlet chỉ có duy nhất một đối tượng Display nhưng nó lại có thể
có rất nhiều đối tượng Displayable Điều đó có nghĩa là một đối tượng Display cóthể hiển thị bao nhiêu đối tượng Displayable tùy ý Đối tượng Displayable là đốitượng có thể nhìn thấy được một cách trực quan trên màn hình Bản thân MIDP cóchứa 2 lớp con của Displayable là Screen và Canvas:
public abstract class Displayable
public abstract class Canvas extends Displayable
public abstract class Screen extends Displayable
.II.4.2 Giao diện người dùng cấp thấp
.II.4.2.1 Các hàm API ở mức thấp
Mặc dù các hàm API cấp cao cung cấp một tập đầy đủ các thành phần để xâydựng giao diện ứng dụng người dùng Tuy nhiên các thành phần cấp cao khôngcung cấp phương tiện để vẽ trực tiếp lên thiết bị thể hiện Vì thiếu khả năng này nêncác ứng dụng được tạo ra sẽ gặp nhiều giới hạn Ví dụ hầu hết các nhà phát triểngame di động dựa trên khả năng vẽ các đường thẳng và các hình dạng như là mộtphần tích hợp quá trình phát triển Nếu các hàm API cấp cao cho phép chúng ta tạo
ra giao diện cho các ứng dụng theo chuẩn, thì các hàm API cấp thấp cho phépchúng ta có thể thể hiện các ý tưởng của mình
Canvas và Graphics là 2 lớp trái tim của các hàm API cấp thấp Chúng ta sẽlàm tất cả các công việc bằng tay Canvas là một khung vẽ cho phép người phát
Trang 20triển có khả năng vẽ lên thiết bị trình bày cũng như là việc xử lý sự kiện Còn lớpGraphics cung cấp các công cụ thật sự để vẽ như drawRoundRect() vàdrawString().
.II.4.2.2 Lớp Canvas và kỹ thuật xử lý đồ họa
Lớp Canvas cung cấp một khung vẽ cho phép tạo ra giao diện tùy biến ngườidùng Một số lượng lớn các phương thức trong lớp này được dùng để xử lý sự kiện,
vẽ ảnh và chuỗi lên thiết bị hiển thị
.II.4.2.2.1 Tạo một đối tượng Canvas
Bước đầu tiên để làm việc với một lớp Canvas là tạo ra một lớp thừa kế từ lớpCanvas
class TestCanvas extends Canvas implements CommandListener {
private Command cmdExit; display = Display.getDisplay(this);
cmdExit = new Command("Exit", Command.EXIT, 1);
addCommand(cmdExit);
setCommandListener(this);
protected void paint(Graphics g) {
// Draw onto the canvas
…}
KEY_NUM0
KEY_NUM1
KEY_NUM2
KEY_NUM3
Trang 21void keyPressed(int keyCode)
void keyReleased(int keyCode)
void keyRepeated(int keyCode)
boolean hasRepeatEvents()
String getKeyName(int keyCode)
.II.4.2.2.3 Sự kiện con trỏ
Trong phần này chúng ta sẽ quản lý sự kiện con trỏ trong một Canvas Nhữngsựkiện này được thiết kếđể làm thuận tiện cho việc tương tác với các thiết bị códạng con trỏ Một số phương thức được cung cấp nhằm hỗ trợ cho việc xử lý sựkiện con trỏ:
boolean hasPointerEvents()
boolean hasPointerMotionEvents()
void pointerPressed(int x, int y)
void pointerReleased(int x, int y)
void pointerDragged(int x, int y)
Các phương thức trên có thể tự giải thích chức năng thông qua tên của chínhmình Ví dụ như phương thức hasPointerMotionEvents() trả về một giá trị cókiểu boolean nhằm chỉ rõ rằng thiết bị di động có hỗ trợ khái niệm “nhấp chuột vàrê” hay không
Trang 22.II.4.2.3Lớp Graphics
Chúng ta sử dụng đối tượng Graphics để vẽ lên một Canvas
.II.4.2.3.1 Hỗ Trợ màu
Một ứng dụng MIDP chỉ có một đối tượng Display Đối tượng này đuợc dùng
để lấy thông tin của màn hình hiển thị hiện tại, ví dụ như số màu hỗ trợ và cácphương thức để yêu cầu các đối tượng được hiển thị Đối tượng Display đơn giản làmột bộ quản lý sự hiển thị của thiết bị và điều khiển những gì sẽđược hiển thị ra trênthiết bị
Có hai phương thức chúng ta cần quan tâm đến:
boolean isColor()
int numColors()
Phương thức đầu tiên cho biết thiết bị có hỗ trợ hiển thị màu hay không Nếu cóthì phương thức thứ 2 sẽ được gọi để xác định số màu được hỗ trợ Các phươngthức tiếp theo dưới đây để lấy về màu và thiết lập màu ưa thích của bạn
void setColor(int RGB)
void setColor(int red, int green, int blue)
int getColor()
int getBlueComponent() int getGreenComponent() int getRedComponent()
void setGrayScale(int value)
int getGrayScale()
Chú ý ta có thể xác định màu bằng 2 cách
Cách 1: Xác định một số nguyên đại diện cho 3 giá trị của màu là đỏ,
xanh lá cây và xanh dương với 8 bit cho mỗi màu
Cách 2: Dùng từng tham số riêng biệt để xác định mỗi màu Khi sử
dụng một giá trịđể lưu giữ màu, thì màu đỏ sẽ chiếm 8 bit đầu kể từ bêntrái, tiếp theo là 8 bit dành cho màu xanh lá cây, sau cùng là màu xanhdương
Dưới đây là cách thiết lập màu chỉ sử dụng một số nguyên:
int red = 0, green = 128, blue = 255;
Trang 23g.setColor((red << 16) | (green << 8) | blue);
Và ta có thể xác định màu bằng cách thiết lập giá trị cho 3 tham số:
g.setColor(red, green, blue);
.II.4.2.3.2 Vẽ cung
Khi vẽ một cung, bạn có thể vẽ nó chỉ có đường bao xung quanh hay yêu cầu
nó được tô bên trong Bạn có thể bắt đầu bằng cách chỉđịnh chiều bao quanh bênngoài của một hình hộp chữ nhật tưởng tượng Góc bắt đầu xác định vị trí bắt đầuvẽkhung, với giá trị 0 được xác định tại thời điểm 3 giờ Giá trị dương tính theongược chiều kim đồng hồ Góc của cung chỉ ra rằng có bao nhiêu độ được vẽ tính
từ góc ban đầu, đi theo ngược chiều kim đồng hồ Để hiểu rõ những phần nàychúng ta hãy cùng xem1 ví dụ sau:
g.drawArc(10, 10, 100, 100, 0, 150);
Đoạn mã trên yêu cầu vẽ một cung,cung này được bao bởi một hình chữ nhật
có tọa độ điểm trái trên là (10,10),chiều rộng và chiều dài là 100, góc bắt đầu là 0,góc kết thúc là 150
Hình 6: Vẽ cung
Trang 24void drawRect(int x, int y, int width, int height)
void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) void fillRect(int x, int y, int width, int height)
void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight)
Khi vẽ hình chữ nhật có 4 góc là tròn thì bạn phải xác định đường kính theo chiềungang (arcWidth) và đường kính theo chiều dọc (arcHeight) Những tham số này đượcđịnh nghĩa độ sắc nét của cung theo mỗi chiều Giá trị càng lớn thể hiện một cungtăng dần, ngược lại là một đường cong hẹp
.II.4.2.3.4 Điểm neo
Để xác định tọa độ x, y của chuỗi ký tựđược hiển thị, thì điểm neo cho phépchúng ta chỉ ra vị trí muốn đặt tọa độ (x,y) trên hình chữ nhật bao quang chuối ký tự
Hình 7: Điểm neo(1)
Có 6 điểm neo được định nghĩa trước, 3 theo chiều dọc và 3 theo chiều thẳngđứng Khi xác định điểm neo để vẽ chuỗi (các điểm neo thường được sử dụngthành từng cặp), ta phải chọn một điểm hoành độ và một điểm tung độ Các điểm
Trang 25neo được định nghĩa như ở dưới đây
- Chiều ngang
LEFT (Bên trái)
HCENTER (Chính giữa của chiều ngang) RIGHT (Bên phải)
- Chiều dọc
TOP (Ở trên)
BASELINE (Đường thẳng cơ sở) BOTTOM (Ở dưới)
Khi sử dụng điểm neo thì cần phải chỉ ra tọa độ x, y của hình chữ nhật baoquanh
Ví dụ:
g.drawString("developerWorks", 0, 0 , Graphics.TOP | Graphics.LEFT);Hình dưới đây mô tả kết quả của hàm trên
Hình 8: Điểm neo(2)
Bằng cách thay đổi điểm neo, chúng ta có thể thay đổi vị trí hiển thị của chuỗi
ký tự trên thiết bị di động Ví dụ tiếp theo chúng ta sẽ minh họa tiếp khi thay đổiđiểm neo thì vị trí của chuỗi ký tự cũng thay đổi theo:
Hình 9: Điểm neo(3)
Trang 26.II.4.2.3.5 Vẽ các chuỗi ký tự
Sau khi tìm hiểu về font và các điểm neo, bạn đã có thể vẽ chuỗi ký tự ra mànhình thông qua một số các phương thức sau:
void drawChar(char character, int x, int y, int anchor)
void drawChars(char[] data, int offset, int length, int x, int y, int anchor)
void drawString(String str, int x, int y, int anchor)
void drawSubstring(String str, int offset, int len, int x, int y, int anchor)
.II.4.2.3.6 Vẽ ảnh
Lớp Graphics cung cấp 1 phương thức dùng để vẽ ảnh:
drawImage(Image img, int x, int y, int anchor)
Chúng ta cũng áp dụng từng bước khi vẽ ảnh cũng giống như khi xuất chuỗi ramàn hình Đối với cả 2 thì chúng ta đều phải bắt đầu bằng việc thiết lập tọa độ x, ycũng nhưđiểm neo Danh sách các điểm neo cho việc hiển thị ảnh cũng không khácmấy so với việc xuất chuỗi, tuy nhiên không giống với việc xuất chuỗi thì một bứcảnh có một điểm trung tâm Ví thếVCENTER được thay thế cho gia trịBASELINE khi làm việc với ảnh
- Chiều ngang
LEFT (Bên trái)
HCENTER (Điểm chính giữa theo chiều ngang), RIGHT (Bên phải)
- Chiều dọc
TOP (Điểm trên)
VCENTER (Điểm chính giữa theo chiều dọc), BOTTOM (Bên dưới)
Hình 10: Vẽ ảnh
Trang 27.II.4.2.3.7 Một số các phương thức khác của lớp Graphics:
clip() và translate() là 2 phương thức của lớp Graphics Một vùng hiển thị đượccắt xén được định nghĩa là khu vực hiển thị của thiết bị di động, vùng này sẽ đượccập nhật trong suốt thao tác vẽ lại Dưới đây là một số phương thức hỗ trợ cho việcxén một vùng hiển thị
void setClip(int x, int y, int width, int height) void clipRect(int x, int y, intwidth, int height) int getClipX()
.II.4.3 Record Management System - RMS
MIDP không sử dụng hệ thống file để lưu trữ dữ liệu Thay vào đó MIDP lưutoàn bộ thông tin vào non-volatile memory bằng hệ thống lưu trữ gọi là RecordManagement System (RMS)
.II.4.3.1 Lưu Trữ Cố Định Thông Qua Record Store
RMS là hệ thống được tổ chức và quản lý dưới dạng các record (bản ghi) Mỗibản ghi (sau này gọi là Record) có thể chứa bất kỳ loại dữ liệu nào, chúng có thể làkiểu số nguyên, chuỗi ký tự hay có thể là một ảnh và kết quả là một Record là mộtchuỗi (mảng) các byte Nếu bạn mã hoá dữ liệu của bạn dưới dạng nhị phân(binary), bạn có thể lưu trữ dữ liệu bằng Record sau đó đọc dữ liệu từ Record vàkhôi phục lại dữ liệu ban đầu Tất nhiên kích thước dữ liệu của bạn không đượcvuợt quá giới hạn qui định của thiết bị di động RMS lưu dữ liệu gần như một cơ sở
dữ liệu, bao gồm nhiều dòng, mỗi dòng lại có một số định danh duy nhất
Trang 28Một cơ sở dữ liệu kiểu bản ghi
số nguyên gọi là Record ID Record đầu tiên được tạo ra sẽđược gán Record ID là 1
và sẽ tăng thêm 1 cho các Record tiếp theo Cần chú rằng Record ID không phải làchỉ mục (index), các thao tác xóa Record trong RecordStore sẽ không gây nên việctính toán lại các Record ID của các Record hiện có cũng như không làm thay đổiRecord ID của các Record được tạo mới, ví dụ: khi ta xóa record id 3 khi thêm mộtrecord mới sẽ có id là 4 Data là một dãy các byte đại diện cho dữ liệu cần lưu.Tên được dùng để phân biệt các RecordStore trong bộ các MIDlet (MIDletsuite) Cần chú ý khái niệm MIDlet suite là tập các MIDlet có chung không gian tên(name space), có thể chia sẽ cùng tài nguyên (như RecordStore), các biến tĩnh(static variable) trong các lớp và các MIDlet này sẽđược đóng gói trong cùng mộtfile .jar khi triển khai Nếu ứng dụng của bạn chỉ có một MIDlet thì cácRecordStore được sử dụng cũng phân biệt lẫn nhau bằng các tên Tên củaRecordStore có thể dài đến 32 ký tự Unicode và là duy nhất trong một MIDlet suite
Trang 29có thể dùng chung một tên.
Record Store còn có 2 thuộc tính là Version Number và Date/time Stamp, cácgiá trị này thay đổi khi thực hiện thêm, thay thế hay xóa một record, ngoài ra còn cóthể dùng cơ chế event handler (Listener) để phát hiện mỗi khi Record store bị thayđổi Version number là một số integer, để biết giá trị khởi đầu cần gọi hàmgetVersion() sau khi tạo một Record store Date/time Stamp là số long integer, là sốmiliseconds kể từ ngày 1 tháng 1 năm 1970, chúng ta có thể biết được giá trị nàythông qua hàm getLastModified()
Trang 30.II.4.3.2 Các Vấn Đề Liên Quan Đến RMS
- Hạn chế về khả năng lưu trữ của thiết bị di động
Dung lượng vùng nhớ (non-volatile memory) dành riêng cho việc lưu trữ dữliệu trong RMS thay đổi tùy theo thiết bị di động Đặc tả MIDP yêu cầu rằng cácnhà sản xuất thiết bị di động phải dành ra vùng nhớ có kích thước ít nhất 8K choviệc lưu trữ dữ liệu trong RMS Đặc tả không nêu giới hạn trên cho mỗi Record.RMS cung cấp các API để xác định kích thước của mỗi Record, tổng dung lượngcủa RecordStore và kích thước còn lại của vùng nhớ này Do đó trong quá trìnhphát triển các ứng dụng J2ME lập trình viên phải cân nhắc trong việc sử dụng vùngnhớ này
- Tốc độ truy xuất dữ liệu
Các thao tác trên vùng nhớ này (non-volatile memory) tất nhiên sẽ chậm hơnnhiều khi truy xuất dữ liệu trên bộ nhớ RAM (volatile memory) Nó sẽ giống nhưtốc độ đọc ổ cứng và tốc độ đọc từ RAM của máy tính Vì vậy trong kỹ thuật lậptrình phải thường xuyên cache dữ liệu và các thao tác liên quan đến RMS chỉ thựchiện tập trung một lần (lúc khởi động hay đóng ứng dụng)
- Cơ chế luồng an toàn
Nếu RecordStore của chỉ được sử dụng bởi một MIDlet thì không phải lo lắng
về vấn đề này vì RMS sẽ dành riêng một Thread để thực hiện các thao tác trênRecordStore Tuy nhiên nếu có nhiều MIDlet và Thread cùng chia sẻ mộtRecordStore thì phải chú ý đến kỹ thuật lập trình Thread để đảm bảo không có sựxung đột dữ liệu
.II.4.3.3 Sắp Xếp Các Record Với interface RecordComparator
Interface này giúp người lập trình so sánh hai Record theo một tiêu chí nào đó.Interface này định nghĩa phương thức compare với trị đầu vào là hai mảng các bytethể hiện hai Record cần so sánh Phương thức này trả về các trị sau được định nghĩatrong interface:
EQUIVALENT: Nếu hai Record bằng nhau
FOLLOWS: Nếu Record thứ 1 đứng sau Record thứ 2
PRECEDES: Nếu Record thứ 1 đứng trước Record thứ 2
Trang 31Do RecrdComparator là một interface nên khi sử dụng cần phải implements nó:
public class Comparator implements RecordComparator {
public int compare(byte[] rec1, byte[] rec2)
{
String str1 = new String(rec1), str2 = new String(rec2);
int result = str1.compareTo(str2);
if (result == 0) return RecordComparator.EQUIVALENT;
else if (result < 0) return RecordComparator.PRECEDES;
else return RecordComparator.FOLLOWS;
}
}
Sau đó ta sử dụng lớp Comparator bằng cách gắn kết nó vớiRecordEnumeration:
// Create a new comparator for sorting
Comparator comp = new Comparator();
// Reference the comparator when creating the result set
.II.4.3.4 Tìm Kiếm Với Bộ Lọc RecordFilter
Ngoài việc sắp xếp các record (sử dụng RecordComparator), enumerator còncung cấp cơ chế lọc (tìm kiếm các record thỏa mãn một điều kiện nào đó).Khi sử dụng RecordComparator tất cả các record trong RecordStore đều được lưutrong một result set Nhưng khi dùng RecordFilter, chỉ có những thỏa mãn điềukiện mới có trong enumerator result set
Trang 32class SearchFilter implements RecordFilter
{
private String searchText = null;
public SearchFilter(String searchText)
String str = new String(candidate).toLowerCase();
// Look for a match
if (searchText != null && str.indexOf(searchText) != -1) return true; else return false;
}
}
Trên đây là một class đơn giản thực thi interface RecordFilter Class này sẽđược gắn với một enumerator, và khi đó enumerator sẽ dùng hàmmatches() duyệt hết recordstore lấy ra những record cần tìm:
// Create a new search filter
SearchFilter search = new SearchFilter("search text");
// Reference the filter when creating the result set
RecordEnumeration re = rs.enumerateRecords(search,null,false);
// If there is at least one record in result set, a match was found if (re.numRecords() > 0)
// Do something
Trang 33.II.4.4 Sound, Music and Video:
Các MMAPI được xây dựng dựa trên sự trừu tượng cấp cao của tất cả các thiết
bị đa phương tiện Sự trừu tượng này được cài đặt(implement) trong ba lớp đã hìnhthành lõi(core) của các hoạt động mà bạn làm với các API này Những lớp này là 2interface Player và Control, và lớp Manager Một lớp khác, lớp trừu tượngDataSource, được sử dụng để xác định vị trí tài nguyên, nhưng nếu bạn định nghĩamột phương pháp mới để đọc dữ liệu, bạn sẽ không cần sử dụng nó một cách trựctiếp
Tóm lại, lớp Manager được sử dụng để tạo ra các thể hiện Player cho các mediakhác nhau bằng cách xác định các thể hiện DataSource Như vậy, các thể hiệnPlayer có thể tạo ra được cấu hình bằng cách sử dụng các thể hiện Control Ví dụ,hầu hết các thể hiện Player hỗ trợ VolumeControl để điều khiển âm lượng của cácPlayer Kiểm tra sơ đồ sau đây:
Hình 12: Sơ đồ âm thanh
Lớp Manager về cơ bản là một factory của các player được hỗ trợ bởi cácphương thức sau đây:
- createPlayer(DataSource source): tạo một player dựa trên DataSource
- createPlayer(InputStream stream, String type): tạo một player sử dụnginput stream như là nguồn và giả định rằng các kiểu media đã được cung cấp
- createLayer(String url): tạo một player sử dụng một url để xác định dữliệu nguồn
Trang 34Phương thức cuối cùng cho phép bạn phân bổ các loại media khác nhau, tùythuộc vào giao thức URL được chọn chọn Các loại sau được hỗ trợ:
Midi Player – “device://midi”: tạo một midi Player
Tone Player – “device://tone”: tạo một tone Player
Capture Audio – “capture://audio”: cho phép capture audio từ thiết bị
Capture Video – “capture://video”: cho phép capture video từ thiết bị
Capture Radio – “capture://radio?f=105.1&st=stereo”: cho phép capture radio Sau khi bạn đã tạo ra một player, bạn có thể bắt đầu sử dụng nó bằng cách đơngiản gọi phương thức start () Khi đạt đến sự kết thúc của media thì nó stop mộtcách tự động Đây là một cái nhìn đơn giản của lớp Player Trên thực tế lớp có nămtiểu trạng thái:
- UNREALIZED: đây là trạng thái đầu tiên của Player thu được từ lớpManager
- REALIZED: Khi phương thức realized() được gọi, Player chuyển sangtrạng thái này để thu nhận thông tin cần thiết để có được các nguồn media.Quá tìnhrealized một Player có thể là một tài nguyên và quá trình tiêu tốn thời gian Player
có thể phải giao tiếp với server, đọc một file hay tương tác với một tập các đốitượng
- PREFETCHED: Sau khi một player được realized, nó có thể vẫn cầncác tài nguyên khan hiếm hay độc quyền, fill bộ đệm với dữ liệu media hay thựchiện các tiến trình start-up khác Và điều này được thực hiện bằng cách gọi phươngthức prefetch() để chuyển đổi sang trạng thái này
- STARTED: Khi gọi phương thức start(), Player bắt đầu play tài nguyênmedia cho đến khi nó đạt đến sự kết thúc của media
- CLOSED: khi gọi phương thức close(), Player chuyển đổi sang trạng thái này,giải phóng tất cả các tài nguyên nắm giữ Và nó không thể sử dụng lại lần nữa