システムのNight Modeの切り替え(方法:Settingsアプリ、API≧29)

投稿日:  更新日:

システムを対象としたNight Modeの切り替えは、SettingsアプリとUiModeManagerで行う方法がります。

ここでは、Settingsアプリを使った方法を説明します。

※Night Modeの切り替えの全体像は「Dark ThemeとNight Modeの関係」を参照

※環境:Android Studio Jellyfish | 2023.3.1
    Kotlin 1.9.0
    Compose Compiler 1.5.1
    androidx.compose.foundation:foundation 1.5.0
    Emulator 35.1.4-11672324

スポンサーリンク

切り替えの方法

SettingsアプリのDisplayページから行います。

スイッチをOn/Offして手動で切り替える方法と、スケジュール(切り替えの時刻)を定義して自動で切り替える方法が準備されています。

DarkとLight Modeの切り替え

ここで行われる切り替えはシステム全体(端末全体)に有効です。つまり、全アプリのモードが切り替わります。

スポンサーリンク

スケジュールの種類

定義できるスケジュールは4つです。

切り替えのスケジュール結果
手動
(API≧29)
Dark OnNight
Dark OffDay
自動
(API≧30)
None(手動)Dark OnNight
Dark OffDay
Turns on at custom time
Start時刻Day⇒Night
End時刻Night⇒Day
Thrns on from sunset to sunrise日の入時刻Day⇒Night
日の出時刻Night⇒Day
Turns on at bedtime
(API≧33)
就寝時刻Day⇒Night
起床時刻Night⇒Day
アプリ内で固定NightまたはDay
※isSystemInDarkTheme()はスケジュールによって切り替えられた結果を返す
  true:Night Mode、false:Day Mode
スポンサーリンク

スケジュール:None

スケジュールはありません。単なるOn/Offのスイッチ動作をします。

Night ModeのOn/Off

Onの時刻でDay⇒Nightへ、Offの時刻でNight⇒Dayへ遷移します。

スケジュール:Noneのタイムチャート

切り替えはOn/Offで即座に反映されます。

スポンサーリンク

スケジュール:Turns on at custon time

指定時刻(StartとEnd)に切り替えを行います。

Night ModeのStart/End

Startの時刻でDay⇒Nightへ、Endの時刻でNight⇒Dayへ遷移します。

スケジュール:Customのタイムチャート

切り替えはStart/Endで即座に反映されません。(後述)

スポンサーリンク

スケジュール:Turns on from suset to sunrise

現在地の「日の入」/「日の出」時刻に切り替えを行います。

Android端末は常に自身の地図上の位置を把握するように努めています。位置はGPSやネットワーク、電話のアクセスポイントなどから得ます。現在地は最後に確定した地図上の位置です。

現在地の確認は、Google Mapアプリを開き、現在値ボタンを押下すれば分かります。地図の中心が現在地です。

現在地のこよみ

日の入(Sunset)の時刻でDay⇒Nightへ、日の出(Sunrise)の時刻でNight⇒Dayへ遷移します。

スケジュール:SunsetSunriseのタイムチャート

切り替えは「日の入」/「日の出」で即座に反映されません。(後述)

スポンサーリンク

スケジュール:Turns on at bedtime

就寝/起床時刻に切り替えを行います。

Digital WellbeingツールはAPI29(Android 10)で追加されました。その中のBedtime Modeは就寝時の端末の振る舞いを変える機能です。

就寝時間はスケジュールや充電の有無で決まります。

Bedtime Mode

就寝の時刻でDay⇒Nightへ、起床の時刻でNight⇒Dayへ遷移します。

スケジュール:Bedtimeのタイムチャート

切り替えは就寝/起床で即座に反映されません。(後述)

エミュレータ(2024/05現在)はBedtimeの全機能をサポートしていないようです。

就寝時刻になった時に、ステータスバーへ通知は届きます。

しかし、グレースケール(画面のカスタマイズ機能)になりません。また、ダークテーマ(Night Mode)にもなりません。

スポンサーリンク

切り替えの反映

切り替えは、スクリーンがOffからOnになる時に反映されます。

例えば、「Powerボタン押下してスリープになり、再びPowerボタン押下してウェイクアップした時」などです。

切り替えのタイミング

ですので、アプリの使用中に、突発的に切り替わることはありません。

切り替えは構成の変更に伴って行われます。ですので、Activityは再作成されます。

スポンサーリンク

構成の変更

NightとDay Modeの切り替えが行われると、構成の変更が発生し、Activityが再作成されます。これにより、DarkとLight Themeが切り替わります。

Activityの再作成を行いたくなければ、Manifestファイルへ下記のように追記してください。

Activityの再作成は抑制され、onConfigurationChanged()がコールパックされます。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application ...>
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:label="@string/app_name"
            android:theme="@style/Theme.DarkMode"
			android:configChanges="uiMode">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
class MainActivity : ComponentActivity() {
    ...
    override fun onConfigurationChanged(newConfig: Configuration) {
        super.onConfigurationChanged(newConfig)

        val _nightMode = newConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK
        when(_nightMode) {
            Configuration.UI_MODE_NIGHT_NO -> {/* 処理 */}       // Night Mode
            Configuration.UI_MODE_NIGHT_YES -> {/* 処理 */}      // Day Mode
            Configuration.UI_MODE_NIGHT_UNDEFINED -> {/* 処理 */}
            else -> {}
        }
    }
	...
}

Jetpack Composeにおいて、Activityを再作成しない場合でも、LightとDark Themeが切り替わります。

これは、isSystemInDarkTheme()の出力が変わることで、Composable関数(UI要素)の状態が変化し、再Composeが行われるからです。

スポンサーリンク

付録:Settingsアプリを開く

プログラム中からSettinsアプリの関連ページを開くには、下記のようにします。

Displayページ

    /**
     * Activity Action: Show settings to allow configuration of display.
     * <p>
     * In some cases, a matching Activity may not exist, so ensure you
     * safeguard against this.
     * <p>
     * Input: Nothing.
     * <p>
     * Output: Nothing.
     */
    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_DISPLAY_SETTINGS =
            "android.settings.DISPLAY_SETTINGS";
    fun openSettingsDisplay() {
        startActivity(
            Intent(Settings.ACTION_DISPLAY_SETTINGS)
        )
    }

Dark themeページ

「Settings.ACTION_DARK_THEME_SETTINGS」は隠しパラメータ(@hide)です。一般のユーザーは、このパラメータを使えません。

しかし、パラメータは単なる文字列なので、文字列を直書きすれば開きます。

    /**
     * Activity Action: Show settings to allow configuration of Dark theme.
     * <p>
     * In some cases, a matching Activity may not exist, so ensure you
     * safeguard against this.
     * <p>
     * Input: Nothing.
     * <p>
     * Output: Nothing.
     *
     * @hide
     */
    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_DARK_THEME_SETTINGS =
            "android.settings.DARK_THEME_SETTINGS";
    @RequiresApi(Build.VERSION_CODES.R)
    fun openSettingsDarkTheme() {
        startActivity(
            Intent("android.settings.DARK_THEME_SETTINGS")	// 文字列を直書き
        )
    }
スポンサーリンク

付録:エミュレータで現在地の設定

エミュレータで現在地の設定を行う場合は、Extended Controlsパネルを使います。

パネルを開きます。

Extended Controlsパネルを開く

地図を目的の場所へ移動させて、ダブルクリックで場所を決定します。

エミュレータで現在地を設定する

“Set Location”の押下で、現在地として登録されます。

スポンサーリンク

関連記事:

「Android Studio Giraffe」の作成するプロジェクトは、Jetpack Composeの利用が推奨されます。 そして、作成されたプロジェクトは、Material Designeに準拠したテーマが指定されます。 ※環境:Android Studio Giraffe | 2022.3.1 Patch 1     Kotlin 1.8.10     Compose Compiler 1.4.3 ...
Android端末は自身の置かれている状況を認識して、ユーザーが使い易いように動作を変える仕組みを持ちます。 uiModeのNight(UI_MODE_NIGHT_YES:夜である)とDay(UI_MODE_NIGHT_NO:昼である) は、その「置かれている状況」の一つです。 NightとDayは古くから定義されているモードです。 API29で追加された機能の「Dark Theme」と結びついて、Night Modeの時はDark Themeにする使い方が定番になってしまいました。 その影響でしょうか... Settingsアプリを見ると、Night Modeの影が薄れて、「Drak Themeにする・しない」が主題に作られています。 しかし、裏にNight Modeが存在していることを忘れてはいけません。 ※環境:Android Studio Jellyfish | 2023.3.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation:foundation 1.5.0 ...
システムを対象としたNight Modeの切り替えは、SettingsアプリとUiModeManagerで行う方法がります。 ここでは、UiModeManagerを使った方法を説明します。 ※Night Modeの切り替えの全体像は「Dark ThemeとNight Modeの関係」を参照 ※環境:Android Studio Jellyfish | 2023.3.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation:foundation 1.5.0 ...
アプリを対象としたNight Modeの切り替えは、AppCompatDelegateとUiModeManagerで行う方法がります。 ここでは、UiModeManagerを使った方法を説明します。 ※Night Modeの切り替えの全体像は「Dark ThemeとNight Modeの関係」を参照 ※環境:Android Studio Jellyfish | 2023.3.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation:foundation 1.5.0 ...
アプリを対象としたNight Modeの切り替えは、AppCompatDelegateとUiModeManagerで行う方法がります。 ここでは、AppCompatDelegateを使った方法を説明します。 ※Night Modeの切り替えの全体像は「Dark ThemeとNight Modeの関係」を参照 ※環境:Android Studio Jellyfish | 2023.3.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.appcompat:appcompat 1.6.1 ...
Activityを対象としたNight Modeの切り替えは、AppCompatDelegateで行う方法があります。 ここでは、AppCompatDelegateを使った方法を説明します。 ※Night Modeの切り替えの全体像は「Dark ThemeとNight Modeの関係」を参照 ※環境:Android Studio Jellyfish | 2023.3.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.appcompat:appcompat 1.6.1 ...
スポンサーリンク