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

基于Firebase实时数据库的任务管理应用通知创建问题求助

问题描述

我正在使用Firebase Realtime Database开发一款任务管理应用,应用中任务的标题、描述、时间、日期均以字符串形式存储。以下是我用于创建日期时间、保存任务的代码,以及任务数据的Model类,目前在创建通知功能时遇到问题,寻求技术帮助。


新建任务页面(保存任务按钮)

saveButton.setOnClickListener((v) -> {
            String mTask = tskTitle.getText().toString().trim();
            String mDescription = tskDescription.getText().toString().trim();
            String id = DBrefrence.push().getKey();

            if (currentDate == null) {
                dateCurrentSelected = DateFormat.getDateInstance().format(new Date());
            } else if (currentDate != null) {
                dateCurrentSelected = currentDate;
            }
            if (FINAL_TIME == null) {
                TimeCurrent = timePickerBTN.getText().toString();
                //notificationtime = timePickerBTN.get
            } else if (FINAL_TIME != null) {
                TimeCurrent = FINAL_TIME;
            }
            String Time = FINAL_TIME;

            if (TextUtils.isEmpty(mTask)) {
                tskTitle.setError("Title Required");
                return;
            }
            if (TextUtils.isEmpty(mDescription)) {
                tskDescription.setError("Description Required");
                return;
            }
            else
            {
                pdLoader.setTitle("Saving Task");
                pdLoader.setMessage("Please wait");
                pdLoader.setCanceledOnTouchOutside(false);
                pdLoader.show();

                final int min = 10;
                final int max = 8000000;
                final int random = new Random().nextInt((max - min) + 1) + min;
                String UslID = String.valueOf(random);

                String EmptyId = "";

                Model model = new Model(mTask, mDescription, id, dateCurrentSelected, TimeCurrent,UslID, finalColorCard);
                DBrefrence.child(id).setValue(model).addOnCompleteListener(new OnCompleteListener<Void>() {
                    @Override
                    public void onComplete(@NonNull Task<Void> task) {
                        if (task.isSuccessful()) {
                            Intent intent = new Intent(NewTaskActivity.this, MainActivity.class);
                            startActivity(intent);
                            finish();
                            Toast.makeText(NewTaskActivity.this, "Task has been successfully added", Toast.LENGTH_SHORT).show();
                            pdLoader.dismiss();
                        } else {
                            Toast.makeText(NewTaskActivity.this, "Failed To Add Task", Toast.LENGTH_SHORT).show();
                            pdLoader.dismiss();
                        }
                    }
                });
            }
        });

以下是我创建日历和时间选择器的代码

日历选择回调

@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
    calendarUniversal = Calendar.getInstance();
    calendarUniversal.set(Calendar.YEAR, year);
    calendarUniversal.set(Calendar.MONTH, month);
    calendarUniversal.set(Calendar.DAY_OF_MONTH, dayOfMonth);
    currentDate = DateFormat.getDateInstance().format(calendarUniversal.getTime());
    datePickerBTN.setText(currentDate);
}

日历选择器类

public class DatePicker extends DialogFragment
{
    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        int Month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        return new DatePickerDialog(getActivity(), (DatePickerDialog.OnDateSetListener) getActivity(), year, Month, day);
    }
}

时间选择器对话框

timePickerBTN.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        TimePickerDialog timePickerDialog = new TimePickerDialog(NewTaskActivity.this, new TimePickerDialog.OnTimeSetListener() {
            @Override
            public void onTimeSet(TimePicker timePicker, int hourOfDay, int Minute) {
                TimeHour = hourOfDay;
                TimeMinute = Minute;
                calendarUniversal = Calendar.getInstance();
                calendarUniversal.set(0, 0, 0, TimeHour, TimeMinute);
                timePickerBTN.setText(android.text.format.DateFormat.format("hh:mm aa", calendarUniversal));
                FINAL_TIME = timePickerBTN.getText().toString();
            }
        }, 12, 0, false);
        timePickerDialog.updateTime(TimeHour, TimeMinute);
        timePickerDialog.show();
    }
});

任务数据的Model类

public class Model {
    private String task, description, id, date,time,UselessID, ColorCode;
    long notificationTime;

    public Model() {}

    public Model(String task, String description, String id, String date, String time, String UslID, String Tskcolor /*long notificationTime*/) {
        this.task = task;
        this.description = description;
        this.id = id;
        this.date = date;
        this.time = time;
        this.UselessID = UslID;
        this.ColorCode = Tskcolor;
//        this.notificationTime = notificationTime;
    }

    public String getTask() { return task; }
    public void setTask(String task) { this.task = task; }

    public String getDescription() { return description; }
    public void setDescription(String description) { this.description = description; }

    public String getColorCode() {return ColorCode;}
    public void setColorCode(String colorCode) {ColorCode = colorCode;}

    public String getId() { return id; }
    public void setId(String id) { this.id = id; }

    public String getUselessID() { return UselessID; }
    public void setUselessID(String uselessID) { UselessID = uselessID; }

    public String getDate() { return date; }
    public void setDate(String date) { this.date = date; }

    public String getTime() {return time;}
    public void setTime(String time) {this.time = time;}
}

通知功能解决方案

1. 存储时间戳而非纯字符串日期

当前代码中仅存储了日期时间的字符串格式,不利于定时通知计算,需修改为存储时间戳:

  • 取消Model类中notificationTime的注释,完善构造方法与getter/setter:
    private long notificationTime;
    
    public Model(String task, String description, String id, String date, String time, String UslID, String Tskcolor, long notificationTime) {
        // 保留原有字段赋值
        this.notificationTime = notificationTime;
    }
    
    public long getNotificationTime() { return notificationTime; }
    public void setNotificationTime(long notificationTime) { this.notificationTime = notificationTime; }
    
  • 修改时间选择回调,合并日期与时间计算时间戳:
    @Override
    public void onTimeSet(TimePicker timePicker, int hourOfDay, int Minute) {
        TimeHour = hourOfDay;
        TimeMinute = Minute;
        // 复用选择日期时的calendarUniversal实例,避免重新创建
        calendarUniversal.set(Calendar.HOUR_OF_DAY, TimeHour);
        calendarUniversal.set(Calendar.MINUTE, TimeMinute);
        calendarUniversal.set(Calendar.SECOND, 0);
        timePickerBTN.setText(android.text.format.DateFormat.format("hh:mm aa", calendarUniversal));
        FINAL_TIME = timePickerBTN.getText().toString();
        // 计算时间戳
        long notificationTimestamp = calendarUniversal.getTimeInMillis();
    }
    
  • 保存任务时传入时间戳:
    Model model = new Model(mTask, mDescription, id, dateCurrentSelected, TimeCurrent,UslID, finalColorCard, notificationTimestamp);
    

2. 实现定时通知逻辑

使用AlarmManager结合广播接收器触发通知:

  • 创建通知广播接收器:
    public class NotificationReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String taskTitle = intent.getStringExtra("task_title");
            String taskDesc = intent.getStringExtra("task_desc");
    
            NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "TASK_CHANNEL")
                    .setSmallIcon(R.drawable.ic_notification)
                    .setContentTitle(taskTitle)
                    .setContentText(taskDesc)
                    .setPriority(NotificationCompat.PRIORITY_DEFAULT);
    
            NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
            notificationManager.notify((int) System.currentTimeMillis(), builder.build());
        }
    }
    
  • 在AndroidManifest中注册接收器:
    <receiver android:name=".NotificationReceiver" />
    
  • 保存任务成功后设置定时任务:
    if (task.isSuccessful()) {
        // 原有跳转、Toast逻辑
        Intent notifyIntent = new Intent(NewTaskActivity.this, NotificationReceiver.class);
        notifyIntent.putExtra("task_title", mTask);
        notifyIntent.putExtra("task_desc", mDescription);
    
        PendingIntent pendingIntent = PendingIntent.getBroadcast(
                NewTaskActivity.this, 
                Integer.parseInt(UslID), 
                notifyIntent, 
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
        );
    
        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, notificationTimestamp, pendingIntent);
    }
    

3. 创建Android 8.0+通知渠道

在应用启动时初始化通知渠道:

private void createNotificationChannel() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        CharSequence name = "任务提醒";
        String description = "任务截止时间通知";
        int importance = NotificationManager.IMPORTANCE_DEFAULT;
        NotificationChannel channel = new NotificationChannel("TASK_CHANNEL", name, importance);
        channel.setDescription(description);

        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 11:35:55