0

My Android widget is not updating the date.

It's a widget with only date, no more.

package com.android.widget;

import java.util.Timer;
import java.util.TimerTask;

import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.widget.RemoteViews;

public class MyCalendarWidget extends AppWidgetProvider {

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new MyTime(context, appWidgetManager), 1,
                1000);
    }

    private class MyTime extends TimerTask {
        RemoteViews remoteViews;
        AppWidgetManager appWidgetManager;
        ComponentName thisWidget;
        Fecha fec = new Fecha();

        public MyTime(Context context, AppWidgetManager appWidgetManager) {
            this.appWidgetManager = appWidgetManager;
            remoteViews = new RemoteViews(context.getPackageName(), R.layout.main);
            thisWidget = new ComponentName(context, MyCalendarWidget.class);
        }

        @Override
        public void run() {
            remoteViews.setTextViewText(R.id.widget_textview, fec.DiaActual(false)+"\r\n"
                                                             +fec.DiaActual(true) +" de "
                                                             +fec.MesActual(false)+" de "
                                                             +fec.AñoActualNumerico());
            appWidgetManager.updateAppWidget(thisWidget, remoteViews);
        }
    }
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
appmobiles.tk
  • 89
  • 1
  • 9

1 Answers1

1

Please begin by reading the documentation, AppWidget Guide and AppWidgetProvider. That explains:

  • Your onUpdate() method needs to send a RemoteViews to the widget via updateAppWidget().
  • Waking up once per second would drain your battery. You certainly don't want to update the widget while the phone is sleeping.
  • Each call to remoteViews.setTextViewText() appends more data to the RemoteViews object. That'll accumulate excess data in memory and make the widget slow. Instead, get a new RemoteViews instance each time.

My hypothesis about your updates not happening is the OS stopping your widget provider's component when the provider finishes responding to an Intent. You can test that hypothesis via Log.d().

You can register for an ACTION_TIME_TICK broadcast that tells you when the time changes, once per minute. Do test that it doesn't run when the phone sleeps (e.g. keep a count of calls) and feel free to report back here.

[Added] It's much easier in practice to display the date (and update it once per day) than the date + time (and update it once per minute; your question code tried to update it once per second), and to do this without using much battery power.

  • Set updatePeriodMillis="0".
  • Add <action android:name="android.intent.action.DATE_CHANGED"/> to the <intent-filter> for the widget provider in AndroidManifest.xml.
  • In the AppWidgetProvider, override

    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
        if (Intent.ACTION_DATE_CHANGED.equals(intent.getAction())) { updateAllMyWidgets(context); }
    }
    
  • Use DateUtils.formatDateTime() to format the date.

Yes, the bug code.google.com/p/android/issues/detail?id=2880 will happen if the clock is adjusted backwards.

Jerry101
  • 12,157
  • 5
  • 44
  • 63
  • Thank you Sr. is very friendly. Please would like to know if it is possible to use the DEBUG for this project. It did not work when I tried. Thanks but although it has helped me a lot as I am newbie in Android that his explanation comes very large. If you can send me a link on ACTION_TIME_TICK such example. I would be eternally grateful. – appmobiles.tk Feb 21 '14 at 10:15
  • The debugger should work on this project. If you're running on a device, remember to use Settings to enable development features including debugging. You might want to begin with an easier project that just uses Activities. This project requires learning Widgets, Intents, Receivers, Services, and more. – Jerry101 Feb 22 '14 at 14:42
  • A web search will find examples using ACTION_TIME_TICK [although some of them are not well designed] such as http://kfb-android.blogspot.com/2009/04/registering-for-timetick-after-reboot.html : `registerReceiver(new DemoReceiver(), new IntentFilter(Intent.ACTION_TIME_TICK));` It needs to be in a Service to keep running in the background. The page also discusses re-registering when the device reboots and the need to stop the service. I don't think the manifest needs `` in the intent-filter. – Jerry101 Feb 22 '14 at 14:51
  • Better idea: It'd save battery power, CPU, and memory to listen to ACTION_TIME_TICK only when the screen is on and an instance of your clock widget exists. To do that, define a broadcast receiver in your manifest for ACTION_SCREEN_ON and ACTION_SCREEN_OFF. On ACTION_SCREEN_ON, if the array of widgetIds is not empty, then start the service. The service will register for ACTION_TIME_TICK. When it receives a tick, the service will update the widgets or, if the array of widgetIds is empty, stop itself. Also on ACTION_SCREEN_OFF, stop the service. – Jerry101 Feb 22 '14 at 19:49
  • Thanks, I'm definitely talking to a being from another galaxy :) I really am grateful but if you explain it well I do not follow you, sorry. I've thought about this. As the onUpdate is updated every 30 minutes. Why not just watch the time of day and if it's 00:00:01, I update the textview and ready. I guess this will not harm the battery consumption or use cpu as the minimum update time. Do not you think?. – appmobiles.tk Feb 23 '14 at 06:29
  • The Android OS only runs app components when needed. That saves battery power and CPU cycles. Once an AppWidgetProvider (which is a kind of BroadcastReceiver) responds to an incoming Intent, the OS can stop it and its Timer. So you need another way to run code once per minute to update the widget. The simplest way is to set android:updatePeriodMillis="60000" so the widget will auto-update every minute. But the documentation http://developer.android.com/guide/topics/appwidgets/index.html#MetaData says that will drain battery power. It will update when the screen is off. – Jerry101 Feb 23 '14 at 20:40
  • Better ways to update the widget include: (1) Listen to ACTION_TIME_TICK messages. That's once per minute when the time changes. Register for these messages when the screen is on. (2) Use AlarmManager with alarm type RTC http://developer.android.com/reference/android/app/AlarmManager.html#RTC . (3) Send delayed messages within a background Service. See http://developer.android.com/reference/android/os/Handler.html – Jerry101 Feb 23 '14 at 20:51
  • Thank Jerry101. But now if I've made ​​a mess. :) But android: updatePeriodMillis, is not updated as a minimum 30 minutes, this is what I observed and it says so in other questions in this forum. Well I tell you my changes. Now detect if date changes every 24 hours with android: updatePeriodMillis. And as a control to compare my date text ideal change is that you can set the start of the implementation of onUpdate but say there is a bug for this. And if this is not fixed. Ah, sorry I ask Jerry, I do not speak English well at all and I'm pulling google translator. – appmobiles.tk Feb 24 '14 at 21:23
  • It's much easier to display and update the date than the time. Set `updatePeriodMillis="0"`. Add `` to the `` for the widget provider in AndroidManifest.xml. In the AppWidgetProvider, override `onReceive(Context context, Intent intent) {super.onReceive(context, intent); if (Intent.ACTION_DATE_CHANGED.equals(action)) { updateAllMyWidgets(context); }}`. Use `DateUtils.formatDateTime()` to format the date. Yes, the bug https://code.google.com/p/android/issues/detail?id=2880 happens if the clock is adjusted backwards. – Jerry101 Feb 25 '14 at 05:43
  • Achieved :) Thank your solution is the best, well well. Only one thing. I have noticed that the date changes work well into the future but the past but not to use do not work. I guess this is normal but if someone wants to put the date in the past this Widget you will not do this again until in the future. I wonder if this one will last based on your solution. Anyway thank you very much, if you know you Android. I owe you one. :) I'm very grateful for having this conversation with you. – appmobiles.tk Feb 25 '14 at 09:05
  • You're welcome. If you want to work around the Android bug that happens when the clock gets adjusted backwards, start with the AlarmManager code in http://stackoverflow.com/questions/21758246/android-action-date-changed-broadcast/21980389 – Jerry101 Feb 27 '14 at 06:24