Background service là gì

Bài này thuộc phần 11 của 16 phần trong series Tự học lập trình Android trong 24 giờ

Bạn đã bao giờ nghe nói đến service trong Android chưa? Vậy hãy cùng mình tìm hiểuService trong Android nhé!

Hầu như bất kỳ ứng dụng Android nào cũng có thể cần làm một việc cần nhiều tài nguyên hệ thống. Mình ví dụ như ứng dụng nghe nhạc, chuyển đổi file hay download tệp từ internetLúc này bạn cần nghĩ đến việc thực hiện tác vụ đó dưới background thay vì main UI để tránh làm ứng dụng bị treo.

Để thực hiện tác vụ chạy dưới background, bạn có nhiều cách để thực hiện trong Android. Bạn tạo một Thread hoặc Executor trong Activity. Tuy nhiên, nhược điểm của phương pháp này là Thread hay Executor sẽ không tồn tại khi Activity bị destroy.

Một cách khác, đó là sử dụng AsyncTask để xử lý việc này, nhưng nếu ứng dụng của bạn cần Background Thread mà không đính với bất kì Activity nào thì sao? Về bản chất thì AsyncTask vẫn phải tạo trên một Activity nào đó.

Mình ví dụ trường hợp bạn muốn tải một file từ internet và chỉ có cập nhập trạng thái tải trên notification mà không hề có giao diện. Người dùng có thể tắt ứng dụng bất kì lúc nào.

Background service là gì

Trong những trường hợp này, Android Services là giải pháp phù hợp nhất.

1. Service trong Android là gì?

Service là một trong 4 thành phần của ứng dụng Android, có thể thực hiện các tác vụ cần nhiều thời gian và không hề có giao diện người dùng(UI). Từ Activity có thể khởi chạy một Service trong Android và sau đó thể tắt ứng dụng để chuyển sang ứng dụng khác mà Service vẫn tiếp tục công việc mà không bị kill.

Tại sao người ta phải tạo ra Service?

Việc xử lý các tác vụ cần nhiều thời gian trên main UI sẽ làm cho ứng dụng bị treo, giảm trải nghiệm người dùng.Vì vậy, khi cần xử lý bất kì tác vụ cần thời gian thì Service trong Android là một trong số ứng viên có thể xem xét.

  • Service không có giao diện người dùng nào và không thể communicate trực tiếp với activity.
  • Một service có thể chạy dưới background vô thời hạn, ngay cả khi ứng dụng bị tắt theo cách thông thường như ấn phím Back, hay Home, hay tắt trong Recent History
  • Thông thường một service thực hiện một công việc đơn lẻ và tự dừng lại khi nhiệm vụ hoàn thành

Về bản chất thì Service vẫn chạy trên main thread của ứng dụng( mỗi ứng dụng khi chạy, Android sẽ tạo một thread cho ứng dụng đó). Nó không tạo ra Thread riêng độc lập với ứng dụng. Nếu service của bạn mà bị treo, nó có thể khiến ứng dụng bị treo (lỗi ANR). Để khắc phục điều này thì bạn nên tạo một Thread( như AsyncTask) bên trong Service.

  • Dành riêng cho bạn: Tìm hiểu cách tạo và sử dụng Activity trong Android

2. Các loại service trong Android: Bound và Unbound

#Bound Servicetrong Android

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().

Một component(ví dụ như Activity chẳng hạn) gọi Service bằng phương thức bindService(). Activity sẽ liên kết với Service theo dạng client service. Lúc này Activity có tương tác với Service để gửi và nhận kết quả từ Service.

Ví dụ, mình tạo một Service có nhiệm vụ cập nhật thời tiết. Activity sẽ bind vào Service và yêu cầu Service cập nhật dữ liệu thời tiết bất kì lúc nào, sau đó trả kết quả cho activity hiển thị cho người dùng.

#Unbound Servicetrong Android

Trường hợp này thì ngược lại với bound service, nghĩa là một Activity có thể khởi chạy service và không quan tâm Service đó chạy như nào, bao giờ thì kết thúc.

Ví dụ, từ activity bắt đầu một service để play bài hát, và service sẻ tiếp tục phát nhạc dưới background vô thời gian kể cả activity đã bị destroy.

3. Vòng đời của Service trong Android

Cũng giống như Activity, Service trong android cũng có vòng đời từ lúc bắt đầu cho đến khi destroy. Để hiểu rõ, các bạn xem hình bên dưới (đọc ngay về activity Lifecycle )

Background service là gì

Mình sẽ giải thích từng hàm trong vòng đời của Service

onStartCommand()

Hàm này được gọi khi service bắt đầu bằng cách gọi hàm startService(). Khi hàm này thực hiện, service được khởi động và có thể chạy nền background vô thời hạn. Để có thể hủy service thì chỉ có 2 cách:

  1. Bạn tự gọi hàmstopSelf() hoặc stopService().
  2. May rủi chờ đến khi hệ thống Android cần tài nguyên cho ứng dụng khác thì sẽ kill service này .

onBind()

Hàm này chỉ được thực hiện nếu service là bound service. Bạn phải cung cấp một giao diện(interface) mà client sử dụng để giao tiếp với Service bằng cách trả về một IBinder. Hàm này được gọi bất kể khi nào có một thành phần nào đó muốn bind vào service

onCreate()

Đây là hàm được khi service được khởi tạo và chỉ được gọi duy nhất một lần

onDestroy()

Tương tự như Activity thì hàm này được khi service bị hủy(có thể do bạn gọi hàmstopService()hay do hệ thống tự hủy) để giải phóng tài nguyên.

4. Tạo service trong Android

Để các bạn có thể hiểu rõ hơn về cơ chế hoạt động của Service, mình sẽ cùng nhau viết một example sử dụng Service

Sau nhiều bài sử dụng Kotlin, lần này mình sẽ hoài cổ một chút. Ví dụ này sẽ sử dụng ngôn ngữ Java

#Tạo mới Service class

Đầu tiên, tạo một Service có tên là HelloService và override các hàm onStartCommand(), onBind(),onCreate()vàonDestroy()như bên dưới

package com.javatechig.serviceexample; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; public class HelloService extends Service { private static final String TAG = "HelloService"; private boolean isRunning = false; @Override public void onCreate() { Log.i(TAG, "Service onCreate"); isRunning = true; } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "Service onStartCommand"); //Creating new thread for my service //Always write your long running tasks in a separate thread, to avoid ANR new Thread(new Runnable() { @Override public void run() { //Your logic that service will perform will be placed here //In this example we are just looping and waits for 1000 milliseconds in each loop. for (int i = 0; i < 5; i++) { try { Thread.sleep(1000); } catch (Exception e) { } if(isRunning){ Log.i(TAG, "Service running"); } } //Stop service once it finishes its task stopSelf(); } }).start(); return Service.START_STICKY; } @Override public IBinder onBind(Intent arg0) { Log.i(TAG, "Service onBind"); return null; } @Override public void onDestroy() { isRunning = false; Log.i(TAG, "Service onDestroy"); } }

#Khai báo Service Manifest

Giống như Activity, Service trong android cũng cần phải khai báo trong Manifest file.

Bạn có thể thiết lập một service chỉ có sẵn cho ứng dụng của bạn bằng cách khai báo thuộc tínhandroid: exportedvà đặt nó thành false. Điều này có hiệu quả ngăn các ứng dụng khác bắt đầu service của bạn một cách không kiểm soát

#Bắt đầu một Service Android

Bạn có thể bắt đầu một service từ một Activity hoặc Broadcast Receiver bằng cách gọi hàm startService().

Trong ví dụ này, chúng ta sẽ bắt đầu service bằng cách gọi phương thức startService()khi nút Start Service

Intent intent = new Intent(this, HelloService.class); startService(intent);

Và đây là kết quả

Background service là gì

Đây chỉ là một ví dụ rất đơn giản để các bạn có thể hình dung cách thức hoạt động của Service. Toàn bộ source code ví dụ minh họa các bạn download link bên dưới nhé

Download source code

Bài viết tiếp theo, mình sẽ hướng dẫn các bạn sẽ sử Broadcast Receiver bộ phận truyền thông của Android. Mình rất mong nhận được ý kiến đóng góp của các bạn để khóa học lập trình android này được hoàn thiện hơn.

Đừng quên like và chia sẻ nhé

Đọc thêm:Lời khuyên dùng Android Thread cho tác vụ Network!!

Xem tiếp các bài trong Series
Phần trước: Xử lý sự kiện trong Android (Event Handling)Phần kế tiếp: Tất tần tật về Broadcast Receiver trong Android
Background service là gì