Reputation: 11829
I created a widget I would like to update periodically every 5 second (for testing purposes). However, the service is never called.
public class WidgetProvider extends AppWidgetProvider {
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Log.i("STATUS", "APPWIDGET onUpdate");
final int count = appWidgetIds.length;
for (int i = 0; i < count; i++) {
int widgetId = appWidgetIds[i];
String number = String.format("%03d", (new Random().nextInt(900) + 100));
Log.i("NUMBER", number);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_large);
remoteViews.setTextViewText(R.id.tv_inmonths, number);
Intent intentt = new Intent(context, UpdateService.class);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intentt, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (5 * 1000), pendingIntent);
appWidgetManager.updateAppWidget(widgetId, remoteViews);
}
}
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
Log.i("STATUS", "APPWIDGET onReceive");
Bundle extras = intent.getExtras();
if(extras!=null) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
ComponentName thisAppWidget = new ComponentName(context.getPackageName(), WidgetProvider.class.getName());
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget);
if (appWidgetIds.length > 0) {
new WidgetProvider().onUpdate(context, appWidgetManager, appWidgetIds);
}
}
}
}
public final class UpdateService extends Service {
PendingIntent pendingIntent;
@Override
public void onCreate(){
Log.i("STATUS", "Service onCreate");
String number = String.format("%03d", (new Random().nextInt(900) + 100));
Log.i("NUMBER2", number);
RemoteViews updateViews = new RemoteViews(this.getPackageName(), R.layout.widget_large);
updateViews.setTextViewText(R.id.tv_inmonths, number); //ha ez AAAA akkor is eltűnik
ComponentName thisWidget = new ComponentName(this, WidgetProvider.class);
AppWidgetManager manager = AppWidgetManager.getInstance(this);
manager.updateAppWidget(thisWidget, updateViews);
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
Manifest:
<receiver android:name=".WidgetProvider" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/widget_provider_large" />
</receiver>
<service android:enabled="true" android:name=".UpdateService" />
Once the I place the widget on my home screen, this is the logcat:
09-09 18:36:48.330 10551-10551/myapp.myapp I/STATUS﹕ APPWIDGET onReceive
09-09 18:36:48.340 10551-10551/myapp.myapp I/STATUS﹕ APPWIDGET onUpdate
09-09 18:36:48.340 10551-10551/myapp.myapp I/NUMBER﹕ 809
Sometimes it calls the service but that's all.
Update: I tried it with a Handler as well, and though it runs every 3 seconds, the service is called only once
m_Handler = new Handler();
mRunnable = new Runnable(){
@Override
public void run() {
Log.i("STATUS", "run");
Intent myIntent = new Intent(context, UpdateService.class);
context.startService(myIntent);
m_Handler.postDelayed(mRunnable, 3000);
}
};
mRunnable.run();
Upvotes: 0
Views: 1022
Reputation: 199805
Two things:
Frequent Alarms
Per the documentation for AlarmManager.set():
Note: Beginning in API 19, the trigger time passed to this method is treated as inexact: the alarm will not be delivered before this time, but may be deferred and delivered some time later. The OS will use this policy in order to "batch" alarms together across the entire system, minimizing the number of times the device needs to "wake up" and minimizing battery use. In general, alarms scheduled in the near future will not be deferred as long as alarms scheduled far in the future.
You can confirm when alarms are scheduled for by using adb shell dumpsys alarm
, which provides a very verbose output that may be hard to understand
But note that even using setExact() may not trigger with small intervals. Instead, as noted at the top of the AlarmManager
documentation:
Note: The Alarm Manager is intended for cases where you want to have your application code run at a specific time, even if your application is not currently running. For normal timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.
Services
You're using a Service
. Per the Services guide, a Service
started with startService()
will remain running until you call stopSelf()
within the Service
or some other component calls stopService()
. As onCreate()
only happens when the Service
is first created, your subsequent calls to startService()
do not retrigger your code.
Instead, consider using an IntentService - for each call to startService()
, you'll get a callback to onHandleIntent()
and the Service
will be stopped immediately upon completion of all pending calls to onHandleIntent()
or even better, just use a BroadcastReceiver - there's no reason to have a Service
in this case as you aren't doing any long processing tasks (of course, you'd update your startService()
to be instead use sendBroadcast())
Upvotes: 1