package com.unity3d.player.appui; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; import android.os.Build; import android.os.Bundle; import android.os.VibrationEffect; import android.os.Vibrator; import android.util.DisplayMetrics; import android.util.Log; import com.unity3d.player.UnityPlayer; import com.unity3d.player.UnityPlayerActivity; public class AppUIActivity extends UnityPlayerActivity { int m_CurrentUiMode = Configuration.UI_MODE_NIGHT_UNDEFINED; float m_CurrentFontScale = 1; float m_CurrentScaledDensity = 1; float m_CurrentDensity = 1; int m_CurrentDensityDpi = DisplayMetrics.DENSITY_DEFAULT; Vibrator m_Vibrator; public boolean IsNightModeDefined() { return m_CurrentUiMode != Configuration.UI_MODE_NIGHT_UNDEFINED; } public boolean IsNightModeEnabled() { return m_CurrentUiMode == Configuration.UI_MODE_NIGHT_YES; } public float FontScale() { return m_CurrentFontScale; } public float ScaledDensity() { return m_CurrentScaledDensity; } public float Density() { return m_CurrentDensity; } public int DensityDpi() { return m_CurrentDensityDpi; } void Vibrate(long[] timings, int repeat) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { m_Vibrator.vibrate(VibrationEffect.createWaveform(timings, repeat)); } else { m_Vibrator.vibrate(timings, repeat); } } void Vibrate(long[] timings) { Vibrate(timings, -1); } void Vibrate(long timing, int amplitude) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { m_Vibrator.vibrate(VibrationEffect.createOneShot(timing, amplitude)); } else { m_Vibrator.vibrate(timing); } } void Vibrate(long timing) { Vibrate(timing, -1); } public void RunHapticFeedback(int hapticFeedbackType) { switch (hapticFeedbackType) { case HapticFeedback.LIGHT: { Vibrate(HapticFeedback.lightTiming, HapticFeedback.lightAmplitude); break; } case HapticFeedback.MEDIUM: { Vibrate(HapticFeedback.mediumTiming, HapticFeedback.mediumAmplitude); break; } case HapticFeedback.HEAVY: { Vibrate(HapticFeedback.heavyTiming, HapticFeedback.heavyAmplitude); break; } case HapticFeedback.SUCCESS: { Vibrate(HapticFeedback.successTimings); break; } case HapticFeedback.ERROR: { Vibrate(HapticFeedback.errorTimings); break; } case HapticFeedback.WARNING: { Vibrate(HapticFeedback.warningTimings); break; } case HapticFeedback.SELECTION: { Vibrate(HapticFeedback.selectionTiming, HapticFeedback.lightAmplitude); break; } default: break; } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Resources resources = getResources(); Configuration configuration = resources.getConfiguration(); m_CurrentUiMode = configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK; m_CurrentFontScale = configuration.fontScale; m_Vibrator = resolveVibrator(); DisplayMetrics displayMetrics = resources.getDisplayMetrics(); m_CurrentScaledDensity = displayMetrics.scaledDensity; m_CurrentDensity = displayMetrics.density; m_CurrentDensityDpi = displayMetrics.densityDpi; Log.d("APP UI", "Initial Night Mode: " + m_CurrentUiMode); Log.d("APP UI", "Initial Font Scale: " + m_CurrentFontScale); Log.d("APP UI", "Initial Density: " + displayMetrics.density); Log.d("APP UI", "Initial Scaled Density: " + displayMetrics.scaledDensity); Log.d("APP UI", "Initial Density DPI: " + displayMetrics.densityDpi); } private Vibrator resolveVibrator() { Vibrator fallback = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); if (Build.VERSION.SDK_INT >= 31) { try { Object manager = getSystemService("vibrator_manager"); if (manager != null) { java.lang.reflect.Method method = manager.getClass().getMethod("getDefaultVibrator"); Object result = method.invoke(manager); if (result instanceof Vibrator) { return (Vibrator) result; } } } catch (Throwable throwable) { Log.w("APP UI", "Unable to access VibratorManager", throwable); } } return fallback; } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); boolean configurationChanged = false; int currentNightMode = newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK; if (m_CurrentUiMode != currentNightMode) { m_CurrentUiMode = currentNightMode; configurationChanged = true; switch (m_CurrentUiMode) { case Configuration.UI_MODE_NIGHT_NO: Log.d("APP UI", "Light Mode enabled"); break; case Configuration.UI_MODE_NIGHT_YES: Log.d("APP UI", "Dark Mode enabled"); break; case Configuration.UI_MODE_NIGHT_UNDEFINED: Log.d("APP UI", "Dark Mode is Undefined"); break; } } float currentFontScale = newConfig.fontScale; if (m_CurrentFontScale != currentFontScale) { m_CurrentFontScale = currentFontScale; configurationChanged = true; Log.d("APP UI", "Changed Font Scale : " + m_CurrentFontScale); } float currentScaledDensity = displayMetrics.scaledDensity; if (m_CurrentScaledDensity != currentScaledDensity) { m_CurrentScaledDensity = currentScaledDensity; configurationChanged = true; Log.d("APP UI", "Changed Scaled Density : " + m_CurrentScaledDensity); } float currentDensity = displayMetrics.density; if (m_CurrentDensity != currentDensity) { m_CurrentDensity = currentDensity; configurationChanged = true; Log.d("APP UI", "Changed Density : " + m_CurrentDensity); } int currentDensityDpi = newConfig.densityDpi; if (m_CurrentDensityDpi != currentDensityDpi) { m_CurrentDensityDpi = currentDensityDpi; configurationChanged = true; Log.d("APP UI", "Changed Density DPI : " + m_CurrentDensityDpi); } if (configurationChanged) { UnityPlayer.UnitySendMessage("AppUIUpdater", "OnAndroidNativeMessageReceived", "configurationChanged"); } } }