Обновление Android-виджета в полночь

Как обновить Android-виджет каждый день в полночь ?? Ниже решения формируется путем просмотра других вопросов при переполнении стека по этой теме.

1) расписание (контекст) вызывается, когда виджет создается в активности, которая расширяет AppWidgetProvider

public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { final int N = appWidgetIds.length; schedule(context); super.onUpdate(context, appWidgetManager, appWidgetIds); } 

2) Метод расписания должен устанавливать таймер и будильник, чтобы виджет обновлялся каждый день в полночь. Однако это не сработает.

 protected void schedule(Context context) { final Intent i = new Intent(context, CalendarWidget.class); service = PendingIntent.getService(context, 0, i, PendingIntent.FLAG_CANCEL_CURRENT); Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.HOUR, 0); calendar.set(Calendar.AM_PM, Calendar.AM); calendar.add(Calendar.DAY_OF_MONTH, 1); AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); //This doesn't work // alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(), service); //This doesn't work either. alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, service); } 

Решение не работает; И его трудно проверить, потому что он может быть проверен только в полночь каждый день; Следовательно, щедрость. Я вручу его первому человеку, который заставляет его работать.

Я создал виджет даты и времени некоторое время назад. Ниже приведена реализация:

В классе AppWidgetProvider:

 private boolean first_run = true; public AlarmManager am; public PendingIntent pi; @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { first_run = context.getSharedPreferences("mywidet", MODE_PRIVATE).getBoolean("first_run", true); if(first_run) { am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class); pi = PendingIntent.getBroadcast(context, 0, intent, 0); long current = System.currentTimeMillis(); LocalTime localTime = LocalTime.now(); long triggerOffset = (24*60*60 - localTime.getHour()*60*60 - localTime.getMinute()*60 - localTime.getSecond())*1000; am.setRepeating(AlarmManager.RTC_WAKEUP, current + triggerOffset, 86400000, pi); SharedPreferences.Editor editor = context.getSharedPreferences("mywidet", MODE_PRIVATE).edit(); editor.putBoolean("first_run", false); editor.apply(); } for (int appWidgetId : appWidgetIds) { appWidgetManager.updateAppWidget(appWidgetId, remoteView); } } 

В классе AlarmManagerBroadcasrReceiver:

 @Override public void onReceive(Context context, Intent intent) { PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "YOUR TAG"); //Acquire the lock wl.acquire(); Log.d("widget", "in alarm manager. static method will come next"); ComponentName thisWidget = new ComponentName(context, NewAppWidget.class); AppWidgetManager manager = AppWidgetManager.getInstance(context); manager.updateAppWidget(thisWidget, remoteViews); //Release the lock wl.release(); } 

ИЗМЕНИТЬ 1

Начиная с API 19 все setReapeating() неточны. Таким образом, можно сделать следующее:

 if(Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, nexMin.getTimeInMillis()-current.getTimeInMillis(), 60000, pendingIntent); } else { alarmManager.setExact(AlarmManager.RTC_WAKEUP, nexMin.getTimeInMillis() - current.getTimeInMillis(), pendingIntent); } 

Здесь вы можете найти полную реализацию.

Ответ Рафидудмана Соннета работает (вроде), но его можно упростить. AppWidgetProvider уже является BroadcastReceiver , поэтому мы можем направить намерение обратно на AppWidgetProvider и переопределить onReceive для его обработки.

В вашем классе расширяется приложение AppWidgetProvider :

 private static final String ACTION_SCHEDULED_UPDATE = "your.package.name.SCHEDULED_UPDATE"; @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(ACTION_SCHEDULED_UPDATE)) { AppWidgetManager manager = AppWidgetManager.getInstance(context); int[] ids = manager.getAppWidgetIds(new ComponentName(context, AppWidget.class)); onUpdate(context, manager, ids); } super.onReceive(context, intent); } @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // Do your updates... _scheduleNextUpdate(context); } private static void _scheduleNextUpdate(Context context) { AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); // Substitute AppWidget for whatever you named your AppWidgetProvider subclass Intent intent = new Intent(context, AppWidget.class); intent.setAction(ACTION_SCHEDULED_UPDATE); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0); // Get a calendar instance for midnight tomorrow. Calendar midnight = Calendar.getInstance(); midnight.set(Calendar.HOUR_OF_DAY, 0); midnight.set(Calendar.MINUTE, 0); // Schedule one second after midnight, to be sure we are in the right day next time this // method is called. Otherwise, we risk calling onUpdate multiple times within a few // milliseconds midnight.set(Calendar.SECOND, 1); midnight.set(Calendar.MILLISECOND, 0); midnight.add(Calendar.DAY_OF_YEAR, 1); // For API 19 and later, set may fire the intent a little later to save battery, // setExact ensures the intent goes off exactly at midnight. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { alarmManager.set(AlarmManager.RTC_WAKEUP, midnight.getTimeInMillis(), pendingIntent); } else { alarmManager.setExact(AlarmManager.RTC_WAKEUP, midnight.getTimeInMillis(), pendingIntent); } } 

Нам нужно настраивать действие, потому что AppWidgetManager.ACTION_APPWIDGET_UPDATE не обновляет все виджеты, даже если вы передаете полный массив идентификаторов в качестве дополнительного в AppWidgetManager.EXTRA_APPWIDGET_IDS . Он просто обновляет первый созданный виджет.

Вот проект, над которым я работаю, который реализует запланированное обновление виджета, подобное этому.

Intereting Posts