You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android第三方APP如何判断设备夜间模式及定时切换夜间模式?

Android原生夜间模式判断与自动切换方案

嘿,好问题!Android确实提供了原生方式来判断设备的夜间模式状态,而且针对你需要根据日出日落自动切换应用内夜间模式的需求,这里有一套完整的解决方案:

一、判断当前设备夜间模式状态

首先,你可以通过系统的Configuration类直接获取当前夜间模式的激活状态,代码如下:

// 获取当前应用的Configuration对象
Configuration config = getResources().getConfiguration();
// 按位与操作判断是否处于夜间模式
boolean isNightModeActive = (config.uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;

二、监听夜间模式的系统切换

如果你的应用需要跟随系统夜间模式的变化同步更新,可以在Activity中重写onConfigurationChanged方法,监听配置变化:

@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    // 检查夜间模式是否发生变化
    boolean isNowNightMode = (newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
    // 调用你的夜间模式更新逻辑
    updateAppNightMode(isNowNightMode);
}

注意:需要在AndroidManifest.xml的对应Activity标签中添加android:configChanges="uiMode",避免Activity重启。

三、根据日出日落时间自动切换(你的核心需求)

要实现按日出日落自动切换,需要三个关键步骤:获取地理位置、计算日出日落时间、设置定时任务触发切换。

1. 获取用户地理位置

首先需要获取用户的经纬度(需要申请位置权限ACCESS_FINE_LOCATION或ACCESS_COARSE_LOCATION):

LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
    Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
    if (lastKnownLocation != null) {
        // 传入经纬度计算日出日落
        calculateSunriseSunset(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude());
    }
}

2. 计算日出日落时间

Android原生没有直接提供日出日落计算的API,你可以实现一套天文算法(比如基于Julian日期的计算逻辑),或者使用简化的模拟逻辑(以下示例为模拟,实际需替换为真实计算):

private void calculateSunriseSunset(double latitude, double longitude) {
    Calendar today = Calendar.getInstance();
    TimeZone localTz = today.getTimeZone();
    
    // 模拟计算当天日出(6:00)和日落(18:00)的时间戳
    Calendar sunriseCal = (Calendar) today.clone();
    sunriseCal.set(Calendar.HOUR_OF_DAY, 6);
    sunriseCal.set(Calendar.MINUTE, 0);
    long sunriseTimestamp = sunriseCal.getTimeInMillis();
    
    Calendar sunsetCal = (Calendar) today.clone();
    sunsetCal.set(Calendar.HOUR_OF_DAY, 18);
    sunsetCal.set(Calendar.MINUTE, 0);
    long sunsetTimestamp = sunsetCal.getTimeInMillis();
    
    // 调度夜间模式切换任务
    scheduleNightModeToggle(true, sunsetTimestamp);
    scheduleNightModeToggle(false, sunriseTimestamp);
}

3. 用WorkManager设置可靠定时任务

推荐使用WorkManager来调度定时任务,它能处理设备重启、应用被杀等场景,确保任务执行:

private void scheduleNightModeToggle(boolean enableNightMode, long triggerTime) {
    // 传递切换参数
    Data inputData = new Data.Builder()
            .putBoolean("ENABLE_NIGHT_MODE", enableNightMode)
            .build();
    
    // 创建一次性任务
    OneTimeWorkRequest toggleRequest = new OneTimeWorkRequest.Builder(NightModeWorker.class)
            .setInitialDelay(triggerTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS)
            .setInputData(inputData)
            .build();
    
    // 加入任务队列
    WorkManager.getInstance(this).enqueue(toggleRequest);
}

// 定义执行切换的Worker类
public static class NightModeWorker extends Worker {
    public NightModeWorker(@NonNull Context context, @NonNull WorkerParameters params) {
        super(context, params);
    }

    @NonNull
    @Override
    public Result doWork() {
        boolean enableNightMode = getInputData().getBoolean("ENABLE_NIGHT_MODE", false);
        UiModeManager uiManager = (UiModeManager) getApplicationContext().getSystemService(Context.UI_MODE_SERVICE);
        
        // 执行夜间模式切换(注意:你的原代码中enableCarMode/disableCarMode和夜间模式无关,可移除)
        if (enableNightMode) {
            uiManager.setNightMode(UiModeManager.MODE_NIGHT_YES);
        } else {
            uiManager.setNightMode(UiModeManager.MODE_NIGHT_NO);
        }
        
        // 第二天重新计算并调度任务,确保每天的时间准确
        // 这里可再次调用calculateSunriseSunset方法(需处理位置获取逻辑)
        return Result.success();
    }
}

额外注意事项

  • 权限处理:务必在运行时申请位置权限,否则无法获取经纬度计算日出日落
  • 设备重启适配:监听BOOT_COMPLETED广播,在设备重启后重新调度任务
  • 冗余代码清理:你原代码中的enableCarMode和disableCarMode是用于车载模式的,和夜间模式无关,可以移除

内容的提问来源于stack exchange,提问作者SimpleCoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:47:27