Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (1.17 MB, 129 trang )
Xây dựng ứng dụng 3D với Android
55
______________________________________________________________________
// code xử lý chính của thread trong này
super.run();
}
};
thread.start(); //bắt đầu thread
•
Lưu ý:
– Thread lần đầu thực thi gọi phương thức start(), những lần sau chỉ gọi
phương thức run(), không gọi start() nữa.
– Các code xử lý liên quan đến giao diện chỉ được xử lý trong thread chính
của ứng dụng (ví dụ load ảnh từ mạng về thì dùng thread, nhưng hiển thị
ảnh lên ImageView thì xử lý trong thread chính)
– Sau khi thực thi xong phương thức run(), thread không còn hoạt động
nữa.
4.2 Handler:
Trong Android, để tiện việc giao tiếp giữa 2 thread ta dùng đối tượng Handler.
Có thể dùng Handler như bộ đếm giây khi chơi nhạc, hoặc chức năng tương tự . Ngoài
ra, có thể dùng Handler để đặt xử lý một yêu cầu nào đó sau một khoảng thời gian xác
định.
Giao tiếp giữa 2 Thread:
– Giả sử trong phương thức run() đã lấy xong đối tượng Bitmap về. Muốn
truyền đối tượng Bitmap cho Thread chính hiển thị lên màn hình:
Message msg = mHandler.obtainMessage(1, bitmap);
mHandler.sendMessage(msg);
– Trong code của Activity (mặc định là thread chính), ta khai báo một đối
tượng Handler tương tứng như sau:
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
Xây dựng ứng dụng 3D với Android
56
______________________________________________________________________
if (msg.what == 1) {
//Hiển thị Bitmap
mImageView.setImageBitmap((Bitmap)msg.obj);
}
super.handleMessage(msg);
}
};
– Trong đoạn code trên, đối tượng mHandler lấy ra một message và gắn mã
vào cho message đó, kèm theo đối tượng bitmap. Sau đó gửi đi.
– Message gửi đi sẽ được nhận phương thức callback là handleMessage()
của đối tượng Handler.
– Handler còn có thể gửi message để xử lý sau một khoảng thời gian định
sẵn sendMessageAtTime hoặc xử lý tại một thời điểm định sẵn
sendMessageDelayed.
Lưu ý:
– Handler được tạo trong thread nào thì sẽ sử dụng hàng đợi message của
thread đó.
– Nếu trong hàng đợi message vẫn còn message thì vẫn còn thực thi dù đã
thoát khỏi ứng dụng.
4.3 AlarmManager (báo hiệu):
Dùng AlarmManager để thực hiện đăng ký xử lý một thao tác nào đó tại một
thời điểm nhất định trong tương lai (thường là thời gian dài, nếu xử lý trong thời gian
ngắn thì khuyến cáo nên dùng Handler). Khi đến thời điểm được đặt trước, dù ứng
dụng đang không chạy thì nó vẫn được gọi. Nếu tắt máy rồi bật lại thì không còn.
Khởi tạo một AlarmManager:
Xây dựng ứng dụng 3D với Android
57
______________________________________________________________________
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent broadcastIntent = new Intent("org.multiuni.android.ACTION...");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,
0, broadcastIntent, PendingIntent.FLAG_CANCEL_CURRENT);
am.set(AlarmManager.RTC_WAKEUP, triggerAtTime, pendingIntent);
Giải thích:
– Khởi tạo một đối tương AlarmManager để làm việc với Alarm.
– Tạo một intent tên broadcastIntent, intent này được dùng để gửi
broadcast khi đến thời điểm định sẵn.
– PendingIntent được khởi tạo gồm context, broadcastIntent ở trên và một
cờ báo rằng nếu đã có một Alarm tương tự thì bỏ nó đi và dùng cái mới
này.
– Sau cùng, set alarm với 3 thông số:
+ Bộ đếm thời gian.
+ Thời gian chính xác để bật alarm lên.
+ PendingIntent gửi đi (dùng để xác định tới thời điểm bật alarm lên
thì cần phát intent nào).
4.4 Notification (thông báo):
Trong những trường hợp chúng ta muốn hiện một thông báo về một sự kiện nào
đó (tin nhắn, cuộc gọi, email…) cho người dùng mà không muốn ảnh hưởng đến công
việc của họ hoặc không chắc là họ có đang cầm điện thoại hay không, hoặc bạn muốn
hiển thị thông tin một việc nào đó đang xảy ra trên điện thoại (đang nghe nhạc, đang
trong cuộc gọi, thiếu thẻ nhớ…) và mong người dùng biết thì chúng ta dùng
Notification.
Chúng ta có thể tạo một thông báo có nhiều hình thức khác nhau như có âm báo,
rung, đèn led, icon…
Mỗi phương pháp thông báo có một tham số id kiểu int và tùy chọn một tham số
tag kiểu String, có thể là null, tạo thành một bộ hai (tag, id) hoặc (null, id). Bộ hai này
nhận diện thông báo từ ứng dụng, và phải là duy nhất trong ứng dụng. Nếu gọi một
Xây dựng ứng dụng 3D với Android
58
______________________________________________________________________
trong những phương thức thông báo với bộ (tag, id) hiện đang hoạt động và thiết lập
các thông số mới thì nó sẽ được cập nhật. Ví dụ, nếu lướt qua một biểu tượng mới của
thanh trạng thái thì biểu tượng cũ của thanh trạng thái sẽ được thay thế bằng biểu
tượng mới.
Chúng ta không khởi tạo lớp này trực tiếp mà lấy nó thông qua
getSystemService(String). Ví dụ:
String svcName = Context.NOTIFICATION_SERVICE;
NotificationManager notificationManager;
notificationManager = (NotificationManager)getSystemService(svcName);
NotificationManager là một dịch vụ hệ thống dùng để quản lý các Notification.
Tạo một thông báo:
– Tạo một đối tượng Notification, truyền vào icon để hiển thị ở thanh trang
thái và thời gian hiển thị:
// chọn một drawable để hiển thị như là một icon của thanh trạng thái
int icon = R.drawable.icon;
// Text để hiển thị lên thanh trạng thái khi thông báo được chạy
String tickerText = “Notification”;
// thanh trạng thái mở rộng sắp xếp các thông báo theo thứ tự thời gian
when = System.currentTimeMillis();
Notification notification = new Notification(icon, tickerText, when);
– Cấu hình giao diện của Notification trong cửa sổ trạng thái mở rộng, sử
dụng phương thức setLatestEventInfo. Cửa sổ trạng thái mở rộng này
hiển thị icon và thời gian được khai báo trong constructor và đồng thời
hiển thị tiêu đề và chi tiết về chuỗi thông báo.
Context context = getApplicationContext();
// Text để hiển thị trên cửa sổ trạng thái mở rộng
String expandedText = “Extended status text”;
// Tiêu đề của thanh trạng thái mở rộng
String expandedTitle = “Notification Title”;
// Intent chạy một activity khi text được click
Xây dựng ứng dụng 3D với Android
59
______________________________________________________________________
Intent intent = new Intent(this, MyActivity.class);
PendingIntent launchIntent = PendingIntent.getActivity(context, 0,
intent, 0);
notification.setLatestEventInfo(context, expandedTitle,
expandedText,
launchIntent);
– Cải tiến thông báo bằng các thuộc tính khác của đối tượng Notification
để làm nháy đèn trên LED trên thiết bị, rung điện thoại hay trình diễn các
file nhạc.
Gọi một thông báo:
Để thực hiện gọi một thông báo, gọi phương thức
notify của
NotificationManager:
int notificationRef = 1;
notificationManager.notify(notificationRef, notification);
Để cập nhật một thông báo đã được sử dụng, gọi lại và truyền lại giá trị
reference ID. Cũng có thể sử dụng ID này để hủy thông báo bằng cách gọi phương
thức cancel của NotificationManager.
notificationManager.cancel(notificationRef);
Việc hủy thông báo sẽ xóa thanh icon trạng thái và cửa sổ trạng thái mở rộng.
Chương 5: Áp dụng OpenGL ES để tạo ứng dụng 3D trên Androi
Xây dựng ứng dụng 3D với Android
60
______________________________________________________________________
5.1 Giới thiệu về OpenGL ES:
OpenGL ES (OpenGL for embedded systems) được phát triển bởi nhóm
Khronos, là một sản phẩm miễn phí bao gồm các hàm API cho phép tạo các ứng dụng
2D, 3D trên các ứng dụng nhúng – bao gồm các thiết bị cầm tay. Nó như là một tập con
của OpenGL (Open Graphics Library), tạo ra tính linh hoạt, mạnh mẽ trên giao diện
cấp thấp giữa các phần mềm và đồ họa. Vì vậy OpenGL ES nhỏ hơn nhiều so với
OpenGL, nên nhiều chức năng thuận tiện đã được gỡ bỏ. Ví dụ, vẽ hình chữ nhật là
không trực tiếp hỗ trợ trong OpenGL ES, bạn phải vẽ hai tam giác để tạo ra một hình
chữ nhật.
Mỗi phiên bản OpenGL ES tương ứng với một phiên bản OpenGL. OpenGL ES
1.0 chỉ tập trung vào các phần mềm cho phép triển khai, là tập con của OpenGL 1.3.
OpenGL ES 1.1 nhấn mạnh về tốc độ phần cứng của các hàm API, là tập con của
OpenGL 1.5. OpenGL ES 2.0 chỉ thực thi các hình dạng thông thường, là tập con của
OpenGL 2.0.
5.2 Dựng (Rendering):
Đây là bước khởi tạo và thiết lập OpenGL ES, khi vẽ trên màn hình OpenGL ES
sử dụng kĩ thuật của một bộ đệm kép. Khi vẽ, chúng ta vẽ trên bộ nhớ đệm. Sau khi có
được tất cả các thông tin của việc vẽ, nó sẽ trao đổi giữa các bộ nhớ đệm và bắt đầu vẽ
trên bộ nhớ đệm khác. Điều này ngăn chặn việc chớp màn hình bởi hằng số xóa màn
hình và vẽ hình khác trên một bộ nhớ đệm.
Khai báo sử dụng thư viện OpenGL ES:
import javax.microedition.khronos.opengles.*;
Khai báo một đối tượng gl, ví dụ: GL10 gl;
Trong hàm init(), chúng ta sử dụng một lời gọi glClearColor, nó được sử dụng
để xác định màu sắc cho màn hình hiện thị, nó bao gồm 4 tham số, các tham số này đại
Xây dựng ứng dụng 3D với Android
61
______________________________________________________________________
diện cho hệ màu RGBA và có giá trị trong khoảng từ 0 đến 1. Ba tham số đầu là màu
đỏ, xanh lá cây và xanh da trời, còn tham số thứ 4 là độ sáng tối của window.
Ví dụ: đặt màu nèn đen cho màn hình hiển thị
private void init(GL10 gl) {
gl.glClearColor(0.0f, 0.0f, 0.0f,0.0f);
}
Để xóa bộ đệm, ta sử dụng hàm glClear(), tham số của nó là những hằng số xác
định. Ví dụ:
gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_
BUFFER_BIT);
Có trường hợp có những hàm chưa được chạy đến khi kết thúc chương trình, để
tránh trường hợp này, ta gọi hàm glFlush(), nó sẽ thực hiện tất cả các hàm chưa được
chạy và kết thúc đối tượng gl bằng hàm glFinish().
gl.glFlush();
gl.glFinish();
5.3 Phép chiếu trực giao (Orthographic Projection):
Có hai cách để hiển thị đối tượng đó là sử dụng phép chiếu phối cảnh và phép
chiếu trực giao.
Phép chiếu trực giao là phép chiếu song song và tia chiếu vuông góc với mặt
phẳng chiếu, cho kết quả nhanh hơn vì chi phí tính toán ít nhưng lại không mô tả đối
tượng một cách chân thực.
Xây dựng ứng dụng 3D với Android
62
______________________________________________________________________
Hình 14 - Phép chiếu trực giao
View volume được định nghĩa là một hình hộp chữ nhật, vật thể nằm trong view
volume được chiếu trực giao lên khung nhìn, do đó trong phép chiếu trực giao, khoảng
cách từ camare đến vật thể không ảnh hưởng đến độ lớn của ảnh.
Hình được tạo ra bằng cách xác định các đỉnh, đây là những điểm trong không
gian 3 chiều vì vậy cần chỉ rõ các điểm trên hình.
Danh sách các tham số
Primitive Flag
Description
GL_POINTS
Các điểm
GL_LINES
Đoạn thẳng
GL_LINE_STRIP
Đường gấp khúc không khép kín
GL_LINE_LOOP
Đường gấp khúc khép kín
GL_TRIANGLES
Tam giác
GL_TRIANGLE_STRIP
Một dải tam giác được liên kết với nhau
Xây dựng ứng dụng 3D với Android
63
______________________________________________________________________
GL_TRIANGLE_FAN
Các tam giác liên kết theo hình quạt
Khi vẽ điểm, chức năng glPointSize có thể thay đổi kích cỡ của điểm được vẽ,
kích cỡ mặc định là 1.
Khi vẽ đường, có thể sử dụng glLineWidth để xác định độ rộng của đường, kích
cỡ mặc định là 1.
Ví dụ: hiển thị một hình vuông lên màn hình
-
Bước đầu tiên là xác định tọa độ của hình vuông đặt trên màn hình, thiết lập 3
giá trị (float) x, y, z cho mỗi đỉnh:
float[] coords = {
0.25f, 0.25f, 0.0f, // 0
0.75f, 0.25f, 0.0f, // 1
0.25f, 0.75f, 0.0f, // 2
0.75f, 0.75f, 0.0f, // 3
};
-
Khởi tạo chương trình:
private void init(GL10 gl) {
gl.glClearColor(0.0f, 0.0f, 0.0f,0.0f);
Thiết lập chế độ ma trân bằng câu lệnh glMatrixMode() trước khi định nghĩa
-
phép chiếu:
gl.glMatrixMode (GL10.GL_PROJECTION);
-
Thiết lập ma trận hiện thời về ma trận đơn vị bằng lệnh glLoadIdentity()
gl.glLoadIdentity ();
-
Chức năng glOrthof được chỉ định để xác định nhìn theo phép chiếu trực giao,
nó bao gồm các tham số: glOrthof(GLfloat left, GLfloat right, GLfloat bottom,
GLfloat top,GLfloat near, GLfloat far):
gl.glOrthof(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);