0

I have googled a lot and tried so many variations but I just can't get my code working. I have a widget that NEEDS to be updated every second but only when the screen is unlocked.

The widget itself should do 2 things:

  1. set an onClickListener to send the user to my MainActivity
  2. edit a textbox every second

Since the intervall is really small with one second I thought I have to use an AlarmManger together with an IntentService for the update. Elapsed_Realtime should be right since I don't want to wake up the phone when locked. So this is how my

AppWidgetProvider.onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)

looks like:

    @Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {

    final AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    final Intent intent = new Intent(context, UpdateService.class);
    final PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);

    alarmManager.cancel(pendingIntent);
    alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(),1000, pendingIntent);
}

Do I really need a loop over the widget-IDs here?

This is how my UpdateService looks like:

public class UpdateService extends IntentService {

    public static int testInt = 0;

    public UpdateService() {
        super("stuff UpdateService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {

        RemoteViews remoteViews = new RemoteViews(this.getPackageName(), R.layout.my_widget);

        //stuff
        remoteViews.setTextViewText(R.id.textView,String.format("%02d",variableThatChangesEverySecond));
        // more stuff

//set onClickListener
        final Intent openApp = new Intent(this, MainActivity.class);
        final PendingIntent pendingAppIntent = PendingIntent.getActivity(this, 0, openApp, 0);
        remoteViews.setOnClickPendingIntent(R.id.myRelativeLayout, pendingAppIntent);

        ComponentName thisWidget = new ComponentName(this,myWidget.class);
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);

//log a testInt to see how often my widget gets updates
        testInt = testInt + 1;
        System.out.println(testInt);

        appWidgetManager.updateAppWidget(thisWidget, remoteViews);
    }
}

Although I set my intervall 1000ms = 1s my widget updates not exact and only like once in one or two minutes. Here is the logcat to see the updateIntervalls:

06-08 19:21:10.444  19376-19749/mypackage.myapp I/System.out﹕ 1
06-08 19:22:42.900  19376-19798/mypackage.myapp I/System.out﹕ 2
06-08 19:23:02.449  19376-19807/mypackage.myapp I/System.out﹕ 3
06-08 19:24:43.035  19376-19860/mypackage.myapp I/System.out﹕ 4
06-08 19:25:43.087  19376-19876/mypackage.myapp I/System.out﹕ 5
06-08 19:26:43.149  19376-19905/mypackage.myapp I/System.out﹕ 6
06-08 19:27:43.214  19376-19936/mypackage.myapp I/System.out﹕ 7
06-08 19:28:43.282  19376-19960/mypackage.myapp I/System.out﹕ 8
06-08 19:29:43.290  19376-19986/mypackage.myapp I/System.out﹕ 9
06-08 19:30:43.355  19376-20051/mypackage.myapp I/System.out﹕ 10
06-08 19:31:43.419  19376-20096/mypackage.myapp I/System.out﹕ 11

Where is my mistake? Thank you so much, you are my last hope...

selmaoh
  • 1
  • 2
  • Note that Android 5.1 sets a minimum one-minute period between `AlarmManager` updates for `setRepeating()` and `setInexactRepeating()`, in part to prevent people from draining the user's battery by updating app widgets every second. Android M will put ill-used apps in "app standby", blocking most background processing, until the user runs the app again, and it is unclear how this will impact apps with app widgets. I **strongly** encourage you to write something else. – CommonsWare Jun 08 '15 at 17:46
  • But there must be a way? Every widget-clock for example needs to show the actual seconds? Any idea? – selmaoh Jun 08 '15 at 17:50
  • You need to use `setExact()` instead of `setRepeating` for API above 18. – Skynet Jun 08 '15 at 17:53
  • But then I would lose all of my current users that have an API below 18... that won't give me good reviews^^ – selmaoh Jun 08 '15 at 17:56
  • Technically No, these would be tedious, but I see these as the only solutions: There are two ways you can go by, restrict your API to 18 and use setRepeating(), your app will still work on and up to API 22 (which is the latest). Else check for the API present on the phone and give your program structure two branches depending on the API using [this](http://developer.android.com/reference/android/os/Build.VERSION.html) – Skynet Jun 08 '15 at 18:00
  • One more way to achieve what you want is to get rid of the alarm manager and use a timer or a handler in conjunction with [this](http://stackoverflow.com/questions/9477922/android-broadcast-receiver-for-screen-on-and-screen-off) – Skynet Jun 08 '15 at 18:04
  • "Every widget-clock for example needs to show the actual seconds?" -- that should be implemented by the home screen itself, not an app widget. – CommonsWare Jun 08 '15 at 18:09
  • @CommonsWare, what do you mean the home screen would implement it? Are you saying there's some broadcast every second we could listen for? Can you elaborate? – David Small Sep 06 '15 at 21:01
  • @DavidSmall: "what do you mean the home screen would implement it?" -- a home screen is an app with 1+ activities, just like any other app. The author of the home screen is perfectly capable of implementing a clock "widget" that happens to be part of the home screen itself, eliminating IPC overhead, keeping a service around just to tell an app widget to update itself every second, etc. – CommonsWare Sep 06 '15 at 21:04

0 Answers0