Bài 6: Service trong android

Heellloo mọi người! Mình là Cheng, hôm nay mình sẽ học tiếp đến bài 6 trong loạt series lập trình android nâng cao tại Blog Thangcoder.Hôm nay chúng ta sẽ đi tìm hiểu về một kiến thức khá là khó trong lập trình Android nâng câo đó là Service.

Đây là một Component thứ 3 trong Android đó các bạn.chúng ta đã học qua được 2 component rồi đó là ActivityBroadcast Receiver.Nói ở phần toàn kiến thức mới và gay go hơn nên mọi người chịu khó đọc kĩ bài viết và xem video nhé.Bài viết mình sẽ cố viết thật chi tiết nhất có thể để mọi người đọc và hiểu được, chứ mình đã lỡ bỏ thời gian ra rồi thì cũng mong đem lại gì đó cho mọi người không thì tội nghiệp mình quá :'(.

Nói về Service thì thật sự đây là một thành phần khó hiểu và gay go nhất trong 4 component theo ý kiến của mình.Thậm chí tới bây giờ mình còn chưa hiểu hết và thực hành với service nhiều nữa.Thế nên ở bài này mình sẽ đi nói 1 cách theo kiến thức mình biết thôi nhé các bạn chứ đào sâu vào thì mình vẫn chưa đủ kinh nghiệm và kiến thức…thật dị.

Tiếp tục như những bài trước chúng ta lại đi trả lời các câu hỏi sau: What? Why? When? How?

Service trong android là gì?

Là một component chính trong android với nhiệm vụ là thực hiện các tác vụ ngầm bên dưới hệ điều hành mà không cần người dùng phải tương tác và thậm chí nó vẫn hoạt động khi mà thành phần tạo ra nó bị huỷ đi và cả khi ứng dụng bị tắt hoàn toàn.

Một Service sẽ có một vòng đời riêng của nó từ lúc tạo ra cho đến khi bị huỷ đi, và thông thường Service sẽ có 2 loại chính tương ứng với 2 cách gọi service khác nhau mà hôm nay chúng ta sẽ đi tìm hiểu đó là Started Service (không ràng buộc) và Bound Service (ràng buộc).

 

Service trong android là gì?

Service trong android là gì?

Tại sao lại sử dụng Service?

Y chang cái tên của nó thôi, mục đích là để chạy ngầm cách dịch vụ bên trên hệ điều hành mà không cần người dùng phải tương tác và thậm chí là chạy ngầm ngay khi cả ứng dụng bị tắt đi.

Một ví dụ kinh điển khi các bạn sử dụng facebook , zalo như sau:

Khi bạn tắt ứng dụng facebook, zalo đi mà có người khác gửi tin nhắn đến thì nó có show lên một notify thông báo cho bạn, ở đây không nhất thiết phải dùng service để làm điều này nhưng một số trường hợp tưng tự có thể áp dụng.

Và một ví dụ tương tự nữa:

Khi các bạn đã tắt ứng dụng facebook, zalo đi và tắt luôn mạng internet , wifi… đi rồi.Khi bạn vừa bật 3G hay Wifi lên thì lập tức các thông báo của Facebook nhắn về quá trời.Thì ở đây ứng dụng đã kết hợp giữa broadcast receiver với Service để làm điều này.Broadcast lắng nghe sự kiện bật mạng , khi lắng nghe được rồi sẽ dùng start 1 service để lấy dữ liệu thông báo (tin nhắn…) và notify lên thiết bị.

Đó, qua nhưng ví dụ thì mình muốn các bạn hiểu những công dụng của service chứ mình sẽ không giải thích gì nhiều nữa.Khi sử dụng một app nào bạn thấy những tính năng hay của app đó thì cứ đặt câu hỏi cho mình là nó đã dùng kĩ thuật gì để làm những tính năng đó? Từ đó bạn sẽ học được nhiều cái thú vị đó.

Khi nào thì sử dụng Service?

Câu hỏi này nó giống như tại sao lại sử dụng service vậy á ha. :D… Để biết khi nào bạn sử dụng service thì chí có một câu trả lời duy nhất đó là khi làm những kĩ thuật mà chỉ service mới làm được thì chúng ta sử dụng nó thôi.

Có những yêu cầu đưa ra cho ứng dụng của bạn, mà chỉ service mới làm được thì ta sử dụng nó thôi, đơn giản là những tiến trình cần chạy ngầm cả khi ứng dụng tắt đi thì chúng ta sẽ sử dụng service.Service nó khác nhiều so với broadcast nhé các bạn, vì 2 thằng đều có thể chạy ngầm được nên sợ các bạn sẽ hiểu nhầm.

Sử dụng Service như thế nào?

Nãy ở trên mình có đã 2 kiểu service nên ở đây mình sẽ trình bày sơ qua về 2 kiểu này cho các bạn xem ha, chi tiết hơn thì mình sẽ nó trong video nữa chính vì vậy bạn đọc bài viết thì kết hợp với video, còn xem video thì kết hợp với bài viết bởi tại có khi quay video mình lại bỏ sót những vấn đề mà bài viết mình lại có ghi :D.

Tuỳ vào mục đích của bạn mà bạn sẽ chọn loại service cho phù hợp, cái này mình sẽ nó rõ trong video luôn nhé.

Start Service

Vòng đời Start Service

Vòng đời của start service (Bound service)

Vòng đời của start service (Bound service)

Với loại service này bạn sẽ start nó bằng cách gọi phương thức startService(), sau đó phương thức onCreate() sẽ được gọi, các bạn nhớ phương thức này tương tự như onCreate() ở activity vậy.Nó chỉ gọi 1 lần duy nhất khi khởi tạo service thôi , nếu như bạn start lại lần nữa thì nó sẽ không được gọi nữa.

Sau khi chạy vào hàm onCreate() được gọi thì nó sẽ chạy vào hàm onStartCommand() để thực hiện những hành động ở đây.Bạn muốn service làm gì thì hãy xử lí ở đây nhé, ví dụ play một bài hát chẳng hạn.Ở hàm này bạn sẽ return về một kiểu int ứng với là các 1 trong các đối tượng sau:

  • START_STICKY bảo với hệ điều hành rằng cần tạo lại service khi có đủ bộ nhớ và call lại onStartCommand() với intent là null (thường áp dung cho các service không truyền dữ liệu gì qua intent).
  • START_NOT_STICKY: chỉ áp dụng khi Service bị huỷ khi chưa thực hiện xong do điện thoại hết bộ nhớ hay vì một lí do nào đó thì lại bảo với Hệ điều hành rằng không cần tạo lại service.

Chú ý: 2 trường hợp trên chỉ thực hiện khi Service bị huỷ khi chưa thực hiện xong do điện thoại hết bộ nhớ hay vì một lí do nào đó.

  • Ngoài ra còn có START_REDELIVER_INTENT để bảo với hệ điều hành rằng sẽ tạo lại service với intent như cũ đến onStartCommand().

*** Note: To address this, in Android 2.0 Service.onStart() as been deprecated (though still exists and operates as it used to in previous versions of the platform). It is replaced with a new Service.onStartCommand() callback that allows the service to better control how the system should manage it. (Trước đây từ API 5 trở xuống thì sử dụng hàm onStart() nhưng hiện nay đã bị thay thế bởi onStartCommand() rồi nhé mọi người).

Phần trên khá là khó hiểu ngay cả bản thân mình cũng vậy, các bạn đọc thêm ở đây nhé:

https://android-developers.googleblog.com/2010/02/service-api-changes-starting-with.html

Để kết thúc service loại này chúng ta sẽ gọi phương thức stopService(), lúc này nó sẽ chạy vào hàm onDestroy() và tới đây serivice hoàn toàn bị phá huỷ.Ngoài ra bạn có thể gọi phương thức stopSelf(), để cho nó huỷ bất kì lúc nào bạn muốn ví dụ như khi service thực hiện xong.Thông thường stopService() được huỷ ở trong onDestroy() của activity để khi thoát ứng dụng nó sẽ huỷ luôn còn stopSelf() thì ở nơi nào bạn muốn huỷ thì huỷ thôi.

Xem thêm vòng đời của Service này tại đây nhé mọi,  sẽ rất dễ hiểu đó.

Thực hành StartService

Đầu tiên khi sử dụng service thì có một việc quan trọng đầu tiên đó là việc bạn phải khai báo nó trong AndroidManifest trước, tương tự như việc bạn khai báo Activity vậy đó mà chúng ta đã học ở android căn bản rồi.

Vậy bây giờ mình sẽ tạo một Class Service có tên là StartService, chính vì vậy mà mình sẽ khai báo trong AndroidManifest như sau:


Bạn chú ý ở dòng:


Chỉ cần như vậy là xong việc khai báo rồi, bây giờ chúng ta sẽ đi khởi tạo cái class StartService này nhé, code mình sẽ tóm gọn như sau:


Bạn nhìn bên trên sẽ thấy class StartService extends từ thằng Service chính vì vậy nó sẽ implement các phương thức như ở trên, thực ra nếu bạn không @Override các phước đó cũng không sao, nhưng nếu không làm vậy thì service đâu làm được gì đâu vì chúng ta sẽ xử lí code logic trong đó mà.

Ở trên bạn sẽ thấy các phương thức như sau:


Đây là phc thức bắt buộc phải ghi đè  và nó thuộc kiểu Bound Service ở phía dưới nên chúng ta sẽ tìm hiểu ở phần dưới nhé, phương thức này không có tác dụng ở Start Service.


Đây là phương thức khởi tạo service thì được gọi, y chang onCreate() ở Activity vậy, nó chỉ được gọi duy nhất một lần trong service đó khởi tạo mà chơi bị Destroy, nếu start lại lần nữa thì nó sẽ không gọi hàm này nữa nhé các bạn mà sẽ vào hàm bên dưới đây.


Đây là hàm thường dùng để xử lý logic cho Service, sau khi onCreate() được gọi thì tiếp theo phương thức này sẽ được gọi sau đó.Nếu như bạn start service 1 lần nữa thì phương thức này sẽ được gọi lại chứ không phải khởi tạo lại 1 service mới đâu nhé.Nghĩa là với 1 service nó sẽ được tạo 1 lần duy nhất nếu như bạn start nhiêu lần thì nó cũng chỉ có 1 service thôi.

Nó chỉ được khởi tạo lại ghi các bạn gọi hàm stopService() thôi, tí nữa mình sẽ nói phía dưới.

Ở đoạn code trên bạn thấy nó return về START_STICKY không nhỉ? Ở đây có nghĩa là service đó nếu như bị tắt đột ngột sẽ được tự động khởi tạo lại nhé các bạn, ở phần vòng đời service mình nó rồi đó các bạn,bạn quay lên xem sẽ rõ chỗ này và kèm theo xem ở video bên dưới nữa nhé.


Và đây là hàm được gọi khi service bị huỷ do người dùng gọi phương thức stopService() hoặc hàm  stopSelf() (khác nhau như nào xem ở video), lúc này phương thức trên sẽ được gọi.Và tới đây là service đã bị dừng hoàn toàn lại rồi nha các bạn, nó sẽ không khởi tạo lại cho đến khi gọi startService đâu.

Và đây là đoạn code start và stop service ở Activity nhé.


*** Note

Khi có một context nào đó gọi startService() để start service mong muốn. Nếu service đó chưa được tạo thì sẽ gọi onCreate() rồi gọi tiếp onStartCommand() và khi đó service chạy nền bên dưới.

Nếu sau đó lại có một context muốn start service này mà service đã đang chạy, chỉ có  phương thứconStartCommand() của service được gọi.

Dù service có được gọi start bao nhiêu lần thì cũng chỉ có 1 instance của service và chỉ cần gọi stopService() một lần để kết thúc service.

 

Bound Service

Vòng đời

Vòng đời Bound Service

Vòng đời Bound Service

Với loại service này thì bạn sẽ không gọi start Service bằng startService(), thay vào đó là sẽ gọi phương thức bindService(), lúc này nó sẽ vẫn chạy vào phương thức onCreate() tương tự như cách 1 luôn không có gì khác cả nhé các bạn.

Sau đó phương thức onBind() sẽ được gọi thay vì cách 1 là phương thức onStartCommand(), phương thức này sẽ trả về môt IBinder (sẽ nói rõ hơn trong video nhé các bạn, cái này mình cũng chẳng hiểu cho mấy :D).

Để huỷ bound servive này chúng ta sẽ gọi phương thức unbindService()lúc này hàm onUnbind() sẽ được gọi và tiếp theo đó là phương thức onDestroy() cũng sẽ được gọi theo luôn.Lúc này bạn đã huỷ kết nối với service và service sẽ không còn chạy nữa khi đã vào tới onDestroy().

Chi tiết hơn mình sẽ nói rõ ở phần video nhé các bạn, mình thấy thằng này khá là gay go nên mình sẽ nói chi tiết ở video chứ ghi ra thì không biết diễn tả sao cho đủ.

Xem thêm vòng đời của Service này tại đây nhé mọi,  sẽ rất dễ hiểu đó.

Thực hành BoundService

Đối với kiểu Start thì service chạy ngầm bên dưới background và có thể không bị huỷ nếu như bạn không chủ động stop nó, còn với loại này thì nó có thể bị huỷ nếu như thành phần gọi nó bị huỷ.Và ngoài ra bound servie sẽ cung cấp cho bạn 1 interface (giao diện), ở đây không phải là giao diện tương tác mà là interface nhé các bạn. Ở đây là 1 IBinder, bạn có thể sử dụng nó để tưởng tác với service.

Và dưới đây là lớp BoundService để các bạn dễ hình dung hơn nhé.


Ở đây bạn cũng extends từ class Service, tuy nhiên không giống như start Service chúng ta sẽ đi @Override các phương thức khác một tí bao gồm có thêm các phương thức như: onBind(), onRebind(),  onUnbind()…

Khi bạn start service này thì nó cũng sẽ vào hàm onCreate rồi sau đó xuống hàm onBind để trả về một interface là IBinder, đây là cái mấu chốt để các bạn có thể tương tác với Bound Service đó.

Mình sẽ không mô tả chi tiết về từng dòng code vì nó rất khó nói và hiểu nên mình sẽ nói chi tiết hơn trong video nhé các bạn.

Và đây là class MainActivity để start bound service:


Ở trên mình đã gọi phương thức bindService() để start service và gọi unBindService() để stop nó, 2 phương thức tương tự như startService() với stopService() của loại Start Service vậy.

Khi start loại service này bạn sẽ truyền vào một cái ServiceConnection để mục đích là nhận về cái Inteface IBinder, mục đích là có thể gọi được cái phương thức của class BoundService ở trên, chính vì vậy người ta nói bound Service là loại service có có giao diện tương tác với service.

Download source code

Bài viết mình chỉ dừng lại ở đây thôi vì chi tiết mình sẽ nói trong video nhé các bạn.

Bài 6: Service trong android
5 (100%) 1 vote

One Response

  1. minh dai May 31, 2018

Add Comment

*