使用BroadcastReceiver的Android IntentService

时间:2020-02-23 14:29:00  来源:igfitidea点击:

在本教程中,我们将讨论Android框架的基本组件之一,即IntentService。
我们将使用BroadcastReceiver开发一个Android IntentService应用程序。

Android IntentService

我们在之前的教程中讨论了Android服务。
IntentService扩展了Service类。

Services和IntentServices均用于运行不需要UI的操作。

IntentService用于顺序运行数据。
每次您对服务调用Intent时,该操作都会添加到队列中。

Android IntentService与服务

使用startService()调用服务使用Intent调用IntentService
服务可以从任何线程调用。IntentService只能从主线程调用
默认情况下,服务在应用程序的主线程上运行后台操作。因此,它会阻塞应用程序的UI。IntentService会创建一个单独的工作线程来运行后台操作
多次调用的服务将创建多个实例。多次调用的IntentService不会创建多个实例
需要使用stopSelf()或stopService()停止服务IntentService在队列完成后自动停止。无需触发stopService()或stopSelf()
Android服务可以运行并行操作。在IntentService中,多个intent调用会自动排队并执行顺序。一个IntentService不能像服务一样运行并行操作

在服务中,当从活动传递意图时,将调用onHandleIntent()方法。

BroadcastReceivers用于在应用程序之间或者服务与活动之间传输消息。
为了在服务和活动之间传输数据,我们需要使用LocalBroadcastManager。

支持库随附LocalBroadcastManager类,该类仅用于本地传输数据。
您无法在应用程序外部传输数据。

在下一节中,我们将创建一个应用程序,该应用程序将字符串传递给IntentService,并在延迟后将其返回给Activity。
多亏了IntentService,这是顺序发生的。

Android IntentService示例项目结构

布局代码

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

  <EditText
      android:id="@+id/inputText"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_margin="8dp"
      android:hint="Enter your message"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintLeft_toLeftOf="parent"
      app:layout_constraintRight_toRightOf="parent"
      app:layout_constraintTop_toTopOf="parent" 

  <Button
      android:id="@+id/button"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginTop="8dp"
      android:text="Send Message"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toBottomOf="@+id/inputText" 

  <TextView
      android:id="@+id/textView"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginTop="24dp"
      android:text="Message received from the Service is:\n"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toTopOf="parent" 

</android.support.constraint.ConstraintLayout>

MainActivity.java类的代码如下:

package com.theitroad.androidintentservices;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

  TextView textView;
  Button button;
  EditText editText;
  MyReceiver myReceiver;

  public static final String FILTER_ACTION_KEY = "any_key";

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      textView = findViewById(R.id.textView);
      button = findViewById(R.id.button);
      editText = findViewById(R.id.inputText);

      button.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
              String message = editText.getText().toString();
              Intent intent = new Intent(MainActivity.this, MyService.class);
              intent.putExtra("message", message);
              startService(intent);
          }
      });
  }

  private void setReceiver() {
      myReceiver = new MyReceiver();
      IntentFilter intentFilter = new IntentFilter();
      intentFilter.addAction(FILTER_ACTION_KEY);

      LocalBroadcastManager.getInstance(this).registerReceiver(myReceiver, intentFilter);
  }

  @Override
  protected void onStart() {
      setReceiver();
      super.onStart();
  }

  @Override
  protected void onStop() {
      unregisterReceiver(myReceiver);
      super.onStop();
  }

  private class MyReceiver extends BroadcastReceiver {
      @Override
      public void onReceive(Context context, Intent intent) {
          String message = intent.getStringExtra("broadcastMessage");
          textView.setText(textView.getText() + "\n" + message);
      }
  }
}

一些要点:

  • 我们需要设置一个IntentFilter来注册我们的BroadcastReceiver。

  • 在IntentFilter Action中,我们指定一个字符串。

  • 同样的字符串也将在我们的IntentService中使用。

  • 我们必须使用onStop()方法注销我们的BroadcastReceiver。

  • LocalBroadcastManager实例用于设置接收者。

  • 我们的BroadcastReceiver将附加从服务返回的字符串。

MyService.java类的代码如下:

package com.theitroad.androidintentservices;

import android.app.IntentService;
import android.content.Intent;
import android.os.SystemClock;
import android.support.v4.content.LocalBroadcastManager;

public class MyService extends IntentService {

  public MyService() {
      super("MyService");
  }

  @Override
  protected void onHandleIntent(Intent intent) {

      String message = intent.getStringExtra("message");
      intent.setAction(MainActivity.FILTER_ACTION_KEY);
      SystemClock.sleep(3000);
      String echoMessage = "IntentService after a pause of 3 seconds echoes " + message;
      LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent.putExtra("broadcastMessage", echoMessage));
  }
}

要将数据返回到活动,我们使用sendBroadcast方法。
它将数据传递到BroadcastReceiver。
广播接收器最终将数据传递给活动。

您必须在列表文件中声明服务。
如果没有LocalBroadcastManager,则不会传递上述数据。