facebook twitter hatena line email

「Unity/Native連携/Kotlinバックグランド通知」の版間の差分

提供: 初心者エンジニアの簡易メモ
移動: 案内検索
(ページの作成:「==Unity側== RenkeiScene.cs <pre> using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using System; public class RenkeiSc...」)
 
行80: 行80:
  
 
import android.app.AlarmManager
 
import android.app.AlarmManager
 +
import android.app.NotificationChannel
 +
import android.app.NotificationManager
 
import android.app.PendingIntent
 
import android.app.PendingIntent
 
import android.content.BroadcastReceiver
 
import android.content.BroadcastReceiver
行86: 行88:
 
import android.os.SystemClock
 
import android.os.SystemClock
 
import android.util.Log
 
import android.util.Log
import android.widget.Toast
 
 
import java.util.Calendar
 
import java.util.Calendar
 +
import android.os.Build
 +
import androidx.core.app.NotificationCompat
  
 
class AlarmReceiver : BroadcastReceiver() {
 
class AlarmReceiver : BroadcastReceiver() {
  
 
     override fun onReceive(context: Context, intent: Intent) {
 
     override fun onReceive(context: Context, intent: Intent) {
         val message = "時間です"
+
        Log.i("AlarmReceiver", "Notification triggered")
         Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
+
        // 通知を作成して表示
 +
         val notificationId = 1
 +
        val channelId = "alarm_channel"
 +
 
 +
         val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
 +
 
 +
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
 +
            val channelName = "Alarm Channel"
 +
            val channelDescription = "Channel for alarm notifications"
 +
            val importance = NotificationManager.IMPORTANCE_HIGH
 +
 
 +
            val notificationChannel = NotificationChannel(channelId, channelName, importance).apply {
 +
                description = channelDescription
 +
            }
 +
 
 +
            notificationManager.createNotificationChannel(notificationChannel)
 +
            Log.i("AlarmReceiver", "Notification Channel Created")
 +
 
 +
            // API 26+ の場合
 +
            val notification = NotificationCompat.Builder(context, channelId)
 +
                .setSmallIcon(android.R.drawable.ic_notification_overlay) // 通知アイコン
 +
                .setContentTitle("アラーム通知") // 通知タイトル
 +
                .setContentText("指定した時間が経過しました!") // 通知内容
 +
                .setPriority(NotificationCompat.PRIORITY_HIGH)
 +
                .build()
 +
 
 +
            notificationManager.notify(notificationId, notification)
 +
            Log.i("AlarmReceiver", "Notification Posted")
 +
        } else {
 +
            // API 26 未満の場合
 +
            val notification = NotificationCompat.Builder(context, channelId)
 +
                .setSmallIcon(R.drawable.ic_notification) // 通知アイコン
 +
                .setContentTitle("アラーム通知") // 通知タイトル
 +
                .setContentText("指定した時間が経過しました!") // 通知内容
 +
                .setPriority(NotificationCompat.PRIORITY_HIGH)
 +
                .build()
 +
 
 +
            notificationManager.notify(notificationId, notification)
 +
            Log.i("AlarmReceiver", "Notification Posted")
 +
        }
 
     }
 
     }
  
行129: 行171:
 
     xmlns:tools="http://schemas.android.com/tools">
 
     xmlns:tools="http://schemas.android.com/tools">
 
     <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
 
     <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
 +
    <!-- アラーム受信に必要な権限(通常は不要) -->
 +
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
 +
    <!-- 通知権限 -->
 +
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
 
     <application>
 
     <application>
 
         <receiver
 
         <receiver
行145: 行191:
 
</manifest>
 
</manifest>
 
</pre>
 
</pre>
 +
 +
Assets/Plugins/Android/mainTemplate.gradle
 +
<pre>
 +
dependencies {
 +
+    implementation 'androidx.core:core:1.12.0'
 +
}
 +
</pre>
 +
NotificationCompatを使うため
 +
 +
Assets/Plugins/Android/gradleTemplate.properties
 +
<pre>
 +
android.useAndroidX=true
 +
android.enableJetifier=true
 +
</pre>
 +
NotificationCompatを使うため

2024年9月11日 (水) 17:20時点における版

Unity側

RenkeiScene.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;
public class RenkeiScene : MonoBehaviour
{
    [SerializeField] Button alarmButton;
    void Start()
    {
        alarmButton.onClick.AddListener(CallMethodAlarm);
    }
    void CallMethodAlarm()
    {
        SetAlarm(10);
    }
#if UNITY_ANDROID && !UNITY_EDITOR
    public void SetAlarm(int second)
    {
        Debug.Log("SetAlarm second=" + second);
        using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        {
            AndroidJavaObject activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
            AndroidJavaObject context = activity.Call<AndroidJavaObject>("getApplicationContext");

            AndroidJavaClass alarmReceiver = new AndroidJavaClass("com.example.mylibrary.AlarmReceiver");
            alarmReceiver.CallStatic("setAlarm", context, second);
        }
    }
    // 権限付与
    public void RequestExactAlarmPermission()
    {
        using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        {
            AndroidJavaObject activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");

            AndroidJavaObject alarmPermissionHelper = new AndroidJavaObject("com.example.alarmapp.AlarmPermissionHelper");
            alarmPermissionHelper.Call("requestExactAlarmPermission", activity);
        }
    }
#endif
}

Android側

AlarmPermissionHelper.kt

package com.example.mylibrary

import android.content.Intent
import android.provider.Settings
import android.app.AlarmManager
import android.content.Context
import android.os.Build
import android.net.Uri

class AlarmPermissionHelper {

    fun requestExactAlarmPermission(context: Context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager

            if (!alarmManager.canScheduleExactAlarms()) {
                // アラームの許可がない場合、設定画面を開く
                val intent = Intent().apply {
                    action = Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM
                    data = Uri.parse("package:${context.packageName}")
                }
                context.startActivity(intent)
            }
        }
    }
}

AlarmReceiver.kt

package com.example.mylibrary

import android.app.AlarmManager
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.SystemClock
import android.util.Log
import java.util.Calendar
import android.os.Build
import androidx.core.app.NotificationCompat

class AlarmReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        Log.i("AlarmReceiver", "Notification triggered")
        // 通知を作成して表示
        val notificationId = 1
        val channelId = "alarm_channel"

        val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channelName = "Alarm Channel"
            val channelDescription = "Channel for alarm notifications"
            val importance = NotificationManager.IMPORTANCE_HIGH

            val notificationChannel = NotificationChannel(channelId, channelName, importance).apply {
                description = channelDescription
            }

            notificationManager.createNotificationChannel(notificationChannel)
            Log.i("AlarmReceiver", "Notification Channel Created")

            // API 26+ の場合
            val notification = NotificationCompat.Builder(context, channelId)
                .setSmallIcon(android.R.drawable.ic_notification_overlay) // 通知アイコン
                .setContentTitle("アラーム通知") // 通知タイトル
                .setContentText("指定した時間が経過しました!") // 通知内容
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .build()

            notificationManager.notify(notificationId, notification)
            Log.i("AlarmReceiver", "Notification Posted")
        } else {
            // API 26 未満の場合
            val notification = NotificationCompat.Builder(context, channelId)
                .setSmallIcon(R.drawable.ic_notification) // 通知アイコン
                .setContentTitle("アラーム通知") // 通知タイトル
                .setContentText("指定した時間が経過しました!") // 通知内容
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .build()

            notificationManager.notify(notificationId, notification)
            Log.i("AlarmReceiver", "Notification Posted")
        }
    }

    companion object {
        @JvmStatic
        fun setAlarm(context: Context, second: Int) {
            val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
            val intent = Intent(context, AlarmReceiver::class.java)
            val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
            val triggerAtMillis = SystemClock.elapsedRealtime() + calculateTriggerTime(second)
            alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtMillis, pendingIntent)
        }

        private fun calculateTriggerTime(second: Int): Long {
            // 現在の時間を取得
            val now = System.currentTimeMillis()
            val calendar = Calendar.getInstance()
            calendar.timeInMillis = now

            // 現在の時間に指定された秒を加算
            calendar.add(Calendar.SECOND, second)

            // 計算された時間が現在の時間より後であることを確認
            return calendar.timeInMillis - now
        }
    }
}

Assets/Plugins/Android/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.unity3d.player"
    xmlns:tools="http://schemas.android.com/tools">
    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
    <!-- アラーム受信に必要な権限(通常は不要) -->
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <!-- 通知権限 -->
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
    <application>
        <receiver
            android:name="com.example.mylibrary.AlarmReceiver"
            android:enabled="true"
            android:exported="true" />
        <activity android:name="com.unity3d.player.UnityPlayerActivity"
                  android:theme="@style/UnityThemeSelector">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
        </activity>
    </application>
</manifest>

Assets/Plugins/Android/mainTemplate.gradle

dependencies {
+    implementation 'androidx.core:core:1.12.0'
}

NotificationCompatを使うため

Assets/Plugins/Android/gradleTemplate.properties

android.useAndroidX=true
android.enableJetifier=true

NotificationCompatを使うため