You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

Android Java时钟应用:带随机数学题的闹钟贪睡功能实现咨询

嘿,这个需求挺实用的——能有效防止用户迷迷糊糊按贪睡继续睡过头~我来给你拆解一下实现步骤,附带具体代码示例:

整体核心思路

整个流程其实很清晰:闹钟触发后 → 弹出一个带随机数学题的全屏界面 → 用户输入答案验证通过后,才允许执行贪睡关闭操作。核心就是把「一键操作」改成「验证后操作」,下面是具体实现细节:

分步实现细节

1. 写一个随机数学题生成工具类

首先需要一个能生成合法数学题的工具,要保证题目简单(用户刚醒状态)、结果为正整数,避免负数或小数增加输入成本。这里给你写个基础版本:

public class MathQuestionGenerator {
    private final Random random = new Random();
    private int num1;
    private int num2;
    private char operator;
    private int correctAnswer;

    // 生成新题目
    public void generateNewQuestion() {
        // 生成1-20的随机数,范围可以自行调整
        num1 = random.nextInt(20) + 1;
        num2 = random.nextInt(20) + 1;

        // 随机选择运算符(加减乘,除法可以后续扩展,需保证整除)
        int opType = random.nextInt(3);
        switch (opType) {
            case 0:
                operator = '+';
                correctAnswer = num1 + num2;
                break;
            case 1:
                // 减法确保结果非负,避免用户输入负数
                if (num1 < num2) {
                    int temp = num1;
                    num1 = num2;
                    num2 = temp;
                }
                operator = '-';
                correctAnswer = num1 - num2;
                break;
            case 2:
                operator = '*';
                correctAnswer = num1 * num2;
                break;
        }
    }

    // 获取题目文本(比如"15 + 7 = ?")
    public String getQuestionText() {
        return num1 + " " + operator + " " + num2 + " = ?";
    }

    // 验证用户答案是否正确
    public boolean isAnswerCorrect(int userInput) {
        return userInput == correctAnswer;
    }
}

2. 闹钟触发时启动答题界面

你的闹钟逻辑应该是用AlarmManagerWorkManager触发的,触发后要启动一个全屏且能在锁屏显示的Activity(毕竟闹钟响时用户大概率是锁屏状态)。

比如在闹钟触发的广播接收器里:

public class AlarmReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // 启动答题界面
        Intent questionIntent = new Intent(context, MathQuestionActivity.class);
        // 确保在锁屏/后台能启动
        questionIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 
                | Intent.FLAG_ACTIVITY_SCREEN_ON 
                | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
        context.startActivity(questionIntent);
        
        // 这里可以同时启动闹钟铃声播放逻辑,比如用MediaPlayer
    }
}

别忘了在AndroidManifest.xml里给答题Activity配置锁屏显示权限:

<activity
    android:name=".MathQuestionActivity"
    android:showOnLockScreen="true"
    android:turnScreenOn="true"
    android:excludeFromRecents="true"
    android:launchMode="singleInstance"
    android:theme="@style/Theme.AppCompat.Light.NoActionBar.Fullscreen">
</activity>

还需要申请唤醒权限:<uses-permission android:name="android.permission.WAKE_LOCK" />(Android 12+还需POST_NOTIFICATIONS权限)

3. 答题界面的布局与逻辑

先写布局文件activity_math_question.xml,要简洁直观:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="24dp"
    android:background="#FFF">

    <TextView
        android:id="@+id/tv_question"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="36sp"
        android:textStyle="bold"
        android:layout_marginBottom="32dp"/>

    <EditText
        android:id="@+id/et_answer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="请输入答案"
        android:inputType="number"
        android:textSize="32sp"
        android:minWidth="150dp"/>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginTop="48dp">

        <Button
            android:id="@+id/btn_snooze"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="贪睡"
            android:textSize="20sp"
            android:paddingHorizontal="24dp"/>

        <Button
            android:id="@+id/btn_dismiss"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="关闭"
            android:textSize="20sp"
            android:paddingHorizontal="24dp"
            android:layout_marginStart="24dp"/>
    </LinearLayout>

</LinearLayout>

然后是Activity的核心逻辑:

public class MathQuestionActivity extends AppCompatActivity {
    private MathQuestionGenerator questionGenerator;
    private TextView tvQuestion;
    private EditText etAnswer;

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

        initViews();
        questionGenerator = new MathQuestionGenerator();
        loadNewQuestion();

        // 绑定按钮点击事件
        findViewById(R.id.btn_snooze).setOnClickListener(v -> handleAction(true));
        findViewById(R.id.btn_dismiss).setOnClickListener(v -> handleAction(false));
    }

    private void initViews() {
        tvQuestion = findViewById(R.id.tv_question);
        etAnswer = findViewById(R.id.et_answer);
    }

    // 加载新题目
    private void loadNewQuestion() {
        questionGenerator.generateNewQuestion();
        tvQuestion.setText(questionGenerator.getQuestionText());
        etAnswer.setText(""); // 清空输入框
    }

    // 处理贪睡/关闭操作
    private void handleAction(boolean isSnooze) {
        String inputStr = etAnswer.getText().toString().trim();
        if (inputStr.isEmpty()) {
            Toast.makeText(this, "请输入答案", Toast.LENGTH_SHORT).show();
            return;
        }

        int userAnswer;
        try {
            userAnswer = Integer.parseInt(inputStr);
        } catch (NumberFormatException e) {
            Toast.makeText(this, "请输入有效数字", Toast.LENGTH_SHORT).show();
            return;
        }

        if (questionGenerator.isAnswerCorrect(userAnswer)) {
            // 答案正确,执行对应操作
            if (isSnooze) {
                // 设置5分钟后贪睡闹钟,复用你原来的闹钟设置逻辑
                setSnoozeAlarm();
            }
            // 停止闹钟铃声
            stopAlarmSound();
            finish(); // 关闭答题界面
        } else {
            Toast.makeText(this, "答案错误,请重试", Toast.LENGTH_SHORT).show();
            loadNewQuestion(); // 错误则换一道题
        }
    }

    // 设置贪睡闹钟
    private void setSnoozeAlarm() {
        AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
        Intent intent = new Intent(this, AlarmReceiver.class);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(
                this, 0, intent, 
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);

        // 5分钟后触发
        long snoozeTime = System.currentTimeMillis() + 5 * 60 * 1000;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, snoozeTime, pendingIntent);
        } else {
            alarmManager.setExact(AlarmManager.RTC_WAKEUP, snoozeTime, pendingIntent);
        }
    }

    // 停止闹钟铃声(根据你实际的播放方式调整)
    private void stopAlarmSound() {
        // 示例:如果你用MediaPlayer播放铃声
        // if (MediaPlayerHolder.getInstance().isPlaying()) {
        //     MediaPlayerHolder.getInstance().stop();
        // }
    }
}

4. 额外注意事项

  • Android版本适配:不同版本对后台启动、锁屏显示的权限限制不同,比如Android 12+需要SCHEDULE_EXACT_ALARM权限才能使用精确闹钟。
  • 铃声播放:要确保铃声在答题界面显示时持续播放,直到用户答对后停止,建议用单例模式管理MediaPlayer。
  • 题目难度扩展:如果想增加难度,可以加入除法(需保证整除)、混合运算,或者让用户选择难度等级。

内容的提问来源于stack exchange,提问作者D. C

火山引擎 最新活动