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

Androidで10秒ごとにIntentService(インテントサービス)を開始する方法を解説

IntentServiceとは?

例に入る前に、AndroidにおけるIntentServiceの基本をおさえておきましょう。IntentServiceは、バックグラウンド処理を非同期(別スレッド)で実行してくれるサービスコンポーネントです。

ActivityなどからstartService()を呼び出しても、リクエストごとに新しいインスタンスは作成されず、処理はキューに順番に積まれて実行されます。すべての処理が完了するとサービスは自動的に停止しますが、任意のタイミングでstopSelf()を呼び出して明示的に停止させることも可能です。

本記事では、10秒ごとにインテントサービスを開始する方法を、サンプルコード付きで段階的に解説していきます。

ステップ1:新規プロジェクトの作成

Android Studioを起動し、メニューから「File」→「New Project」を選択して、必要な項目を入力しながら新しいプロジェクトを作成します。

ステップ2:レイアウトファイルの作成

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を1つ用意しています。インテントサービスからデータを受け取った際に、この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.os.Handler;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;

import java.util.Timer;
import java.util.TimerTask;

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

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

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        text = findViewById(R.id.text);
        final Handler handler = new Handler();
        TimerTask timertask = new TimerTask() {
            @Override
            public void run() {
                handler.post(new Runnable() {
                    public void run() {
                        startService(new Intent(MainActivity.this, service.class));
                    }
                });
            }
        };
        Timer timer = new Timer();
        timer.schedule(timertask, 0, 10000);
    }

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

このコードのポイントは次の通りです。

  • Timer/TimerTask:timer.schedule(timertask, 0, 10000)によって、初回は即時に、以降は10秒間隔でタスクが繰り返し実行されます。
  • Handler:UIスレッド以外からは直接サービスを安全に扱えないため、handler.post()を使ってメインスレッド上でstartService()を呼び出しています。
  • BroadcastReceiver:onStart()でLocalBroadcastManagerにレシーバーを登録し、サービスからの結果を受け取ってTextViewへ反映します。onStop()で登録解除を行い、メモリリークを防止している点も重要です。

サービスクラスの作成(service.java)

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

package com.example.andy.myapplication;

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

public class service extends IntentService {
    public static volatile boolean shouldStop = false;
    public service() {
        super(service.class.getSimpleName());
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Intent intent1 = new Intent("com.example.andy.myapplication");
        intent1.putExtra("someName", "Tutorialspoint.com");
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent1);
        if(shouldStop) {
            stopSelf();
            return;
        }
    }
}

onHandleIntent()内では、アクション「com.example.andy.myapplication」を持つインテントを生成し、putExtra()で文字列データを添えたうえでローカルブロードキャストを送信しています。これを受信したActivity側のTextViewが更新される流れです。また、volatile修飾子を付けたshouldStopフラグがtrueになれば、stopSelf()を呼び出してサービスを停止できます。

ステップ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 android:name=".service"/> の宣言を忘れると、サービス起動のタイミングでアプリがクラッシュするため注意してください。

アプリの実行と動作確認

それでは、アプリケーションを実行してみましょう。ここでは、実際のAndroid端末をPCに接続しているものとします。Android Studioでプロジェクト内のアクティビティファイルを開き、ツールバーの「実行(Run)」アイコンをクリックします。表示された候補から自分のモバイルデバイスを選択してください。

Androidで10秒ごとにIntentService(インテントサービス)を開始する方法を解説

上記がアプリの初期画面です。その後は10秒ごとにサービスが自動的に起動され、バックグラウンドでデータを取得して画面表示を更新し続けます。

補足:IntentServiceは現在非推奨

なお、IntentServiceはAPIレベル30(Android 11)で非推奨(deprecated)となっています。新規開発で定期的なバックグラウンド処理を行う場合は、WorkManagerやJobSchedulerの利用が推奨されます。ただし、本記事で紹介した「Timerによる定期起動+ブロードキャストでの結果通知」という設計思想自体は、他の手法でもそのまま応用できるので、仕組みの理解として役立ててください。


  1. 【Android】デバイス起動時にアプリを自動起動させる方法を徹底解説

    概要本記事では、Androidデバイスの電源投入・再起動が完了したタイミングで、アプリケーションを自動的に起動させる方法を解説します。BroadcastReceiverを使ってシステムが発行する「BOOT_COMPLETED」ブロードキャストを受け取り、そこからアクティビティを起動するのが基本的な仕組みです。実装手順ステップ1:新規プロジェクトの作成Android Studioを開き、File ⇒ New Project を選択します。必要な項目をすべて入力して、新しいプロジェクトを作成しましょう。ステップ2:レイアウトファイル(res/layout/activity_main.xml)の編集

  2. AndroidでAsyncTaskにタイムアウトを設定する方法【サンプルコード付きで解説】

    はじめに このチュートリアルでは、AndroidアプリでAsyncTaskにタイムアウトを設定する方法を、実際に動作するサンプルコードとともに解説します。EditTextに入力した秒数だけバックグラウンド処理をスリープさせ、その間の進捗状況をProgressDialogで表示するシンプルなデモアプリを作成していきます。 実装手順 ステップ1:新規プロジェクトを作成する Android Studioを開き、メニューから「File」→「New Project」を選択します。必要な項目をすべて入力して、新しいプロジェクトを作成してください。 ステップ2:activity_main.xml にレ