java - 如何设置来自应用程序的每天一次通知

标签 java android android-service alarmmanager android-alarms

我有一个关于在我的应用程序中设置每日数据检查(发生某些事件时发出通知)的一般性问题。

我目前的做法是:

  • 我从应用程序 (onCreate) 启动服务
  • 在检查是否已经存在匹配的 PendingIntent 后,我​​使用 AlarmManager 设置了一个警报(在这种情况下我没有 需要设置一个新闹钟)
  • 该服务检查来自 SharedPreferences 的数据并最终显示通知

出于测试目的,我将闹钟设置为 +1 分钟......但它并没有那样工作。也许我在概念上做错了什么?

一些代码

AndroidManifest.xml

<application
    <activity
        android:name=".OverviewActivity"
        android:label="@string/app_name"
        android:theme="@style/AppTheme.NoActionBar"
        android:configChanges="orientation"
        android:screenOrientation="portrait">

        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <service
        android:name="xxxxx.CheckDaysMonths" >
    </service>
</application>

服务 CheckDaysMonths

public class CheckDaysMonths extends Service {

    private static int ALARM_ID = 131313;
    private static String DECLARED_ACTION = "xxxxx.CheckDaysMonths";

    @Override
    public void onCreate() {
        super.onCreate();

        PendingIntent alarmIntent = AlarmHelper.getPendingIntentFromAlarm(this, ALARM_ID, DECLARED_ACTION);
        if(alarmIntent == null) {
           if(someConditionIsMet)
              sendNotification(" my notification text ");
           // Set an alarm for the next time this service should run:
           setAlarm();
        }

        stopSelf();
    }

    public void setAlarm() {

        AlarmHelper.setAlarm(this, ALARM_ID, DECLARED_ACTION, 8);
    }

    public void sendNotification(String notifyText) {

        Intent mainIntent = new Intent(this, OverviewActivity.class);
        @SuppressWarnings("deprecation")
        Notification noti = new Notification.Builder(this)
                .setAutoCancel(true)
                .setContentIntent(PendingIntent.getActivity(this, 131314, mainIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT))
                .setContentTitle("Gratuliere!")
                .setContentText("Du bist seit " + notifyText + " rauchfrei!")
                .setDefaults(Notification.DEFAULT_ALL)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setTicker("Du bist seit " + notifyText + " rauchfrei!")
                .setWhen(System.currentTimeMillis())
                .getNotification();

        NotificationManager notificationManager
                = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(131315, noti);

    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

在主 Activity 中(OverviewActivity.java)

编辑:将服务调用从隐式更改为显式

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_overview);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    startService(new Intent(this, CheckDaysMonths.class));


    // additional stuff happening on the activity of my app goes here:
    ...
}

AlarmHelper.java

public class AlarmHelper {

    public static PendingIntent getPendingIntentFromAlarm(Context context, int alarmId, String declaredAction) {
        return (PendingIntent.getService(context, alarmId,
                new Intent(declaredAction),
                PendingIntent.FLAG_NO_CREATE));
    }

    public static void setAlarm(Context context, int alarmId, String declaredAction, int hourOfDay) {
        Intent serviceIntent = new Intent(declaredAction);
        PendingIntent pi = PendingIntent.getService(context, alarmId, serviceIntent,
                PendingIntent.FLAG_UPDATE_CURRENT);

        // How long until tomorrow to its hourOfDay?
        //DateTime tomorrow = (new DateTime()).plusDays(1);
        //DateTime tomorrowAtHourOfDay = new DateTime(tomorrow.getYear(), tomorrow.getMonthOfYear(), tomorrow.getDayOfMonth(), hourOfDay, 0);

        DateTime tomorrowAtHourOfDay = (new DateTime()).plusHours(3);

        AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        am.set(AlarmManager.RTC_WAKEUP, tomorrowAtHourOfDay.getMillis(), pi);
    }
}

最佳答案

我通过引入另一个“中间层”服务来修复它

现在我有

  • 应用程序 GUI 启动服务 1
  • 服务 1 将检查是否已经有运行正确签名的警报。如果没有,它将启动警报
  • 闹钟将在凌晨 2 点响起并开始服务 2
  • 服务 2 将检查数据 (SharedPreferences) 并最终发送通知。然后它会再次启动警报
  • BOOT 的 BroadcastReceiver 启动服务 2

这很好用

关于java - 如何设置来自应用程序的每天一次通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35199054/

相关文章:

java - 如何在 Windows 上从命令行运行 Java 程序?

java - 如何覆盖struts 2.2.3.1文件上传消息?

android - NDK原生代码具体执行在哪里

java - 无法从包含 DEX 和 Java 字节码内容的 archive\app\libs\appodeal-2.1.11.jar' 创建 android 应用程序

android - 奇巧 : Service is null after exiting main activity

android - 当用户通过 android 中的任务滑动删除应用程序时执行注销

java - Android Java - 无法捕获异常

java - 对象和实例是一回事吗?

android - 如何使用 Camera API 实现 SlowMotion 和 TimeLapse 视频录制

android - 当应用程序被杀死时,Job Scheduler 服务不工作