Android 简明教程

Android - Services

Sr.No.

State & Description

1

Started 当应用程序组件(如活动)通过调用 startService() 来启动 started 时,将调用服务。一旦启动,服务可以在后台无限期地运行,即使启动它的组件已销毁。

2

Bound 当应用程序组件通过调用 bindService() 来绑定 bound 时,将调用服务。已绑定的服务提供一个客户端-服务器接口,允许组件与服务交互、发送请求、获取结果,甚至通过进程间通信 (IPC) 在进程之间进行交互。

服务拥有生命周期回调方法,你可实现这些回调方法来监视服务状态的变化,并可在适当的阶段执行工作。下图左侧显示了通过 startService() 来创建服务时的生命周期,右图显示了通过 bindService() 来创建服务时的生命周期:(图像由 android.com 提供)

services

若要创建服务,可创建一个 Java 类,它扩展 Service 基类或其现有子类。 Service 基类定义了各种回调方法,其中最重要的方法如下。你无需实现所有回调方法。但是,理解每种回调方法并实现那些确保你的应用程序符合用户期望的方法非常重要。

Sr.No.

Callback & Description

1

onStartCommand() 当另一个组件(如活动)通过调用 startService() 请求启动服务时,系统将调用此方法。如实现此方法,你有责任在服务工作完成时通过调用 stopSelf() 或 stopService() 方法来停止该服务。

2

onBind() 当另一个组件希望通过调用 bindService() 与服务进行绑定时,系统将调用此方法。如实现此方法,你必须提供一个供客户端用于与服务进行通信的接口,方法是返回 IBinder 对象。你必须始终实现此方法,但如果你不想允许绑定,则应返回 null。

3

onUnbind() 当所有客户端都已断开与服务所发布的特定接口的连接时,系统将调用此方法。

4

onRebind() 当新客户端连接到服务(此前已通知它服务中所有客户端均已断开连接)后,系统将调用此方法。

5

onCreate() 当使用 onStartCommand() 或 onBind() 首次创建服务时,系统将调用此方法。此调用需要执行一次性设置。

6

onDestroy() 当不再使用服务且服务正在销毁时,系统将调用此方法。你的服务应实现此方法来清理任何资源,如线程、已注册的侦听器、接收器等。

以下框架服务演示了每个生命周期方法 −

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

   }
}

Example

此示例将通过简单的步骤向你展示如何创建你自己的 Android 服务。按照以下步骤修改我们在 Hello World 示例一章中创建的 Android 应用程序 −

Step

Description

1

你将使用 Android StudioIDE 创建 Android 应用程序,并将其命名为 My Application,其包路径为 com.example.tutorialspoint7.myapplication,如 Hello World 示例一章中所述。

2

修改主活动文件 MainActivity.java 以添加 startService() 和 stopService() 方法。

3

在 com.example.My Application 包下方创建一个新的 java 文件 MyService.java。此文件将实现与 Android 服务相关的各种方法。

4

使用 <service…​/> 标记在 AndroidManifest.xml 文件中定义你的服务。一个应用程序在不受任何限制的情况下可包含一个或多个服务。

5

修改 res/layout/activity_main.xml 文件的默认内容以包含线性布局中的两个按钮。

6

无需更改 res/values/strings.xml 文件中的任何常量。Android Studio 会处理字符串值

7

运行应用,以启动 Android 模拟器,并验证应用中已执行的更改。

下面是修改后的主活动文件 MainActivity.java 的内容。此文件可包括每个基本生命周期方法。我们已添加了 startService() 和 stopService() 方法来启动和停止服务。

package com.example.tutorialspoint7.myapplication;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.View;

public class MainActivity extends Activity {
   String msg = "Android : ";

   /** Called when the activity is first created. */
   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      Log.d(msg, "The onCreate() event");
   }

   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));
   }
}

下面是 MyService.java 的内容。此文件可根据要求实现与基于服务的相关的一个或多个方法。目前我们仅实现两种方法 onStartCommand() 和 onDestroy() −

package com.example.tutorialspoint7.myapplication;

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

/**
   * Created by TutorialsPoint7 on 8/23/2016.
*/

public class MyService extends Service {
   @Nullable
   @Override
   public IBinder onBind(Intent intent) {
      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();
   }
}

以下是修改后的 AndroidManifest.xml 文件的内容。我们在此处添加了 <service…​/> 标记以包含我们的服务 −

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.example.tutorialspoint7.myapplication">

   <application
      android:allowBackup="true"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name"
      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>

以下是 res/layout/activity_main.xml 文件的内容,用于包含两个按钮 −

<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>

让我们尝试运行我们刚刚修改过的 Hello World! 应用程序。我假设你在进行环境设置时已创建了 AVD 。要从 Android Studio 运行该应用程序,请打开项目的一个活动文件,然后单击工具栏中的运行图标。Android Studio 会将该应用程序安装到你的 AVD 并启动它,如果你的设置和应用程序一切正常,它将显示以下模拟器窗口 −

services1

现在要启动你的服务,让我们单击 Start Service 按钮,这将启动服务,并且根据我们在 onStartCommand() 方法中编程,一条消息服务已启动将显示在模拟器的底部,如下所示 −

services2

要停止服务,你可以单击停止服务按钮。