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

Android批量闹钟APP仅模拟器生效,真机仅创建首个闹钟求助

问题描述

我需要能随时便捷启用/停用时钟应用里的17个闹钟,但现有应用只能一次性删除所有闹钟或逐个停用,试了Play Store里的应用都存在这个问题。
临时方案是先删除现有闹钟,再通过代码按需重建这组闹钟。在Android Studio模拟器里运行完全正常,但打包调试APK安装到手机后,启动APP只能创建第一个闹钟,求帮忙分析原因。

硬件/软件环境

  • SAMSUNG Galaxy A3 (2017) SM-A320FL
  • Android Studio Dolphin 2021.3.1 Patch 1
  • Android 8.0.0 (Oreo)
  • Clock 7.0.92.7 (Galaxy Store)

代码实现

MainActivity.java

package com.example.setalarms;

import android.app.Activity;
import android.content.Intent;
import android.provider.AlarmClock;
import android.os.Bundle;
import java.util.ArrayList;
import java.util.Arrays;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        String[] messages = {"alarm1","alarm2to16","alarm17"};
        int[] hours = {7,8,9};
        int[] minutes = {0,0,0};
        ArrayList<Integer> days = new ArrayList<>(
                Arrays.asList(1,2,3,4,5,6,7)
        );
    
        Intent[] intents = new Intent[messages.length];
    
        for (int i = 0; i < messages.length; i++) {
            Intent intent = new Intent(AlarmClock.ACTION_SET_ALARM)
                    .putExtra(AlarmClock.EXTRA_MESSAGE, messages[i])
                    .putExtra(AlarmClock.EXTRA_HOUR, hours[i])
                    .putExtra(AlarmClock.EXTRA_MINUTES, minutes[i])
                    .putExtra(AlarmClock.EXTRA_DAYS, days)
                    .putExtra(AlarmClock.EXTRA_SKIP_UI, i != messages.length - 1);
            intents[i] = intent;
        }

        startActivities(intents);
    }
}

AndroidManifest.xml

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

    <uses-permission android:name="com.android.alarm.permission.SET_ALARM" />

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.SetAlarms"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <meta-data
                android:name="android.app.lib_name"
                android:value="" />
        </activity>
    </application>
</manifest>

问题分析与解决方案

核心原因

  1. startActivities的兼容性问题:模拟器和真实设备对批量Intent启动的处理逻辑不一致,Android 8.0及部分厂商定制系统会拦截连续的ACTION_SET_ALARM请求,仅处理第一个。
  2. 三星定制时钟应用限制:自带的Clock 7.0.92.7版本可能针对批量创建闹钟做了限制,不支持通过startActivities一次性处理多个请求。
  3. Extra参数复用问题:所有Intent共用同一个days列表对象,部分系统/应用可能存在对象引用复用的兼容性bug。

可行解决方案

方案1:逐个启动Intent并添加延迟

放弃startActivities,改用Handler逐个启动闹钟创建请求,给系统足够时间处理每个请求:

import android.os.Handler;
import android.os.Looper;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    String[] messages = {"alarm1","alarm2to16","alarm17"};
    int[] hours = {7,8,9};
    int[] minutes = {0,0,0};

    new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
        int index = 0;
        @Override
        public void run() {
            if (index >= messages.length) return;
            
            // 每个Intent创建独立的天数列表
            ArrayList<Integer> days = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7));
            Intent intent = new Intent(AlarmClock.ACTION_SET_ALARM)
                    .putExtra(AlarmClock.EXTRA_MESSAGE, messages[index])
                    .putExtra(AlarmClock.EXTRA_HOUR, hours[index])
                    .putExtra(AlarmClock.EXTRA_MINUTES, minutes[index])
                    .putExtra(AlarmClock.EXTRA_DAYS, days)
                    .putExtra(AlarmClock.EXTRA_SKIP_UI, index != messages.length - 1);
            
            startActivity(intent);
            
            index++;
            // 延迟500ms启动下一个,可根据实际情况调整
            new Handler(Looper.getMainLooper()).postDelayed(this, 500);
        }
    }, 100);
}

方案2:直接使用AlarmManager API创建闹钟(推荐)

绕过系统时钟应用的Intent限制,用AlarmManager直接创建闹钟,能更可靠地批量管理闹钟:

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import java.util.Calendar;

// 示例:批量创建重复闹钟
private void createAlarms() {
    String[] messages = {"alarm1","alarm2to16","alarm17"};
    int[] hours = {7,8,9};
    int[] minutes = {0,0,0};
    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

    for (int i = 0; i < messages.length; i++) {
        int alarmId = i; // 每个闹钟用唯一ID区分
        Intent alarmIntent = new Intent(this, AlarmReceiver.class);
        alarmIntent.putExtra("message", messages[i]);
        
        PendingIntent pendingIntent = PendingIntent.getBroadcast(
                this, alarmId, alarmIntent, 
                Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? 
                        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE : 
                        PendingIntent.FLAG_UPDATE_CURRENT
        );

        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, hours[i]);
        calendar.set(Calendar.MINUTE, minutes[i]);
        // 若当前时间已过,设置为第二天
        if (calendar.getTimeInMillis() < System.currentTimeMillis()) {
            calendar.add(Calendar.DAY_OF_YEAR, 1);
        }

        // 适配不同Android版本的闹钟API
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
        } else {
            alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
        }
    }
}

需要创建广播接收器AlarmReceiver(处理闹钟触发逻辑),并在Manifest中注册:

<receiver android:name=".AlarmReceiver" android:exported="false"/>

这种方式能完全控制闹钟的创建、启用和停用,比调用时钟应用Intent更稳定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 20:35:31