Beginning Android for Application - Chapter 11: Android Services
Service là một ứng dụng trong Android mà chạy trong background và không cần
tương tác với người dùng. Ví dụ, khi sử dụng một application, bạn có thể muốn nghe một vài
bản nhạc trong cùng một thời gian. Trong trường hợp đó, phần code đang play nhạc đó không
cần tương tác với người dùng, vì thế nó chạy như là một service. Và bạn cũng có dùng
service khi không cần hiển thị UI cho người dùng. Một ví dụ thích hợp là một ứng dụng lưu
trữ vị trí địa lý của thiết bị
Thangit14.blogspot.com Thangit14@gmail.com 1 Chương 11: Android Services Service là một ứng dụng trong Android mà chạy trong background và không cần tương tác với người dùng. Ví dụ, khi sử dụng một application, bạn có thể muốn nghe một vài bản nhạc trong cùng một thời gian. Trong trường hợp đó, phần code đang play nhạc đó không cần tương tác với người dùng, vì thế nó chạy như là một service. Và bạn cũng có dùng service khi không cần hiển thị UI cho người dùng. Một ví dụ thích hợp là một ứng dụng lưu trữ vị trí địa lý của thiết bị. Tạo Services của bạn. Thangit14.blogspot.com Thangit14@gmail.com 2 Thangit14.blogspot.com Thangit14@gmail.com 3 Method onBind() cho phép bạn bind một activity vào một service. Nó cho phép một activity truy xuất member và method bên trong service. Trong ví dụ này là return null, phần tiếp theo ta sẽ thảo luận thêm về binding. Method onStartCommand() được gọi khi bạn start service bằng cách sử dụng startService() method. Thong method này, bạn trả về START_STICKY nên service sẽ tiếp tục chạy ch đến khi nó được stop bởi người dùng. Method onDestroy được gọi khi service được dừng bởi method stopService(). Điều này sẽ làm xóa bỏ các resource được sử dụng bởi service. Tất cả services bạn đều phải khai báo trong AndroidManifest.xml. Nếu bạn muốn sử dụng service trong ứng dụng khác, bạn có thể add intent filter: Để chạy service trong ứng dụng khác, bạn phải chỉ rõ action của service chứ không phải class như ví dụ trên: Thực hiện những công việc trong một Service. Thangit14.blogspot.com Thangit14@gmail.com 4 Khi bạn cho service khởi chạy, chú ý rằng, activity đó sẽ bị treo trong vòng 5s, chính là thời gian để tải file trên mạng internet. Trong thời gian đó, toàn bộ activity không có sự hồi đáp nào, việc này là rất quan trọng nếu: Service chạy trên cùng một Thread với activity của bạn. Trong trường hợp này, vì service bị tạm dừng trong 5s, nên activity của bạn cũng vậy. Thangit14.blogspot.com Thangit14@gmail.com 5 Vì thế khi thực hiện những tác vụ có thời gian dài, bạn phải viết code trong các thread độc lập. Thangit14.blogspot.com Thangit14@gmail.com 6 doInBackground() Method này nhận vào một mảng các giá trị đầu vào và được thực hiển trong background. Khi bạn gọi method publishProgress(), thì sẽ gọi ra method onProgressUpdate(). onProgressUpdate(): được gọi bằng cách dùng method publishProgress(). onProgressExecute(): Được gọi khi method doInbackground thực hiện xong. Chú ý rằng khi background thực hiện xong công việc của mình, bạn cần dừng service sử dụng method stopSelf(). Method này tương đương với method stopService(). Thangit14.blogspot.com Thangit14@gmail.com 7 Thực hiện những tác vụ lặp lại trong một Service Ví dụ, bạn có thể cân viết một alarm clock service liên tục chạy trong background. Trong trường hợp đó, service của bạn phải thực hiện một cách định kì một vài đoạn code để kiểm tra xem khi nào tới thời gian đã định trước để báo hiệu. Thangit14.blogspot.com Thangit14@gmail.com 8 Thangit14.blogspot.com Thangit14@gmail.com 9 Trong method scheduleAtFixedRate() tham số thứ 2 là thời gian trước lần thực hiện đầu tiên, tham số thứ 3 là thời gian theo sau các lần thực hiện.Trong ví dụ này, thực chất là bạn in ra một counter mỗi giây. Counter đó sẽ dừng khi nào bạn destroy service. Bạn hãy lưu ý rằng, ở đây method doSomethingRepeatedly() được gọi trực tiếp trong method onStartCommand() mà không cần nằm trong một class AsyncTask. Đó là bởi vì TimerTask class đã implement Unable Interface, vì thế cho phép nó chạy trên một thread độc lập. Executing Asynchronous Task on Separate Threads Using IntentService. Trong phần trước, bạn đã học cách sử dụng Asyncronous class và tắt service để giải thoát resources sử dụng method stopSelf(). Việc này là rất quan trọng, nhưng chúng ta thường hay quên. Vì thế để đơn giản sử dụng công việc bất đồng bộ, ta có thể sử dụng IntentService class. IntentService class đực sử dụng để xử lý các yêu cầu asynchronous. Nó được khởi chạy như một service bình thường, và nó thực hiện công việc bên trong một worker class và tự hủy khi công việc được hoàn thành. Thangit14.blogspot.com Thangit14@gmail.com 10 Thangit14.blogspot.com Thangit14@gmail.com 11 Bạn cần tạo một Constructor với IntentService để truyền và service name. Trong method onHandleIntent() bạn code những gì cần làm mà được thực hiện trong một thread riêng biệt, như là download một file. Khi đoạn code được thực hiện xong, thread đó sẽ kết thức và service sẽ dừng lại một cách tự động. Thangit14.blogspot.com Thangit14@gmail.com 12 Giao tiếp giữa một service và một Activity Thông thường, một service chỉ thực hiện những công việc trong thread của nó, độc lập với activity mà gọi service đó. Điều này không gây ra bất kì vấn đề gì nếu bạn chỉ đơn giản muốn service thực hiện một vài công việc một cách định kì và activity đó không cần được báo về status của service. Ví dụ, bạn có thể muốn một service ghi lại một cách định kì vị trí của nó trên bạn đồ và lưu vào database. Trong trường hợp này, service không cần tương tác với bất kì activities nào cả, bời vì nó có thể tự lưu vị trí vào database. Tuy nhiên, giả sử bạn muốn theo dõi một vị trí nhất định. Khi service ghi lại địa chỉ mà gần với địa chỉ mà bạn đang theo dõi, thì sẽ cần phải giao tiếp với activity khác. Thangit14.blogspot.com Thangit14@gmail.com 13 Thangit14.blogspot.com Thangit14@gmail.com 14 Binding Activities to Services. Bây giờ, giả thiết rằng bạn muốn calling activity xác định files nào được download, thay vì đặt chúng cố định trong service. Bạn có thể làm như sau: Đầu tiên, trong calling activity, bạn tạo một Intent object, xác định service name. Sau đó, tạo một array của URL obejcts và gán nó vào Intent object thông qua putExtra() method. Thangit14.blogspot.com Thangit14@gmail.com 15 Như vậy, trong method onStartCommand() bạn phải lấy data đã truyền vào thông qua Intent object: Đây là một cách để activity của bạn có thể truyền giá trị vào service. Như bạn thấy, nếu bạn có dữ liệu để truyền vào service, bạn có thể làm một số công việc để đảm bảo dữ liệu được truyền vào là thực sự đúng, rõ ràng. Một cách khác để truyền data đó là bind activity trực tiếp vào service, như thế activity có thể gọi bất kì method, biến nào là public trong service. Thangit14.blogspot.com Thangit14@gmail.com 16 Thangit14.blogspot.com Thangit14@gmail.com 17 Để bind một activity vào một service, bạn phải khai báo một inner class trong service, inner class này sẽ extend Binder class. Và trong inner class này, bạn implemented method getService(). Ta tạo ra một tham số serviceBinder object để liên kết với service, giúp bạn truy cập trực tiếp. Sau đó bạn phải tạo ra một instance của ServiceConnection class cho phép bạn theo dõi trạng thái của service: Thangit14.blogspot.com Thangit14@gmail.com 18 Method onServiceConnected() được gọi khi activity được connected với service, tương tự như vậy là method onServiceDisconnected. Bạn cần lưu ý, hai method startService(Intent) và startService(View) là khác nhau. Khi bạn nhấn vào button start service, ta dùng method bindService để cho phép activity kết nối đến service: Method này sẽ cần đến một Serviceconnection. Trong method onServiceConnected() của connection này, ta gọi method startService( Intent ) để khởi chạy service. Threading Phần này sẽ tóm tắt ngắn gọn các cách khác nhau để xử lý các tác vụ có thời gian xử lý dài một cách đúng đắn sử dụng đa dạng các phương thức. Bạn tạo ra một project mới tên là : Threading Thangit14.blogspot.com Thangit14@gmail.com 19 Giả sử bạn muốn hiển thị một counter từ 0 đến 1000 trong main activity: Khi bạn chạy ứng dụng và nhấn vào nút Start thì ứng dụng của bạn sẽ bị đóng băng một thời gian và sau đó sẽ hiển thị một dialog như Figure 11-5. App bị đóng băng vì nó đang cố gắng hiển thị value của counter và cùng thời điểm nó được pause 1s sau khi nó được hiển thị. Để giải quyết vấn đề này, mọt trong những cách giải quyết đó là sử dụng Thread và Runable class như sau: Thangit14.blogspot.com Thangit14@gmail.com 20 Tuy nhiên, đoạn code trên sẽ không làm việc, và chương trình sẽ bị crash nếu bạn chạy thử. Đoạn code đó được đặt trong một Runable block nằm trong một Thread độc lập, và bạn đang cố update UI từ một thread khác. Điều này không được cho phép trong android. Để giải quyết vấn đề, bạn cần sử dụng method post() của View để tạo ra một Runable khác. Khi đó Runable mới này sẽ được chạy trng thread của UI activity. Khi đó chương trình sẽ chạy, nhưng code như vậy làm chương trình khó đọc và quản lý. Cách thư 2 để update UI thừ một thread khác đó là sử dụng Handler class. Một Handler class cho phép bạn gửi và xử lý các message , tương tự như việc sử dụng method post() của View. Thangit14.blogspot.com Thangit14@gmail.com 21 Class Handler không được bàn nhiều trong phần này, các bạn có thể tham khảo ở địa chì: Ngoài ra, để thực hiện công việc trên, bạn chỉ việc đơn giản sử dụng class AsyncTask được hỗ trợ trong Android. Nếu bạn chạy ứng dụng trên, sau đó ấn nút back, tiến trình vẫn chạy tiếp mặc cho activity đã được destroy. Bạn có thể kiểm tra điều đó trong Logcat. Để stop lớp con của AsyncTask, đầu tiên bạn cần lấy về instance của nó. Để stop công việc, bạn gọi method cancel(), đặt trong method onPause. Và dùng method isCancelled() để kiểm tra và dừng vòng lặp. Thangit14.blogspot.com Thangit14@gmail.com 22 Thangit14.blogspot.com Thangit14@gmail.com 23 Tổng kết
File đính kèm:
- Beginning Android for Application - Chapter 11 Android Services.pdf