Android(安卓)服务

服务(service)是一个在后台运行的组件,用于执行长时间运行的操作,而无需与用户交互,即使应用程序被破坏,它也能正常工作。

服务基本上可以有两种状态:

编号状态 & 描述
1

Started(启动)

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

2

Bound(绑定)

当应用程序组件通过调用 bindService() 绑定 到服务时,服务即被绑定绑定服务提供了一个客户端-服务器接口,支持组件与服务交互、发送请求、获取结果,甚至通过进程间通信(IPC)跨进程执行这些操作

服务具有生命周期回调方法,您可以实现这些方法来监视服务状态的更改,并可以在适当的阶段执行工作。左边的下图显示了使用 startService() 创建服务时的生命周期,右边的图显示了使用 bindService() 建立服务时的寿命周期:

要创建服务,您需要创建一个 Java 类来扩展服务基类或其现有子类之一。Service 基类定义了各种回调方法,下面给出了最重要的方法。您不需要实现所有回调方法。然而,重要的是你要理解每一个并实现那些确保你的应用程序按照用户期望的方式运行的东西。

编号回调 & 描述
1

onStartCommand()

当另一个组件(如 activity)通过调用 startService() 请求启动服务时,系统将调用此方法如果您实现了此方法,则您应该通过调用 stopSelf() 或 stopService() 方法在服务工作完成时停止服务。

2

onBind()

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

3

onUnbind()

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

4

onRebind()

当新客户机连接到该服务时,系统会调用此方法,之前会通知它所有客户机都已在其 onUnbind(Intent) 中断开连接。

5

onCreate()

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

6

onDestroy()

当服务不再使用并且正在被销毁时,系统将调用此方法您的服务应该实现这一点,以清理任何资源,如线程、注册的侦听器、接收器等。

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

  1. package com.cankaoshouce.helloworld;
  2. import android.app.Service;
  3. import android.content.Intent;
  4. import android.os.IBinder;
  5. public class HelloService extends Service {
  6. /** 指示服务被终止时的行为 */
  7. int mStartMode;
  8. /** 绑定客户端的接口 */
  9. IBinder mBinder;
  10. /** 指示是否应使用onRebind */
  11. boolean mAllowRebind;
  12. /** 在创建服务时调用。 */
  13. @Override
  14. public void onCreate() {
  15. }
  16. /** 由于调用startService(),服务正在启动 */
  17. @Override
  18. public int onStartCommand(Intent intent, int flags, int startId) {
  19. return mStartMode;
  20. }
  21. /** 客户端使用bindService()绑定到服务 */
  22. @Override
  23. public IBinder onBind(Intent intent) {
  24. return mBinder;
  25. }
  26. /** 当所有客户端都与unbindService()解除绑定时调用*/
  27. @Override
  28. public boolean onUnbind(Intent intent) {
  29. return mAllowRebind;
  30. }
  31. /** 当客户端通过bindService()绑定到服务时调用*/
  32. @Override
  33. public void onRebind(Intent intent) {
  34. }
  35. /** 当服务不再使用并被销毁时调用 */
  36. @Override
  37. public void onDestroy() {
  38. }
  39. }

实例

这个例子将带你通过简单的步骤来展示如何创建你自己的 Android 服务。

按照以下步骤修改我们在 Hello World 实例章节中创建的 Android 应用程序:

Step描述
1您将使用 Android Studio IDE 创建一个 Android 应用程序,并在com.example.cankaoshouce.myapplication 包下将其命名为 My application,如 Hello World 实例一章中所述。
2修改主 activity 文件 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() 方法来启动和停止服务。

  1. package com.cankaoshouce.helloworld;
  2. import androidx.appcompat.app.AppCompatActivity;
  3. import android.content.Intent;
  4. import android.os.Bundle;
  5. import android.util.Log;
  6. import android.view.View;
  7. public class MainActivity extends AppCompatActivity {
  8. String msg = "Android : ";
  9. /** 在第一次创建 activity 时调用。 */
  10. @Override
  11. public void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.activity_main);
  14. Log.d(msg, "onCreate() 事件被调用。");
  15. }
  16. public void startService(View view) {
  17. startService(new Intent(getBaseContext(), HelloService.class));
  18. }
  19. // 停止服务
  20. public void stopService(View view) {
  21. stopService(new Intent(getBaseContext(), HelloService.class));
  22. }
  23. }

以下是 HellowService.java 的内容。该文件可以根据要求实现与服务相关联的一种或多种方法。现在,我们将仅实现两种方法 onStartCommand() 和 onDestroy():

  1. package com.cankaoshouce.helloworld;
  2. import android.app.Service;
  3. import android.content.Intent;
  4. import android.os.IBinder;
  5. import android.widget.Toast;
  6. import androidx.annotation.Nullable;
  7. public class HelloService extends Service {
  8. @Nullable
  9. @Override
  10. public IBinder onBind(Intent intent) {
  11. return null;
  12. }
  13. @Override
  14. public int onStartCommand(Intent intent, int flags, int startId) {
  15. // Let it continue running until it is stopped.
  16. Toast.makeText(this, "服务启动。", Toast.LENGTH_LONG).show();
  17. return START_STICKY;
  18. }
  19. @Override
  20. public void onDestroy() {
  21. super.onDestroy();
  22. Toast.makeText(this, "服务销毁。", Toast.LENGTH_LONG).show();
  23. }
  24. }

以下将修改 AndroidManifest.xml 文件的内容。在这里我们添加了 <service … /> 标签以包括我们的服务

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.cankaoshouce.helloworld">
  4. <application
  5. android:allowBackup="true"
  6. android:icon="@mipmap/ic_launcher"
  7. android:label="@string/app_name"
  8. android:roundIcon="@mipmap/ic_launcher_round"
  9. android:supportsRtl="true"
  10. android:theme="@style/AppTheme">
  11. <activity android:name=".MainActivity">
  12. <intent-filter>
  13. <action android:name="android.intent.action.MAIN" />
  14. <category android:name="android.intent.category.LAUNCHER" />
  15. </intent-filter>
  16. </activity>
  17. <service
  18. android:name=".HelloService"
  19. android:enabled="true"
  20. android:exported="true"></service>
  21. </application>
  22. </manifest>

以下是 res/layout/activity_main.xml 文件的内容,其中包括两个按钮:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:tools="http://schemas.android.com/tools"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. xmlns:app="http://schemas.android.com/apk/res-auto"
  7. android:paddingLeft="@dimen/activity_horizontal_margin"
  8. android:paddingRight="@dimen/activity_horizontal_margin"
  9. android:paddingTop="@dimen/activity_vertical_margin"
  10. android:paddingBottom="@dimen/activity_vertical_margin"
  11. tools:context=".MainActivity">
  12. <TextView
  13. android:id="@+id/textView1"
  14. android:layout_width="wrap_content"
  15. android:layout_height="wrap_content"
  16. android:layout_alignParentTop="true"
  17. android:layout_centerHorizontal="true"
  18. android:layout_marginTop="43dp"
  19. android:text="services 例子"
  20. android:textSize="30dp"
  21. tools:ignore="MissingConstraints"
  22. tools:layout_editor_absoluteX="109dp"
  23. tools:layout_editor_absoluteY="48dp" />
  24. <TextView
  25. android:id="@+id/textView2"
  26. android:layout_width="wrap_content"
  27. android:layout_height="wrap_content"
  28. android:layout_above="@+id/imageButton"
  29. android:layout_centerHorizontal="true"
  30. android:layout_marginBottom="96dp"
  31. android:text="参考手册 "
  32. android:textColor="#ff87ff09"
  33. android:textSize="30dp"
  34. tools:ignore="MissingConstraints"
  35. tools:layout_editor_absoluteX="162dp"
  36. tools:layout_editor_absoluteY="121dp" />
  37. <ImageButton
  38. android:id="@+id/imageButton"
  39. android:layout_width="wrap_content"
  40. android:layout_height="wrap_content"
  41. android:layout_centerHorizontal="true"
  42. android:layout_centerVertical="true"
  43. android:src="@drawable/logo"
  44. app:layout_constraintEnd_toEndOf="parent"
  45. app:layout_constraintStart_toStartOf="parent"
  46. tools:layout_editor_absoluteY="196dp"
  47. tools:ignore="MissingConstraints" />
  48. <Button
  49. android:id="@+id/button2"
  50. android:layout_width="wrap_content"
  51. android:layout_height="wrap_content"
  52. android:layout_below="@+id/imageButton"
  53. android:layout_centerHorizontal="true"
  54. android:layout_marginTop="16dp"
  55. android:onClick="startService"
  56. android:text="启动服务"
  57. app:layout_constraintEnd_toEndOf="parent"
  58. app:layout_constraintStart_toStartOf="parent"
  59. tools:ignore="MissingConstraints"
  60. tools:layout_editor_absoluteY="397dp" />
  61. <Button
  62. android:id="@+id/button"
  63. android:layout_width="wrap_content"
  64. android:layout_height="wrap_content"
  65. android:layout_below="@+id/button2"
  66. android:layout_alignStart="@+id/button2"
  67. android:layout_alignLeft="@+id/button2"
  68. android:layout_alignEnd="@+id/button2"
  69. android:layout_alignRight="@+id/button2"
  70. android:layout_centerHorizontal="true"
  71. android:layout_marginStart="0dp"
  72. android:layout_marginLeft="0dp"
  73. android:layout_marginTop="47dp"
  74. android:layout_marginEnd="0dp"
  75. android:layout_marginRight="0dp"
  76. android:onClick="stopService"
  77. android:text="停止服务"
  78. app:layout_constraintEnd_toEndOf="parent"
  79. app:layout_constraintStart_toStartOf="parent"
  80. tools:ignore="MissingConstraints"
  81. tools:layout_editor_absoluteY="326dp" />
  82. </RelativeLayout>

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

现在启动服务,让我们单击 "启动服务" 按钮,这将启动服务,并且按照我们在 onStartCommand() 方法中的编程,一条 "服务启动。" 的消息将出现在模拟器的底部。

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