Homeキーはシステムのボタンであり、onKeyDown では検知することができません。
そのため、Homeキーのイベントを検知するには、ちょっとだけトリックを使う必要があります。
それは、 Intent.ACTION_CLOSE_SYSTEM_DIALOGS と BroadcastReceiver です。
Intent.ACTION_CLOSE_SYSTEM_DIALOGS
このブロードキャストは、システムダイアログ(たとえば電源メニュー、Homeキーの押し、通知パネルのスワイプダウンなど)がシステムによって閉じられる際に送信されます。主に以下の用途で使用されます:
- Homeキーの短押し を検知する
- システムがダイアログを閉じようとしている(例:電源ボタンの長押し)状況を検知する
- 一部のTVシステムにおいて、リモコンに関連するメニューのクローズイベントを検知する
まず、BroadcastReceiver を継承したクラスを作成して、Intent.ACTION_CLOSE_SYSTEM_DIALOGSを受信するようにします:
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
import com.unity3d.player.UnityPlayer
class SystemDialogsBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == Intent.ACTION_CLOSE_SYSTEM_DIALOGS) {
val reason = intent.getStringExtra("reason")
when (reason) {
"homekey" -> { // Home button press
UnityPlayer.UnitySendMessage("SceneManager", "OnAndroidKeyDown", "home")
}
"recentapps" -> { // Home button hold
Log.d("SystemBroadcastReceiver", "Recent apps button pressed")
}
}
}
}
}
次に、MainActivity でこのブロードキャストレシーバーを登録します:
class MainActivity : UnityPlayerActivity() {
private lateinit var broadcastReceiver: SystemDialogsBroadcastReceiver
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
broadcastReceiver = SystemDialogsBroadcastReceiver()
}
override fun onResume() {
super.onResume()
val filter = IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)
registerReceiver(broadcastReceiver, filter)
}
override fun onPause() {
super.onPause()
unregisterReceiver(broadcastReceiver)
}
}
このように、Unity の SceneManager オブジェクトの OnAndroidKeyDown メソッドが呼び出され、home というパラメータが渡されます。
Unity 側の受信
BroadcastReceiver のコードで Unity の SceneManager オブジェクトの OnAndroidKeyDown メソッドを呼び出していますから、Unity 側でこのメソッドを実装します:
// Created by LunarEclipse on 2024-7-14 10:6.
using System;
using UnityEngine;
namespace USEN.Games.Common
{
public class RemoteControlHandler : MonoBehaviour
{
public void OnAndroidKeyDown(string keyName)
{
Debug.Log($"[UsenRemoteControlHandler] Key pressed: {keyName}");
UsenEvents.OnRemoconButtonClicked.Invoke(this, keyName);
switch (keyName)
{
case "home":
UsenEvents.OnRemoconHomeButtonClicked.Invoke(this, EventArgs.Empty);
break;
}
}
}
}
Homeキーを押すとき、イベント OnRemoconHomeButtonClicked を送信する。
そして、イベントをサブスクライブして、ホームボタンが押されたときのイベントを受信します。
namespace USEN.Games.Roulette
{
public class RouletteStartView : Widget
{
private async void Start()
{
UsenEvents.OnRemoconHomeButtonClicked += OnRemoconHomeButtonClicked;
}
private void OnRemoconHomeButtonClicked(object sender, EventArgs e)
{
Application.Quit();
}
}
}
これで、Homeキーを押すと、Unity 側の OnAndroidKeyDown メソッドが呼び出され、プログラムを終了することができます。