Bài viết được sự cho phép của tác giả Sơn Dương
Bạn đã bao giờ nghe nói đến service trong Android chưa? Vậy hãy cùng mình tìm hiểu Service 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ừ internet… Lú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.
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.
2. Các loại service trong Android: Bound và Unbound
#Bound Service trong 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 Service trong 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.
Tham khảo việc làm Android Developer Hồ Chí Minh tại TopDev
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 )
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:
- Bạn tự gọi hàm stopSelf() hoặc stopService().
- 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àm stopService()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ính android: 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
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.javatechig.serviceexample" > <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".HelloActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!--Service declared in manifest --> <service android:name=".HelloService" android:exported="false"/> </application> </manifest>
#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ả
Đâ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é!
Bài viết gốc được đăng tải tại vntalking.com
Xem thêm:
- Debug trong Android Studio – Đây là kỹ năng cần phải giỏi
- Tạo Splash Screen cho Android như thế nào là “chuẩn” nhất?
- Cách Thiết Lập Máy Ảo, Máy Thật & Khởi Chạy Ứng Dụng Trong Android
Tìm việc làm IT mọi cấp độ tại TopDev