如何在特定时间在Android上发出通知?

adm*_*798 24 android android-notifications

我想在特定时间通知我的应用.每天说我必须在上午7点发出通知,即使该应用程序已关闭.

我怎样才能做到这一点?任何教程?请提及链接.

小智 26

首先,您需要使用广播接收器.并且因为广播接收器只能在短时间内启动

来自android开发人员博客.当处理广播时,应用程序将获得一组固定的时间(当前为10秒)来完成其工作.如果它在那段时间内没有完成,那么应用程序被认为是行为不端,并且如果需要,它的进程立即被抛入后台状态以便为内存被杀死.

在这里使用意图服务是一个更好的做法,你有一个例子如何做到这一点.

这是广播接收器类.

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

    @Override
    public void onReceive(Context context, Intent intent) {

        Intent intent1 = new Intent(context, MyNewIntentService.class);
        context.startService(intent1);
    }
}
Run Code Online (Sandbox Code Playgroud)

并在清单中注册.

<receiver
    android:name=".MyReceiver"
    android:enabled="true"
    android:exported="false" >
</receiver>
Run Code Online (Sandbox Code Playgroud)

这是意图服务类.

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

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

    @Override
    protected void onHandleIntent(Intent intent) {
        Notification.Builder builder = new Notification.Builder(this);
            builder.setContentTitle("My Title");
            builder.setContentText("This is the Body");
            builder.setSmallIcon(R.drawable.whatever);
        Intent notifyIntent = new Intent(this, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 2, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        //to be able to launch your activity from the notification 
        builder.setContentIntent(pendingIntent);
        Notification notificationCompat = builder.build();
        NotificationManagerCompat managerCompat = NotificationManagerCompat.from(this);
        managerCompat.notify(NOTIFICATION_ID, notificationCompat);
    }
}
Run Code Online (Sandbox Code Playgroud)

并在清单中注册.

<service
    android:name=".MyNewIntentService"
    android:exported="false" >
</service>
Run Code Online (Sandbox Code Playgroud)

然后在你的活动中设置闹钟管理器以在特定时间启动广播接收器并使用AlarmManager setRepeating方法重复此示例,下面将每天重复它.

 Intent notifyIntent = new Intent(this,MyReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast
            (context, NOTIFICATION_REMINDER_NIGHT, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,  System.currentTimeMillis(),
            1000 * 60 * 60 * 24, pendingIntent);
Run Code Online (Sandbox Code Playgroud)

我希望这能帮到您.

  • 不适合我,尝试手动设置时间但仍然无法正常工作。 (2认同)

Vas*_*nov 15

由于后台服务限制(https://developer.android.com/about/versions/oreo/background.html#services),所接受答案的解决方案将无法在Android 8 Oreo(api level 26)及更高版本上正常运行当应用程序在后台时会导致这样的异常:

java.lang.IllegalStateException: Not allowed to start service Intent xxx: app is in background
Run Code Online (Sandbox Code Playgroud)

可能的解决方法之一是使用JobIntentService:

  1. 扩展你ServiceJobIntentService而不是IntentService和使用onHandleWork方法而不是onHandleIntent.

  2. 加入android:permission="android.permission.BIND_JOB_SERVICE"ServiceAndroidManifest.xml.


SaN*_*iaN 10

您可以使用AlarmManager在指定时间设置警报

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
if (!prefs.getBoolean("firstTime", false)) {

    Intent alarmIntent = new Intent(this, AlarmReceiver.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);

    AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis());
    calendar.set(Calendar.HOUR_OF_DAY, 7);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 1);

    manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
            AlarmManager.INTERVAL_DAY, pendingIntent);

    SharedPreferences.Editor editor = prefs.edit();
    editor.putBoolean("firstTime", true);
    editor.apply();
}
Run Code Online (Sandbox Code Playgroud)

我曾经SharedPreferences检查过这不是第一次运行应用程序,如果是,你设置该警报,否则什么也不做,而不是每次启动你的应用程序时重置警报.发生警报时
使用a BroadcastReceiver

public class AlarmReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // show toast
        Toast.makeText(context, "Alarm running", Toast.LENGTH_SHORT).show();
    }
}
Run Code Online (Sandbox Code Playgroud)

使用另一个接收器收听设备启动,以便您可以重置警报

public class DeviceBootReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
            // on device boot compelete, reset the alarm
            Intent alarmIntent = new Intent(context, AlarmReceiver.class);
            PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);

            AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

            Calendar calendar = Calendar.getInstance();
            calendar.setTimeInMillis(System.currentTimeMillis());
            calendar.set(Calendar.HOUR_OF_DAY, 7);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 1);

            manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
                    AlarmManager.INTERVAL_DAY, pendingIntent);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

将权限添加到清单

<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Run Code Online (Sandbox Code Playgroud)

然后注册您的接收器

<receiver android:name=".DeviceBootReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>
<receiver android:name=".AlarmReceiver" />
Run Code Online (Sandbox Code Playgroud)


4xM*_*ole 6

这是我的解决方案,在android 10上进行了测试,但与所有以前的 android 版本兼容。

MainActivity.class

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    ....
    reminderNotification();

}

public void reminderNotification()
{
    NotificationUtils _notificationUtils = new NotificationUtils(this);
    long _currentTime = System.currentTimeMillis();
    long tenSeconds = 1000 * 10;
    long _triggerReminder = _currentTime + tenSeconds; //triggers a reminder after 10 seconds.
    _notificationUtils.setReminder(_triggerReminder);
}
Run Code Online (Sandbox Code Playgroud)

通知实用程序类

public class NotificationUtils extends ContextWrapper
{

    private NotificationManager _notificationManager;
    private Context _context;

    public NotificationUtils(Context base)
    {
        super(base);
        _context = base;
        createChannel();
    }

    public NotificationCompat.Builder setNotification(String title, String body)
    {
        return new NotificationCompat.Builder(this, CHANNEL_ID)
                .setSmallIcon(R.drawable.noti_icon)
                .setContentTitle(title)
                .setContentText(body)
                .setAutoCancel(true)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT);
    }

    private void createChannel()
    {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
        {
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID, TIMELINE_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
            channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
            getManager().createNotificationChannel(channel);
        }
    }

    public NotificationManager getManager()
    {
        if(_notificationManager == null)
        {
            _notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        }

        return _notificationManager;
    }

    public void setReminder(long timeInMillis)
    {
        Intent _intent = new Intent(_context, ReminderBroadcast.class);
        PendingIntent _pendingIntent = PendingIntent.getBroadcast(_context, 0, _intent, 0);

        AlarmManager _alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);

        _alarmManager.set(AlarmManager.RTC_WAKEUP, timeInMillis, _pendingIntent);
    }

}
Run Code Online (Sandbox Code Playgroud)

ReminderBroadcast.class

public class ReminderBroadcast extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        NotificationUtils _notificationUtils = new NotificationUtils(context);
        NotificationCompat.Builder _builder = _notificationUtils.setNotification("Testing", "Testing notification system");
        _notificationUtils.getManager().notify(101, _builder.build());
    }
}
Run Code Online (Sandbox Code Playgroud)

AndroidManifest.xml

<application>
    ...
    <receiver android:name=".custom.ReminderBroadcast"/>
</application>
Run Code Online (Sandbox Code Playgroud)

注意:CHANNEL_IDTIMELINE_CHANNEL_NAME,已在另一个类上创建。

例如,

CHANNEL_ID = "notification channel";

TIMELINE_CHANNEL_NAME = "Timeline notification";

如果对我的代码和错误有任何误解,请随时发表评论。我会尽快回复。