Android
 Computer >> コンピューター >  >> プログラミング >> Android

【Android】IntentServiceからUIを更新する方法をわかりやすく解説

IntentServiceとは

AndroidのIntentServiceは、バックグラウンド処理を非同期的に実行するためのサービスコンポーネントです。アクティビティからstartService()を呼び出しても、リクエストごとに新しいインスタンスが生成されることはありません。また、サービスクラス内の処理が完了すると自動的に停止し、必要に応じてstopSelf()を呼び出して明示的に停止させることも可能です。

本記事では、IntentServiceからUIを更新する方法を、実際のサンプルコードとともにステップ形式で解説します。

実装のポイント:BroadcastReceiverの活用

IntentServiceはワーカースレッド上で動作するため、そのままではUI要素を直接操作できません。そこで今回は、BroadcastReceiver(ブロードキャストレシーバー)を使い、サービス側で生成したデータをアクティビティ側へ通知することで、TextViewを更新する仕組みを実装します。

手順1:新規プロジェクトの作成

Android Studioで「File」→「New Project」を選択し、必要な項目を入力して新しいプロジェクトを作成します。

手順2:レイアウトファイル(activity_main.xml)の作成

res/layout/activity_main.xmlに以下のコードを追加します。

<?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">
   <TextView
      android:id = "@+id/text"
      android:layout_width = "wrap_content"
      android:layout_height = "wrap_content"
      android:text = "Start Service"
      android:textSize = "25sp"
      app:layout_constraintBottom_toBottomOf = "parent"
      app:layout_constraintLeft_toLeftOf = "parent"
      app:layout_constraintRight_toRightOf = "parent"
      app:layout_constraintTop_toTopOf = "parent" />
</android.support.constraint.ConstraintLayout>

上記のコードでは、画面中央にTextViewを配置しています。ユーザーがIntentServiceからデータを受け取ると、このTextViewの表示内容が更新されます。

手順3:MainActivity.javaの実装

src/MainActivity.javaに以下のコードを追加します。

package com.example.andy.myapplication;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    TextView text;
    BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String s1 = intent.getStringExtra("DATAPASSED");
            text.setText(s1);
        }
    };

    @Override
    protected void onStart() {
        super.onStart();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("com.example.andy.myapplication");
        registerReceiver(broadcastReceiver, intentFilter);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        text = findViewById(R.id.text);
        text.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startService(new Intent(MainActivity.this, service.class));
            }
        });
    }

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

上記のコードでは、サービスクラスの起動と、動的なブロードキャストレシーバーの登録を行っています。ポイントとなる処理は以下の通りです。

@Override
protected void onStart() {
   super.onStart();
   IntentFilter intentFilter = new IntentFilter();
   intentFilter.addAction("com.example.andy.myapplication");
   registerReceiver(broadcastReceiver, intentFilter);
}

BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
   @Override
   public void onReceive(Context context, Intent intent) {
      String s1 = intent.getStringExtra("DATAPASSED");
      text.setText(s1);
   }
};

@Override
protected void onStop() {
   super.onStop();
   unregisterReceiver(broadcastReceiver);
}
  • onStart():アクティビティの開始時に、アクション名「com.example.andy.myapplication」を持つIntentFilterを作成し、BroadcastReceiverを登録します。
  • BroadcastReceiver:onReceive()内で、Intentからキー「DATAPASSED」に格納された文字列を取得し、TextViewに反映します。
  • onStop():アクティビティの停止時に、登録済みのBroadcastReceiverを解除します。メモリリーク防止のため必須の処理です。

service.java(IntentServiceクラス)の作成

続いて、service.classという名前で新しいクラスファイルを作成し、以下のコードを追加します。

package com.example.andy.myapplication;
import android.app.IntentService;
import android.content.Intent;
import android.os.IBinder;
public class service extends IntentService {
   public service() {
      super(service.class.getSimpleName());
   }
   @Override
   public IBinder onBind(Intent intent) {
      return null;
   }
   @Override
   protected void onHandleIntent(Intent intent) {
      Intent intent1 = new Intent();
      intent1.setAction("com.example.andy.myapplication");
      intent1.putExtra("DATAPASSED", "Tutorialspoint.com");
      sendBroadcast(intent1);
   }
}

onHandleIntent()内では、新しいIntentを生成してアクション名を設定し、キー「DATAPASSED」に文字列「Tutorialspoint.com」を格納したうえで、sendBroadcast()によりブロードキャストを送信しています。これを受け取ったアクティビティ側のBroadcastReceiverがTextViewを更新する仕組みです。

手順4:AndroidManifest.xmlの編集

manifest.xmlに以下のコードを追加します。

<?xml version = "1.0" encoding = "utf-8"?>
<manifest xmlns:android = "https://schemas.android.com/apk/res/android"
    package = "com.example.andy.myapplication">
    <uses-permission android:name = "android.permission.WAKE_LOCK"/>
    <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 = ".service"/>
    </application>
</manifest>

マニフェストには、作成したサービスクラス「.service」の宣言と、WAKE_LOCKパーミッションが含まれています。

アプリの実行と動作確認

それでは、アプリケーションを実行してみましょう。ここでは、実機のAndroid端末をPCに接続しているものとして説明します。Android Studioでプロジェクトのアクティビティファイルを開き、ツールバーの「Run」アイコンをクリックしてください。実行デバイスとして自分のモバイル端末を選択すると、まず以下のような初期画面が表示されます。

【Android】IntentServiceからUIを更新する方法をわかりやすく解説

上記がアプリの初期画面です。画面上の「Start Service」をタップするとサービスが起動し、IntentServiceから送信されたデータを受信して、TextViewが以下のように更新されます。

【Android】IntentServiceからUIを更新する方法をわかりやすく解説

まとめ

IntentServiceはバックグラウンド処理に便利なコンポーネントですが、ワーカースレッドで動作するためUIを直接操作できません。今回のようにsendBroadcast()とregisterReceiver()を組み合わせてBroadcastReceiver経由でデータを渡すことで、サービスから安全かつシンプルにUIを更新できます。ぜひ実際のプロジェクトでも活用してみてください。

  1. Androidアプリで端末起動時にサービスを自動開始する方法【コード例付きで解説】

    はじめにAndroidアプリの中には、端末が再起動された後もバックグラウンド処理を継続したいケースがあります。本記事では、BroadcastReceiverとBOOT_COMPLETEDアクションを組み合わせて、端末の起動完了時にサービスを自動的に開始する方法を、実際のコード例とともにステップごとに解説します。この仕組みを実現するには、まずシステムから「起動完了」のブロードキャストを受け取るレシーバーを用意し、その中でActivityやServiceを起動します。以下の手順に従って実装していきましょう。Step 1:新規プロジェクトを作成するAndroid Studioを開き、「File」→「

  2. Androidからマルウェアを削除する方法|感染の兆候と予防策を徹底解説

    現代社会において、スマートフォンは生活に欠かせない存在となっています。銀行アプリ、ナビゲーションアプリ、各種ユーティリティアプリなど、個人の重要な情報や機能がほぼすべて詰まっています。だからこそ、プライバシーを守るためにも、スマートフォンをしっかりと保護することが何よりも重要です。パソコンと同様に、Androidスマートフォンもウイルス、トロイの木馬、スパイウェア、アドウェアなどの悪意あるプログラム(マルウェア)に感染する可能性があります。Androidマルウェアの主な目的は、機密情報の窃取、無関係な広告の表示によるユーザーの誤誘導、悪質なサイトへのリダイレクトなどです。マルウェアはさまざまな