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

【Android開発】5分ごとに通知を自動表示するアプリの作り方を解説

はじめに

このチュートリアルでは、Androidアプリで5分ごと(任意の間隔)に通知を自動表示する方法を、サンプルコードとともに段階的に解説します。ServiceとTimerを組み合わせることで、アプリがバックグラウンドに回っても定期的に通知を発行できるようになります。

全体の仕組み

実装のポイントは以下の3つです。

  • メインアクティビティが停止(onStop)したタイミングでサービスを起動する
  • サービス内でTimerを使い、一定間隔で通知生成処理を実行する
  • Android 8.0(APIレベル26)以降では通知チャンネルを作成して通知を表示する

それでは、順番に見ていきましょう。

ステップ1:新規プロジェクトを作成する

Android Studioを開き、File → New Project を選択して新しいプロジェクトを作成します。必要な項目(プロジェクト名、パッケージ名、保存先など)を入力しましょう。

ステップ2:レイアウトファイル(activity_main.xml)を編集する

res/layout/activity_main.xml に以下のコードを追加します。画面中央に「通知確認のためアプリを閉じる」ボタンを配置するシンプルな構成です。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    tools:context=".MainActivity">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:onClick="closeApp"
        android:text="close App for notification" />

</RelativeLayout>

ステップ3:MainActivity.java を実装する

src/MainActivity.java に以下のコードを記述します。onStop() メソッド内で NotificationService を起動している点が重要です。これにより、ユーザーがホームボタンなどでアプリを離れたタイミングで定期通知が開始されます。

package app.tutorialspoint.com.notifyme;

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

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onStop() {
        super.onStop();
        startService(new Intent(this, NotificationService.class));
    }

    public void closeApp(View view) {
        finish();
    }
}

ステップ4:NotificationService.java を実装する

次に、実際に通知を発行するサービスクラスを作成します。src/NotificationService.java に以下のコードを追加してください。

package app.tutorialspoint.com.notifyme;

import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import java.util.Timer;
import java.util.TimerTask;

public class NotificationService extends Service {

    public static final String NOTIFICATION_CHANNEL_ID = "10001";
    private final static String default_notification_channel_id = "default";
    Timer timer;
    TimerTask timerTask;
    String TAG = "Timers";
    int Your_X_SECS = 5;

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand");
        super.onStartCommand(intent, flags, startId);
        startTimer();
        return START_STICKY;
    }

    @Override
    public void onCreate() {
        Log.e(TAG, "onCreate");
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "onDestroy");
        stopTimerTask();
        super.onDestroy();
    }

    // TimerTask内でUIスレッド上の処理を実行するためHandlerを使用
    final Handler handler = new Handler();

    public void startTimer() {
        timer = new Timer();
        initializeTimerTask();
        timer.schedule(timerTask, 500000, Your_X_SECS * 1000);
    }

    public void stopTimerTask() {
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
    }

    public void initializeTimerTask() {
        timerTask = new TimerTask() {
            public void run() {
                handler.post(new Runnable() {
                    public void run() {
                        createNotification();
                    }
                });
            }
        };
    }

    private void createNotification() {
        NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext(), default_notification_channel_id);
        mBuilder.setContentTitle("My Notification");
        mBuilder.setContentText("Notification Listener Service Example");
        mBuilder.setTicker("Notification Listener Service Example");
        mBuilder.setSmallIcon(R.drawable.ic_launcher_foreground);
        mBuilder.setAutoCancel(true);
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            int importance = NotificationManager.IMPORTANCE_HIGH;
            NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "NOTIFICATION_CHANNEL_NAME", importance);
            mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
            assert mNotificationManager != null;
            mNotificationManager.createNotificationChannel(notificationChannel);
        }
        assert mNotificationManager != null;
        mNotificationManager.notify((int) System.currentTimeMillis(), mBuilder.build());
    }
}

コードのポイント

  • Your_X_SECS = 5:通知の表示間隔(秒)を指定する変数です。この値を変更すれば、任意の間隔で通知を繰り返せます。
  • timer.schedule(timerTask, 500000, Your_X_SECS * 1000):最初の通知までの遅延時間(ミリ秒)と、その後の繰り返し間隔を指定しています。
  • START_STICKY:システムによってサービスが強制終了された場合でも、可能な限り再起動されるようにしています。
  • 通知チャンネル対応:Android 8.0(Oreo)以降では通知チャンネルの作成が必須のため、SDK_INTの判定を行っています。

ステップ5:AndroidManifest.xml を編集する

最後に、AndroidManifest.xml にサービスの宣言と権限を追加します。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="app.tutorialspoint.com.notifyme">

    <uses-permission android:name="android.permission.VIBRATE" />

    <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=".NotificationService"
            android:label="@string/app_name">
            <intent-filter>
                <action
                    android:name="app.tutorialspoint.com.notifyme.NotificationService" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </service>

    </application>
</manifest>

アプリを実行して動作を確認する

それでは、実際にアプリを起動してみましょう。Android端末をPCに接続し、Android Studioからプロジェクトのアクティビティファイルを開いて、ツールバーのRun(実行)アイコンをクリックします。デバイス選択画面で接続中のスマートフォンを選択すると、端末にアプリがインストールされ、デフォルト画面が表示されます。

ボタンをタップしてアプリを閉じると、onStop() が呼ばれてサービスが起動し、設定した間隔ごとに通知が届くことを確認できます。うまく動作しない場合は、端末の設定でアプリの通知が許可されているか、バッテリー最適化によってサービスが停止されていないかも合わせてチェックしてみてください。

  1. 【Android】Notification.deleteIntentの使い方を徹底解説!通知削除を検知する方法

    Androidアプリ開発において、Notification.deleteIntentは「ユーザーが通知を削除(スワイプして消去)した瞬間」を検知できる非常に便利な仕組みです。本記事では、deleteIntentを実際に使ったサンプルアプリを通じて、その実装手順をステップごとにわかりやすく解説します。deleteIntentとは?deleteIntentにPendingIntentを設定しておくと、ユーザーが通知を消去した際にシステムがそのPendingIntentを発行してくれます。これにより、「通知を閉じたらデータをクリアする」「削除されたことをログに記録する」といった処理を実現できます。そ

  2. Androidでリマインダー通知を実装する方法を初心者向けに解説

    この記事では、Androidアプリで毎日決まった時刻に通知を表示する「リマインダー通知」の実装方法を、サンプルコードとともにステップごとに解説します。AlarmManagerとServiceを組み合わせることで、アプリが起動していなくても指定時刻に通知を届けられる仕組みを作れます。全体の仕組み本サンプルでは、以下の流れでリマインダー通知を実現します。1. 画面上のボタンをタップすると、翌日の午前0時に通知を発行するようAlarmManagerに登録します。2. 指定時刻になるとシステムがNotifyService(Serviceクラス)を起動します。3. Service内でNotificati