Android – Dịch vụ (Services)



Service là một Component chạy ở nền ứng dụng để thực thị các thao tác chạy trong thời gian dài và không cần tương tác với người dùng. Component này thậm chí vẫn hoạt động khi ứng dụng bị triệt tiêu. Một Service có thể có 2 trạng thái (State):

Trạng thái (State) Mô tả
Đã khởi tạo (Started) Một Service được khởi tạo, nói cách khác nó ở trong trạng thái Started, khi một Component của ứng dụng, ví dụ như một Activity nào đó gọi phương thức startService(). Sau khi được khởi tạo, một Service có thể chạy ở nền ứng dụng vô thời hạn, ngay cả khi ứng dụng bị triệt tiêu.
Được chỉ định (Bound) Một Service được chỉ định, nói cách khác nó ở trong trạng thái Bound, khi một Activity chỉ định nó bằng cách gọi phương thức bindService(). Một Bound Service cho phép các Component tương tác với Service, gửi yêu cầu, nhận kết quả và thậm chí liên lạc giữa các process của một ứng dụng hoặc của các ứng dụng khác nhau.

Một Service có các phương thức callback trong vòng đời của nó. Lập trình viên có thể viết lại những phương thức đó để điều khiển việc thay đổi trạng thái của Service. Trong sơ đồ bên trái biểu diễn vòng đời Service được khởi tạo bởi phương thức startService(). Sơ đồ bên phải biểu diễn vòng đời của Service khi nó được chỉ định với phương thức bindService():

Android Service lifecycle

Để tạo một Service, bạn tạo một lớp Java, kế thừa (extend) từ lớp Service hoặc một lớp con nào đó của lớp Service. Lớp Service định nghĩa nhiều phương thức callback mà bạn có thể viết lại theo ý muốn. Bạn không cần viết lại tất cả các phương thức callback. Dưới đây là một vài phương thức được sử dụng thường xuyên nhất:

Tên phương thức callback Mô tả
onStartCommand() Hệ thống gọi phương thức này khi một Component, ví dụ như một Activity, yêu cầu khởi động Service bằng cách gọi phương thức startService(). Nếu bạn viết lại phương thức này, bạn phải tắt Service này khi đã sử dụng xong bằng cách gọi stopSelf() hoặc stopService().
onBind() Hệ thống gọi phương thức này khi một Component muốn chỉ định Service này bằng cách gọi bindService(). Nếu bạn viết lại phương thức này, bạn phải cung cấp một giao diện cho phép client dùng để liên lạc với Service bằng cách trả về một đối tượng IBinder. Bạn phải luôn luôn viết lại phương thức này. Trong trường hợp bạn không cho phép chỉ định, hãy trả về giá trị null khi viết lại.
onUnbind() Hệ thống gọi phương thức này khi tất cả các client ngừng kết nối khỏi một giao diện được tạo bởi Service.
onRebind() Hệ thống gọi phương thức này khi client mới kết nối với Service, sau khi nó đã được thông báo là tất cả các client khác đã ngừng kết nối.
onCreate() Hệ thống gọi phương thức này khi Service được khởi tạo lần đầu tiên bằng cách dùng phương thức onStartCommand() hoặc onBind(). Việc gọi hàm này là cần thiết để thực hiện các thiết lập ban đầu.
onDestroy() Hệ thống gọi phương thức này khi Service không còn được dùng nữa và nó bị triệt tiêu. Bạn nên viết lại phương thức này để xóa các tài nguyên như threads, registered listeners, receivers…

Skeleton Service trong đoạn code dưới đây thể hiện từng phương thức trong vòng đời của Service:

package com.tutorialspoint;

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

public class HelloService extends Service {
   
   /** indicates how to behave if the service is killed */
   int mStartMode;
   
   /** interface for clients that bind */
   IBinder mBinder;     
   
   /** indicates whether onRebind should be used */
   boolean mAllowRebind;

   /** Called when the service is being created. */
   @Override
   public void onCreate() {
     
   }

   /** The service is starting, due to a call to startService() */
   @Override
   public int onStartCommand(Intent intent, int flags, int startId) {
      return mStartMode;
   }

   /** A client is binding to the service with bindService() */
   @Override
   public IBinder onBind(Intent intent) {
      return mBinder;
   }

   /** Called when all clients have unbound with unbindService() */
   @Override
   public boolean onUnbind(Intent intent) {
      return mAllowRebind;
   }

   /** Called when a client is binding to the service with bindService()*/
   @Override
   public void onRebind(Intent intent) {

   }

   /** Called when The service is no longer used and is being destroyed */
   @Override
   public void onDestroy() {

   }
}

Ví dụ

Ví dụ sau đây sẽ hướng dẫn bạn những bước cơ bản để tạo một Service trong ứng dụng Android. Làm theo các bước trong bảng bên dưới:

Bước Mô tảDescription
1 Tạo một Project ứng dụng Android và đặt tên nó là My Application, tên  package là com.example.My Application.
2 Sửa tập tin Activity chính MainActivity.java  bằng cách thêm 2 phương thức startService()  và stopService().
3 Tạo 1 tập tin Java mới tên là MyService.java nằm trong package com.example.My Application. Tập tin này sẽ chứa các phương thức được viết lại của Service của bạn.
4 Khai báo Service mới trong AndroidManifest.xml file bằng cách thêm thẻ <service…/> . Một ứng dụng có thể có một hoặc nhiều ứng dụng.
5 Chỉnh sửa nội dung mặc định của tập tin res/layout/activity_main.xml  để thêm 2 nút bấm vào bố cục linear (linear layout).
6 Không cần thay đổi giá trị constants trong res/values/strings.xml .
7 Chạy ứng dụng để chạy Android emulator và xem thay đổi của ứng dụng.

Bên dưới đây là nội dung của tập tin src/com.example.My Application/MainActivity.java đã được chỉnh sửa. Tập tin này chứa những phương thức cơ bản của Activity. Chúng ta thêm startService() và stopService() để khởi động và tắt Service.

package com.example.My Application;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.content.Intent;
import android.view.View;

public class MainActivity extends Activity {

   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
   }
   
   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
      getMenuInflater().inflate(R.menu.activity_main, menu);
      return true;
   }

   // Method to start the service
   public void startService(View view) {
      startService(new Intent(getBaseContext(), MyService.class));
   }

   // Method to stop the service
   public void stopService(View view) {
      stopService(new Intent(getBaseContext(), MyService.class));
   }
}

Bên dưới đây là nội dung của tập tin src/com.example.My Application/MyService.java. Tập tin này chứa các phương thức được viết lại tùy theo yêu cầu. Ở đây chúng ta chỉ viết lại 2 phương thức onStartCommand() và onDestroy() :

package com.example.My Application;

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

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

   @Override
   public int onStartCommand(Intent intent, int flags, int startId) {
      // Let it continue running until it is stopped.
      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();
   }
}

Toast là một loại thông báo ngắn xuất hiện trên màn hình. Trong ví dụ này ta dùng Toast.makeText() để thông báo ra màn hình dòng chữ “Service Start” và “Service Destroyed”. Để sử dụng Toast bạn phải import package android.widget.toast ở đầu tập tin.

Bên dưới đây là nội dung đã chỉnh sửa của tập tin AndroidManifest.xml file. Ở đây chúng ta thêm thẻ <service…/> để thêm Service mới:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.example.MyApplication"
   android:versionCode="1"
   android:versionName="1.0" >
   
   <uses-sdk
      android:minSdkVersion="13"
      android:targetSdkVersion="22" />
   
   <application
       android:icon="@drawable/ic_launcher"
       android:label="@string/app_name"
       android:theme="@style/AppTheme" >
       
       <activity
          android:name=".MainActivity"
          android:label="@string/title_activity_main" >
       
          <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>

Bên dưới đây là nội dung của tập tin res/layout/activity_main.xml, trong đó chúng ta thêm 2 nút bấm vào giao diện:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
   android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
   android:paddingRight="@dimen/activity_horizontal_margin"
   android:paddingTop="@dimen/activity_vertical_margin"
   android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
   
   <TextView
      android:id="@+id/textView1"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Example of services"
      android:layout_alignParentTop="true"
      android:layout_centerHorizontal="true"
      android:textSize="30dp" />
      
      <TextView
         android:id="@+id/textView2"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="Tutorials point "
         android:textColor="#ff87ff09"
         android:textSize="30dp"
         android:layout_above="@+id/imageButton"
         android:layout_centerHorizontal="true"
         android:layout_marginBottom="40dp" />

    <ImageButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/imageButton"
        android:src="@drawable/abc"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button2"
        android:text="Start Services"
        android:onClick="startService"
        android:layout_below="@+id/imageButton"
        android:layout_centerHorizontal="true" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Stop Services"
        android:id="@+id/button"
        android:onClick="stopService"
        android:layout_below="@+id/button2"
        android:layout_alignLeft="@+id/button2"
        android:layout_alignStart="@+id/button2"
        android:layout_alignRight="@+id/button2"
        android:layout_alignEnd="@+id/button2" />

</RelativeLayout>

Bên dưới đây là nội dung của tập tin res/values/strings.xml để định nghĩa 2 constant:

<resources>
    <string name="app_name">My Application</string>
    <string name="menu_settings">Settings</string>
    <string name="title_activity_main">MainActivity</string>
</resources>

Hãy thử chạy ứng dụng vừa tạo và chỉnh sửa code. Bạn sẽ thấy Emulator hiện lên như sau:

Android Service Demo

Bây giờ hãy bấm vào nút Start Service, nó sẽ chạy Service theo cách mà chúng ta muốn và đã code trong phương thức onStartCommand() , dòng chữ Service Started sẽ xuất hiện ở bên dưới 2 nút như trong ảnh bên dưới:

Android Service Start

Để tắt Service, bạn bấm nút Stop Service.

897 Total Views 2 Views Today