在安卓应用中创建一个通知,即使应用被关闭,每天在特定时间重复出现。

huangapple go评论76阅读模式
英文:

Creating an android notification that reoccurs every day at some time even when app is closed

问题

在这个主题上有很多过时的回答(1-4年前)。

我的代码如下所示:

Intent notifyIntent = new Intent(this, MyReceiver.class);

PendingIntent pendingIntent = PendingIntent.getBroadcast(this, NOTIFICATION_REMINDER, 
notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);

Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, hours);
calendar.set(Calendar.MINUTE, minutes);
calendar.set(Calendar.SECOND, seconds);

AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,  calendar.getTimeInMillis(),
     AlarmManager.INTERVAL_DAY,
     pendingIntent); 

我的广播接收器如下所示:

public class MyReceiver extends BroadcastReceiver {
    public MyReceiver() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("Test", "RAN");
        Intent intent1 = new Intent(context, MyNewIntentService.class);
        context.startService(intent1);
    }
}

我的IntentService如下所示:

public class MyNewIntentService extends IntentService {
    private static final int NOTIFICATION_ID = 3;

    public MyNewIntentService() {
        super("MyNewIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        NotificationManager mNotificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel("SH",
                    "Simple",
                    NotificationManager.IMPORTANCE_DEFAULT);
            channel.setDescription("Notifs");
            mNotificationManager.createNotificationChannel(channel);
        }

        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext(), "SH")
                .setSmallIcon(R.mipmap.ic_launcher) // notification icon
                .setContentTitle("Title") // title for notification
                .setContentText("Message")// message for notification
                .setAutoCancel(true); // clear notification after click
        Intent intent1 = new Intent(getApplicationContext(), MainActivity.class);
        PendingIntent pi = PendingIntent.getActivity(this, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
        mBuilder.setContentIntent(pi);
        mNotificationManager.notify(0, mBuilder.build());

    }
}

我已经在我的AndroidManifest.xml文件中,在应用程序标签中的活动下面添加了以下内容:

<receiver
    android:name=".MyReceiver"
    android:enabled="true"
    android:exported="true" >
</receiver>
<service
    android:name=".MyNewIntentService"
    android:exported="false" >
</service>

通知在应用程序开启时会触发,但在应用关闭时不会。根据Android文档,Android似乎试图限制后台处理和应用程序的定时,因此AlarmManager不会在准确的时间运行。

我如何将此转变为一个可靠的通知提醒,即使在应用程序关闭时也能在几乎相同的时间每天运行?

英文:

A lot of questions on this topic have outdated answers (1-4 years old).

https://stackoverflow.com/questions/34517520/how-to-give-notifications-on-android-on-specific-time

https://stackoverflow.com/questions/51343550/how-to-give-notifications-on-android-on-specific-time-in-android-oreo?noredirect=1&amp;lq=1

https://stackoverflow.com/questions/41643743/repeat-notification-every-day-12h?rq=1

The documentation for android did not lead me to specific solutions but helped me understand AlarmManager and the NotificationCompat. My code looks like this in my MainActivity

Intent notifyIntent = new Intent(this, MyReceiver.class);

PendingIntent pendingIntent = PendingIntent.getBroadcast(this, NOTIFICATION_REMINDER, 
notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);

Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, hours);
calendar.set(Calendar.MINUTE, minutes);
calendar.set(Calendar.SECOND, seconds);

AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,  calendar.getTimeInMillis(),
     AlarmManager.INTERVAL_DAY,
     pendingIntent); 

My BroadcastReceiver looks like this

public class MyReceiver extends BroadcastReceiver {
    public MyReceiver() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(&quot;Test&quot;, &quot;RAN&quot;);
        Intent intent1 = new Intent(context, MyNewIntentService.class);
        context.startService(intent1);
    }
}

My IntentService looks like this

public class MyNewIntentService extends IntentService {
private static final int NOTIFICATION_ID = 3;
public MyNewIntentService() {
super(&quot;MyNewIntentService&quot;);
}
@Override
protected void onHandleIntent(Intent intent) {
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT &gt;= android.os.Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(&quot;SH&quot;,
&quot;Simple&quot;,
NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription(&quot;Notifs&quot;);
mNotificationManager.createNotificationChannel(channel);
}
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext(), &quot;SH&quot;)
.setSmallIcon(R.mipmap.ic_launcher) // notification icon
.setContentTitle(&quot;Title&quot;) // title for notification
.setContentText(&quot;Message&quot;)// message for notification
.setAutoCancel(true); // clear notification after click
Intent intent1 = new Intent(getApplicationContext(), MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(pi);
mNotificationManager.notify(0, mBuilder.build());
}
}

I've added these to my AndroidManifest.xml right under my activity within the application tag

&lt;receiver
android:name=&quot;.MyReceiver&quot;
android:enabled=&quot;true&quot;
android:exported=&quot;true&quot; &gt;
&lt;/receiver&gt;
&lt;service
android:name=&quot;.MyNewIntentService&quot;
android:exported=&quot;false&quot; &gt;
&lt;/service&gt;

The notification fires for me but does not when the app is closed. In the android documentation, it seems like android has tried to limit the amount of background processing and timing of apps and the AlarmManager does not run at an accurate time because of this.

How do I make this into a reliable notification reminder for my app that runs at nearly the same time every day even when the app is closed?

答案1

得分: 0

你就快成功了,非常接近,只有一件事情需要修改。
不要使用 startService(),而应该使用 startForegrounService()。这样,你的闹钟将始终会触发。以下是一些建议:

  1. 你应该在清单文件中声明前台服务。
  2. 对于 API 等级高于 23 的情况,你必须使用 alarmManager.setExactAndAllowWhileIdle 方法。

你还可以查看这个链接以获取更多信息。

更新:这个方法在小米 Redmi Note 8 上对我起作用,但突然间就停止工作了!对于定制的操作系统设备,此方法可能不是一个非常可靠的解决方案。希望 Google 能够提出一个稳固的解决方案。

英文:

You are almost there. Very close just one more thing.
Instead of startService() you should use startForegrounService(). In that case your alarm will always fire. Just a few tips:

  1. you should declare the foreground service in your manifest
  2. You have to use alarmManager.setExactAndAllowWhileIdle for API level higher than 23

You can also check this out for more information.

Update: This method worked forme on Xiaomi Redme note 8, but the just suddenly stopped working! It may not be a very dependable solution for custom OS devices at the moment. Hope google come up with a solid solution.

huangapple
  • 本文由 发表于 2020年8月16日 06:06:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/63431234.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定