Tạp chí Lập trình – Khi trả lời câu hỏi “Lập trình mobile khác gì với lập trình trên nền tảng PC?”, thì có đến khoảng 90% các bạn lập trình viên sẽ nghĩ ngay đến 2 vấn đề “Memory’ – Bộ nhớ và “Performance’ – Tốc độ xử lí. Điều này rất dễ giải thích vì các bạn đều biết mobile là một thiết bị với giới hạn về tốc độ xử lí của chip (CPU) và dung lượng bộ nhớ trong (RAM).

Nhưng trong bài viết này tôi sẽ đề cập đến một vấn đề khác cũng không kém phần quan trong trọng và thực sự là khác biệt của lập trình mobile. Đã có rất ít bạn khi mới làm quen với lập trình mobile để ý. Đó là vấn đề “Competition” – cạnh tranh. Để có một ứng dụng tốt thì nhất định phải giải quyết được cả 3 vấn đề trên.

Vậy Competition trong lập trình mobile thể hiện như thế nào? Tôi sẽ lấy các ví dụ và cách giải quyết bài toán trong Android để giải thích khái niệm này.

Vì trong một bài viết không thể nói hết được một vấn đề lớn của lập trinh mobile nên tôi chỉ mong có thể giải thích khái niệm và cơ chế hoạt động chứ không quá đi sâu chi tiết về coding.

TH1 : Các bạn đang nghe nhạc thì có một cuộc gọi đến. Nhạc sẽ tắt để bạn có thể trả lời cuộc gọi. Sau khi cuộc gọi kết thúc nhạc sẽ lại tự động được bật lên.

Trong tình huống này ứng dụng nghe nhạc đã phải tạm dừng để ưu tiên cho ứng dụng gọi điện được hoạt động. Khi kết thúc cuộc gọi thì ứng dụng nghe nhạc sẽ lại được hoạt động trở lại. Điều này không phải do hệ thống tự xử lý mà được xử lý trong ứng dụng nghe nhạc. Nếu bạn muốn tạo ra ứng dụng nghe nhạc của riêng mình thì đây là một điều cần chú ý nếu không người dùng sẽ vừa phải nghe nhạc và vừa nghe điện thoại J

Tương tự với các game, nếu bạn đang chơi game mà có cuộc gọi đến thì game của bạn sẽ phải tạm dừng, sau khi kết thúc cuộc gọi màn hình chơi game sẽ được hiện ra với một menu có nút resume để bạn chơi tiếp.

TH2: Khi các bạn vào ứng dụng contact, chọn call tới một contact các bạn sẽ thấy một danh sách các ứng dụng hiện ra (Call, Viber, Skype, …) bạn phải chọn một trong các ứng dụng để call. Tương tự với các trường hơp bạn mở môt SMS hay Mail mới. Tại sạo như vậy?

TH3: Bạn đang lượn lờ Facebook bằng điên thoại và ra khỏi khu vực có wifi. Ứng dụng Facebook sẽ thông báo “No Internet Connection’ để thông báo với bạn rằng mobile của bạn không còn kết nối với wifi nữa. Bạn sẽ ko view thêm được bất kì comment hoặc message nào nữa. Tại sao ứng dụng Facebook lại biết được khi nào mobile của bạn không còn kết nối với wifi?

TH4: Bạn đang xem một quảng cáo sản phẩm trong một ứng dụng. Bạn thích sản phẩm này và muốn liên hệ với cửa hàng đặt mua. Bạn click vào số điện thoại của cửa hàng bên dưới sản phẩm. Và thế là mobile của bạn calling đến số điện thoại đó. Và ‘a lô, xin chào bạn đến với cửa hàng….’. Tại sao ứng dụng quảng cáo sản phẩm lại có thể gọi ra ứng dụng call như vậy.

Để giải quyết tất cả các trường hợp cạnh tranh này Android đã đưa ra một khái niệm Broadcast Receiver. Vậy Broadcast Receiver là gi?

Broadcast receiver là một thành phần android cơ bản nó cho phép ứng dụng của bạn đăng kí lắng nghe các sự kiện của hệ thống hoặc của các ứng dụng khác.

Nôm na như sau, trong Android có một thành phần giống như đài truyền hình (broadcaster), nó có nhiệm vụ phát sóng (send) các sự kiện (events) tới các ứng dụng (broadcast receiver or receiver).

Các sự kiện (events) ở đây có thể là các sự kiện của hệ thống như incoming call, new SMS, low battery, wifi ON/OFF, Screen lock/unlock, time zone change… hoặc sự kiện do các ứng dụng thông thường tạo ra. Như vậy ngay ứng dụng của các bạn cũng có thể phát ra các sự kiện và broadcaster sẽ gửi nó đến các ứng dụng có trên thiết bị.

Để ứng dụng của bạn nhận được các sự kiện từ broadcaster như trên thì bạn phải biến ứng dụng của bạn thành một receiver. Có 2 cách để đăng kí một ứng dụng trở thành receiver.

Cách 1: đăng kí trong file AndroidMenifest.xml của ứng dụng

[code language=”xml”]
<receiver android:name=".MyWifiReceiver">
<intent-filter>
<action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
</intent-filter>
</receiver>
[/code]

Intent-filter định nghĩa ra một loại message thông bao sự kiện trạng thái wifi thay đổi (WIFI_STATE_CHANGED) và đoạn code xml trên đã đăng kí ứng dụng nhận các thông báo liên quan đến sự thay đổi trạng thái của wifi.

“MyWifiReceiver” là một class extends BroadcastReceiver class và bạn phải overwrite hàm onReceive(). Class MyWifiReceiver sẽ nhận và sử lí intent-filter trên trong hàm onReceive()

Cách 2: đăng kí trong code, sử dụng hàm Context.registerReceiver()

[code language=”java”]
context.registerReceiver(new BroadcastReceiver() {

@Override
public void onReceive(Context context, Intent intent) {

try {

int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN);

switch (wifiState) {
case WifiManager.WIFI_STATE_DISABLING:
// DO SOMETHING HERE
break;

case WifiManager.WIFI_STATE_DISABLED:
// DO SOMETHING HERE
break;

case WifiManager.WIFI_STATE_ENABLING:
// DO SOMETHING HERE
break;

case WifiManager.WIFI_STATE_ENABLED:
// DO SOMETHING HERE
break;

case WifiManager.WIFI_STATE_UNKNOWN:
// DO SOMETHING HERE
break;

default:
break;

}
} catch (Exception e) {

}
}

}, new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION));

[/code]

Bạn cũng có thể gỡ bỏ đăng kí broadcast receiver bằng hàm Context.unregisterReceiver()

Có rất nhiều các sự kiện mà ứng dụng có thể đăng kí lắng nghe như đã nói ở trên và mỗi loại sự kiện sẽ tương ứng với các action khác nhau. Bạn có thể tham khảo trong link sau.

https://github.com/ViliusKraujutis/AndroidBroadcastsMonitor/wiki/List-of-all-Broadcast-Intent-actions.-API-17

Bây giờ tôi quay lại giải 4 trường hợp đã nêu ra ở trên để cho các bạn có hình dung thực tế hơn.

TH1: Ứng dụng nghe nhạc sẽ phải đăng kí một receiver để lắng nghe sự kiện incoming call và end call.

[code language=”xml”]
<receiver android:name=".PlayerReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
[/code]

Xử lí khi bắt được sự kiện incoming call va end call trong class PlayerReceiver

[code language=”java”]
public void onReceive(Context context, Intent intent) {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);

if(state.equals(TelephonyManager.EXTRA_STATE_RINGING)){
//Phone is ringing à Stop service play media
}else if(state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK){
//Call received
}else if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)){
//Call Dropped or rejected à Restart service play media
}
}
[/code]

TH2: Khi các bạn vào ứng dụng contact, chọn call tới một contact các bạn sẽ thấy một danh sách các ứng dụng hiện ra (Call, Viber, Skype, …) bởi vì tất cả các ứng dụng trên đều đăng kí nhận sự kiện outgoing call của hệ thống. Vì vậy khi bạn chọn call tới một số nào đó trong contact thì cả 3 ứng dụng này đều có nhận được message outgoing call và tất cả đều có thể start để thực thi cuộc gọi. Lúc này hệ thống sẽ đưa ra danh sách các ứng dụng trên cho người dùng lựa chọn. Nếu úng dụng của bạn đăng kí nhận sự kiện ACTION_NEW_OUTGOING_CALL thì nó cũng được hiện thị trong danh sách ứng dụng trên cùng với Call, Viber, Skype,…

TH3: Ứng dụng Facebook đã đăng kí nhận sự kiện WIFI_STATE_CHANGED vì vậy khi Wifi bị tắt hoặc device đi ra khỏi khu vực có wifi thì ứng dụng sẽ nhận được sự kiện này và hiển thị thông báo “No Internet Connection”.

TH4: Bạn click vào số điện thoại của cửa hàng bên dưới sản phẩm. Và thế là mobile của bạn calling đến số điện thoại đó. Lúc này ứng dụng của bạn sẽ gửi đến hệ thống (broadcaster) một message với action là ACTION_CALL. Hệ thống (broadcaster) sẽ gửi message này tới các ứng dụng. Ứng dụng nào đăng kí xử lí message này thì sẽ được mớ. Trong trường hợp này ứng dụng call sẽ được start. Và người dùng có thể gọi đến số điện thoại ghi trên quảng cáo. Thật là đơn giản phải không. Tương tự như vậy bạn có thể gọi ra các ứng dụng khác như SMS, Browser, …có sẵn trên thiết bị.

Bạn cũng có thể tự định nghĩa ra các sự kiện của riêng mình và gửi chúng đến các ứng dụng khác có trên thiết bị hay chính các ứng dụng khác của bạn. Tôi có thể gợi ý cho các bạn một ví dụ sau.

Bạn có 2 ứng dụng đọc sách và từ điển. Trong ứng dụng đọc sách có thể gửi message do bạn đinh nghĩa ra tới hệ thống (Broadcaster). Hệ thống sẽ gửi message này tới tất cả các ứng dụng nhưng chi có duy nhất ứng dụng từ điển của bạn đăng kí nhận xử lí message này. Và thế là ứng dụng từ điển của bạn được mở khi bạn đang đọc sách.

Tôi xin dừng lại ở đây và hi vọng với các giới thiệu tổng quan ở trên các bạn đã phần nào hình dung ra cơ chế hoạt động của broadcast receiver và một số tình huống cơ bản hay gặp khi làm việc với nó. Các bạn có thể tham khảo kĩ thuật chi tiết hơn trong các link bên dưới đây.

http://www.vogella.com/articles/AndroidBroadcastReceiver/article.html#broadcastreceiver_definition

http://developer.android.com/reference/android/content/BroadcastReceiver.html

Hà Nội, ngày 21/04/2013

LuQuTu