Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/208.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在应用程序关闭时每小时触发一次警报_Java_Android - Fatal编程技术网

Java 如何在应用程序关闭时每小时触发一次警报

Java 如何在应用程序关闭时每小时触发一次警报,java,android,Java,Android,我有一个生日应用程序,需要每天检查一次本地SharedReferences数据,看看某人的生日是不是那天 到目前为止,我正在尝试做一些简单的事情:每分钟发送一次测试通知,即使我点击后退按钮,向上滑动以关闭应用程序,打开另一个应用程序,关闭手机(而不是关机),等等。很多其他应用程序都会这样做 如果我能让每分钟的提醒都起作用,我就可以调整它来显示来自SharedReferences的数据,这没什么大不了的。然而,有一个问题: ALARMMANAGER根本没有按照他们在文档中所说的方式工作。 我在al

我有一个生日应用程序,需要每天检查一次本地SharedReferences数据,看看某人的生日是不是那天

到目前为止,我正在尝试做一些简单的事情:每分钟发送一次测试通知,即使我点击后退按钮,向上滑动以关闭应用程序,打开另一个应用程序,关闭手机(而不是关机),等等。很多其他应用程序都会这样做

如果我能让每分钟的提醒都起作用,我就可以调整它来显示来自SharedReferences的数据,这没什么大不了的。然而,有一个问题:

ALARMMANAGER根本没有按照他们在文档中所说的方式工作。

我在alarm manager中使用setInexactRepeating,并让它触发一个名为“ReminderAlarm”的类,然后启动一个创建通知通道并构建测试通知的服务。问题是,当我退出应用程序时,不会显示任何通知。但是,一旦我打开应用程序,他们就会因此,出于某种原因,除非应用程序打开,否则AlarmManager不会启动。(我也用Log.d尝试过这一点,如果应用程序打开,它也只会打印到日志中)

这是设置重复报警的原因:

 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_enter);
        ToggleButton toggle = (ToggleButton) findViewById(R.id.toggleButton);
        toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if(isChecked) {
                    setAlarm();
                } else {
                    cancelAlarm();
                }
            }
        });
    }

    private void setAlarm() {
        alarmManager = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(this, ReminderAlarm.class);
        pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
        alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), 100, pendingIntent);
    }

    private void cancelAlarm() {
        //alarmManager.cancel(pendingIntent);
    }
这是报警接收器:(在清单中定义为接收器)

这是提醒生成器服务:(它在清单中定义为服务)

通知应该每分钟显示一次(我知道setInexactRepeating不允许精确的重复计时),但它仅在应用程序打开时显示

最后,这里是Android清单xml

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

    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.SET_ALARM" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/main_icon"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/main_icon_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <receiver android:name=".ReminderAlarm"/>
        <activity android:name=".ListOfDaysActivity" />
        <activity android:name=".MainActivity" />
        <activity android:name=".EnterActivity"
            android:launchMode="singleInstance">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver android:name=".ReminderAlarm"/>
        <service android:name=".ReminderBuilderService"/>
    </application>
</manifest>


有什么我遗漏的吗?

您可以使用
JobScheduler
AlarmManager
来实现您想要的结果。但您应该使用的是
WorkManager
这两个版本的抽象,具体取决于Android版本

WorkManager
是高度可配置的,允许您创建
PeriodicWorkRequest
OneTimeWorkRequest
这些都保证成功<代码>PeriodicWorkRequest将在您安排工作时以及在计时器中指定时触发。即使应用程序关闭或处于后台,它也将在后台执行。如果您不想立即执行任务,可以使用PWR(PeriodicWorkRequest)和。有关更多信息,请参阅下面的文档

例如,我创建了两个PeriodicWorkRequests,它们刷新服务,并通过更新用户的令牌来保持用户始终登录。当用户进行身份验证时,将创建
周期性工作请求
。在我的例子中,我不需要立即启动它,因为他们刚刚收到并缓存了这些信息,所以我使用了FlexInterval。当应用程序处于后台或关闭状态时,工作人员继续每12小时刷新一次服务,每6小时刷新一次令牌。它就像一个符咒

以下是一个例子:

构建工作:

 override fun beginWork() {

        val periodicWorkRequest = PeriodicWorkRequest.Builder(
                MyWorker::class.java,
                REPEAT_INTERVAL, TimeUnit.MINUTES, // How often work should repeat
                // Flex not required.
                FLEX_INTERVAL, TimeUnit.MINUTES) // Limits execution into a time window
                .setConstraints(
                     Constraints.Builder().setRequiredNetworkType(
                                       NetworkType.CONNECTED).build())
                .addTag(MY_WORKER_TAG)
                .build()

        WorkManager.getInstance().enqueueUniquePeriodicWork(
                MY_UNIQUE_WORK,
                ExistingPeriodicWorkPolicy.KEEP,
                periodicLoginRequest)
class MyWorker(context: Context, params: WorkerParameters) : Worker(context, params) {

    override fun doWork(): Result {
            // DO WORK HERE

            Result.success()
        } else {
            // HANDLE FAILURE HERE
            Result.failure()
        }
工人:

 override fun beginWork() {

        val periodicWorkRequest = PeriodicWorkRequest.Builder(
                MyWorker::class.java,
                REPEAT_INTERVAL, TimeUnit.MINUTES, // How often work should repeat
                // Flex not required.
                FLEX_INTERVAL, TimeUnit.MINUTES) // Limits execution into a time window
                .setConstraints(
                     Constraints.Builder().setRequiredNetworkType(
                                       NetworkType.CONNECTED).build())
                .addTag(MY_WORKER_TAG)
                .build()

        WorkManager.getInstance().enqueueUniquePeriodicWork(
                MY_UNIQUE_WORK,
                ExistingPeriodicWorkPolicy.KEEP,
                periodicLoginRequest)
class MyWorker(context: Context, params: WorkerParameters) : Worker(context, params) {

    override fun doWork(): Result {
            // DO WORK HERE

            Result.success()
        } else {
            // HANDLE FAILURE HERE
            Result.failure()
        }

以上是一个简单的实现,但它应该能给您提供总体思路。

您可以使用
JobScheduler
AlarmManager
来实现所需的结果。但您应该使用的是
WorkManager
这两个版本的抽象,具体取决于Android版本

WorkManager
是高度可配置的,允许您创建
PeriodicWorkRequest
OneTimeWorkRequest
这些都保证成功<代码>PeriodicWorkRequest将在您安排工作时以及在计时器中指定时触发。即使应用程序关闭或处于后台,它也将在后台执行。如果您不想立即执行任务,可以使用PWR(PeriodicWorkRequest)和。有关更多信息,请参阅下面的文档

例如,我创建了两个PeriodicWorkRequests,它们刷新服务,并通过更新用户的令牌来保持用户始终登录。当用户进行身份验证时,将创建
周期性工作请求
。在我的例子中,我不需要立即启动它,因为他们刚刚收到并缓存了这些信息,所以我使用了FlexInterval。当应用程序处于后台或关闭状态时,工作人员继续每12小时刷新一次服务,每6小时刷新一次令牌。它就像一个符咒

以下是一个例子:

构建工作:

 override fun beginWork() {

        val periodicWorkRequest = PeriodicWorkRequest.Builder(
                MyWorker::class.java,
                REPEAT_INTERVAL, TimeUnit.MINUTES, // How often work should repeat
                // Flex not required.
                FLEX_INTERVAL, TimeUnit.MINUTES) // Limits execution into a time window
                .setConstraints(
                     Constraints.Builder().setRequiredNetworkType(
                                       NetworkType.CONNECTED).build())
                .addTag(MY_WORKER_TAG)
                .build()

        WorkManager.getInstance().enqueueUniquePeriodicWork(
                MY_UNIQUE_WORK,
                ExistingPeriodicWorkPolicy.KEEP,
                periodicLoginRequest)
class MyWorker(context: Context, params: WorkerParameters) : Worker(context, params) {

    override fun doWork(): Result {
            // DO WORK HERE

            Result.success()
        } else {
            // HANDLE FAILURE HERE
            Result.failure()
        }
工人:

 override fun beginWork() {

        val periodicWorkRequest = PeriodicWorkRequest.Builder(
                MyWorker::class.java,
                REPEAT_INTERVAL, TimeUnit.MINUTES, // How often work should repeat
                // Flex not required.
                FLEX_INTERVAL, TimeUnit.MINUTES) // Limits execution into a time window
                .setConstraints(
                     Constraints.Builder().setRequiredNetworkType(
                                       NetworkType.CONNECTED).build())
                .addTag(MY_WORKER_TAG)
                .build()

        WorkManager.getInstance().enqueueUniquePeriodicWork(
                MY_UNIQUE_WORK,
                ExistingPeriodicWorkPolicy.KEEP,
                periodicLoginRequest)
class MyWorker(context: Context, params: WorkerParameters) : Worker(context, params) {

    override fun doWork(): Result {
            // DO WORK HERE

            Result.success()
        } else {
            // HANDLE FAILURE HERE
            Result.failure()
        }

以上是一个简单的实现,但它应该能让您大致了解情况。

您能发布您的AndroidManifest.xml吗?@QuangNhat我编辑了我的文章,以包含xml文件。很抱歉最初没有包括它。只有当您的问题是关于IDE本身时,才使用
android studio
标记。您可以发布您的AndroidManifest.xml吗?@QuangNhat我编辑了我的帖子以包含xml文件。很抱歉最初没有包括它。仅当您的问题是关于IDE本身时才使用
android studio
标记非常感谢。我会调查的。我听说过工作经理,但我不确定“带灵活区间的PWR”isI更新了什么,并在上面添加了一些代码,如果这有帮助,请务必接受它作为答案。这很有效!!!非常感谢。问题的根源是,由于某种原因,我的通知没有正确生成,而工人没有被解雇。非常感谢。我会调查的。我听说过工作经理,但我不确定“带灵活区间的PWR”isI更新了什么,并在上面添加了一些代码,如果这有帮助,请务必接受它作为答案。这很有效!!!非常感谢。问题的根源是,由于某种原因,我的通知没有正确生成,而工人没有启动。