Android: Service trong Android

Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực
Một Service là một thành phần chạy trong Background để thực hiện các hoạt động mà không cần tương tác với người dùng và nó làm việc ngay cả khi ứng dụng bị hủy.

Về cơ bản, một Service nhận hai trạng thái:

Trạng thái Miêu tả
Started Một Service được bắt đầu (started) khi một Component, chẳng hạn như activity, bắt đầu bằng việc gọi startService(). Khi đã được bắt đầu, một Service có thể chạy ngầm định trong Background, ngay cả khi thành phần mà bắt đầu nó đã bị hủy
Bound Một Service được gắn kết (bound) khi một Component kết nối tới nó bằng việc gọi bindService(). Một bound service cung cấp một giao diện Client-Server cho phép các thành phần tương tác với Service đó, gửi yêu cầu, nhận kết quả, và có thể thực hiện một số tiên trình khác với Interprocess Communication (IPC)

Một Service có các phương thức callback mà bạn có thể triển khai để giám sát các thay đổi trong trạng thái của Service và bạn có thể thực hiện công việc trên các giai đoạn cụ thể. Sơ đồ bên trái minh họa vòng đời của Service khi Service được tạo với phương thức startService() và sơ đồ bên phải minh họa vòng đời Service khi Service được tạo với bindService():

Service trong Android

Để tạo một Service, bạn tạo một lớp Java kế thừa lớp cơ sở Service hoặc một trong các lớp con đang tồn tại của nó. Lớp cơ sở Service định nghĩa các phương thức callback đa dạng và các phương thức quan trọng nhất được liệt kê dưới đây. Bạn không cần triển khai toàn bộ chúng. Điều quan trọng là bạn hiểu từng phương thức và cách triển khai chúng để đảm bảo ứng dụng của bạn vận hành như người dùng mong đợi.

Callback Miêu tả
onStartCommand() Hệ thống gọi phương thức này khi thành phần khác, chẳng hạn một activity, yêu cầu rằng Service bắt đầu, bằng việc gọi startService(). Nếu bạn triển khai phương thức này, thì bạn cũng cần dừng nó khi công việc đã được thực hiện, bằng cách gọi phương thức stopSelf() hoặc stopService()
onBind() Hệ thống gọi phương thức này khi thành phần khác muốn liên kết với Service bằng việc gọi bindService(). Nếu bạn triển khai phương thức này, bạn phải cung cấp một giao diện mà client sử dụng để giao tiếp với Service đó, bằng việc trả về một đối tượng IBinder. Bạn phải luôn luôn triển khai phương thức này, nếu bạn không muốn cho phép liên kết, thì bạn nên trả về null.
onUnbind() Hệ thống gọi phương thức này khi tất cả client đã bị ngắt kết nối với một giao diện nào đó đã được công bố bởi Service này
onRebind() Hệ thống gọi phương thức này khi client mới đã kết nối tới Service này, sau khi nó đã được thông báo trước đó rằng tất cả đã bị ngắt kết nối trong phương thức onUnbind(Intent) của nó .
onCreate() Hệ thống gọi phương thức này khi Service là được tạo đầu tiên bởi sử dụng onStartCommand() hoặconBind(). Lời gọi này là cần thiết để thực hiện cài đặt one-time
onDestroy() Hệ thống gọi phương thức này khi Service không còn được sử dụng nữa và đang bị hủy. Service của bạn nên triển khai phương thức này để xóa bất cứ Resource nào như thread, registered listener, receiver, ...

Ví dụ sau minh họa vòng đời của mỗi phương thức của một Service:

package v1study.com.service;

import android.app.Service;
import android.os.IBinder;
import android.content.Intent;
import android.os.Bundle;

public class HelloService extends Service {

  /**
   * cho biết cách xử lý nếu dịch vụ bị ngừng hoạt động
   */
  int mStartMode;

  /**
   * giao diện cho các máy khách ràng buộc
   */
  IBinder mBinder;

  /**
   * cho biết có nên sử dụng onRebind hay không
   */
  boolean mAllowRebind;

  /**
   * Được gọi khi dịch vụ đang được tạo.
   */
  @Override
  public void onCreate() {

  }

  /**
   * Dịch vụ đang bắt đầu, do một lời gọi đến startService ()
   */
  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    return mStartMode;
  }

  /**
   * Máy khách liên kết với dịch vụ bằng bindService ()
   */
  @Override
  public IBinder onBind(Intent intent) {
    return mBinder;
  }

  /**
   * Được gọi khi tất cả các khách hàng đã hủy liên kết với unbindService ()
   */
  @Override
  public boolean onUnbind(Intent intent) {
    return mAllowRebind;
  }

  /**
   * Được gọi khi một máy khách liên kết với dịch vụ bằng bindService ()
   */
  @Override
  public void onRebind(Intent intent) {

  }

  /**
   * Được gọi khi Dịch vụ không còn được sử dụng và đang bị hủy
   */
  @Override
  public void onDestroy() {

  }
}

Ví dụ

Ví dụ sau sẽ đưa bạn qua các bước đơn giản để minh họa cách tạo Service riêng cho ứng dụng Android của bạn.

Bước Miêu tả
1 Sử dụng Android StudioIDE để tạo một ứng dụng Android và đặt tên nó là ServiceV1Study dưới một package là v1study.com.service
2 Sửa đổi MainActivity.java để thêm phương thức startService() và phương thức stopService()
3 Tạo một file MyService.java mới dưới package là v1study.com.service. File này sẽ có trình triển khai của các phương thức liên quan tới Android Service
4 Định nghĩa Service của bạn trong AndroidManifest.xml bằng cách sử dụng thẻ <service.../> Một ứng dụng có thể có một hoặc nhiều Service mà không có bất cứ hạn chế nào
5 Sửa đổi nội dung mặc định của file res/layout/activity_main.xml để đưa thêm hai button vào
6 Không cần thiết thay đổi bất cứ hằng nào trong res/values/strings.xml file
7 Chạy ứng dụng để chạy Android Emulator và kiểm tra kết quả các thay đổi đã thực hiện trong ứng dụng này.

Sau đây là nội dung của file MainActivity.java:

package v1study.com.service;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
  }

  public void startService(View view) {
    startService(new Intent(getBaseContext(), MyService.class));
  }

  public void stopService(View view) {
    stopService(new Intent(getBaseContext(), MyService.class));
  }
}

Sau đây là nội dung của file MyService.java:

File này có thể có trình triển khai của một hoặc nhiều phương thức được gắn kết với Service tùy theo yêu cầu. Bây giờ, chúng ta đang triển khai chỉ hai phương thức là onStartCommand() và onDestroy():

package v1study.com.service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;

import androidx.annotation.Nullable;

public class MyService extends Service {
  @Nullable
  @Override
  public IBinder onBind(Intent intent) {
    return null;
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    Toast.makeText(this, "Service started", Toast.LENGTH_LONG).show();
    return START_STICKY;
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    Toast.makeText(this, "Service destroyed", Toast.LENGTH_LONG).show();
  }
}

Còn đây là nội dung của file AndroidManifest.xml:

Ở đây, chúng ta đã thêm thẻ <service.../> để bao Service của chúng ta:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:dist="http://schemas.android.com/apk/distribution"
          package="v1study.com.service">

  <dist:module dist:instant="true"/>

  <application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
      <intent-filter>
        <action android:name="android.intent.action.MAIN"/>

        <category android:name="android.intent.category.LAUNCHER"/>
      </intent-filter>
    </activity>
    <service android:name=".MyService"/>
  </application>

</manifest>

Đây sẽ là nội dung của file res/layout/activity_main.xml bao gồm hai nút:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context=".MainActivity">

  <TextView
    android:id="@+id/txtTitle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/servicev1study"
    android:textColor="#8BC34A"
    android:textSize="30sp"
    android:textStyle="bold"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="0.07"/>

  <ImageView
    android:id="@+id/imgView"
    android:layout_width="170dp"
    android:layout_height="170dp"
    android:contentDescription="@string/logo_v1study"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintHorizontal_bias="0.497"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="0.294"
    app:srcCompat="@mipmap/logo_v1_regular"/>

  <Button
    android:id="@+id/btnStartService"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="startService"
    android:text="@string/start_service"
    android:textColor="#8BC34A"
    android:textSize="30sp"
    android:textStyle="bold"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="0.636"/>

  <Button
    android:id="@+id/btnStopService"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="stopService"
    android:text="@string/stop_service"
    android:textColor="#8BC34A"
    android:textSize="30sp"
    android:textStyle="bold"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="0.767"/>

</androidx.constraintlayout.widget.ConstraintLayout>

Và nội dung của res/values/strings.xml để định nghĩa hai hằng mới là:

<resources>
    <string name="app_name">ServiceV1Study</string>
    <string name="start_service">Start Service</string>
    <string name="stop_service">Stop Service</string>
    <string name="servicev1study">ServiceV1Study</string>
    <string name="logo_v1study">Logo V1Study</string>
</resources>

Bây giờ, chạy ứng dụng đã sửa trên. Giả sử bạn đã tạo AVD trong khi cài đặt. Để chạy ứng dụng từ Android Studio, mở activity file của project và nhấn vào biểu tượng Run Service trong Android từ thanh công cụ. Android Studio đặt ứng dụng trên AVD và bắt đầu nó. Nếu mọi thứ là ổn, nó sẽ hiển thị cửa sổ Emulator sau:

Service trong Android

Để bắt đầu dịch vụ, bạn nhấn nút Start Service, việc này sẽ bắt đầu Service và theo như lập trình trong phương thức onStartCommand() thì một thông điệp "Service Started" sẽ xuất hiện ở cuối hình minh họa, như sau:

Service trong Android

Để dừng Service, bạn có thể nhấn nút Stop Service, khi đó sẽ có thông báo như sau:

Stop Service trong Android

» Tiếp: Broadcast Receiver trong Android
« Trước: Activity trong Android
Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực
Copied !!!