更新AppWidget定期从服务 [英] Update AppWidget Periodically from a service
问题描述
这是我想从我的AppWidget:
This is what I want from my AppWidget:
- 在配置活动启动后,当小部件添加到屏幕//好为止
- 在配置被保存后,启动服务的更新微件//好为止
- 在定期安排警报,运行更新插件的服务。 //有麻烦在这里
这是严重地给我花白的头发已经,我不知道该怎么办了。如何设置的更新速率从服务的AppWidget?我可以从服务更新的部件,但是当我尝试设置了警钟,它并没有得到对AppWidget的的onReceive()
方法。
This is seriously giving me grey hair already, and I don't know what to do anymore. How do you set the update rate for an AppWidget from a service? I can update the widget from the service, but when I try to set the alarm, it does not get to the onReceive()
method on the AppWidget.
下面是code的服务更新:
Here is the code for the service update:
Intent updateWidget = new Intent();
updateWidget.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
updateWidget.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[]{appWidgetId});
Uri data = Uri.withAppendedPath(Uri.parse(WeatWidgetProvider.URI_SCHEME +
"://widget/id/"), String.valueOf(appWidgetId));
updateWidget.setData(data);
PendingIntent updatePend = PendingIntent.getBroadcast(this, 0, updateWidget, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarm = (AlarmManager)getSystemService(ALARM_SERVICE);
alarm.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime()+ updateRate, updateRate, updatePend);
而在的onReceive()
WidgetProviderClass的:
And in the onreceive()
of WidgetProviderClass:
public void onReceive(Context context, Intent intent){
super.onReceive(context, intent);
Log.d("OnReceive", "OnReceive called");
String action = intent.getAction();
Log.d("Action", "OnReceive:Action: " + action);
if(AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)){
int appwidgetId = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
if(appwidgetId != AppWidgetManager.INVALID_APPWIDGET_ID){
this.onDeleted(context, new int[] {appwidgetId});
}
} else if(AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)){
if(!URI_SCHEME.equals(intent.getScheme())){
final int[] appWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
for(int appWidgetId:appWidgetIds){
SharedPreferences prefs = context.getSharedPreferences(WeatForecastConfigure.WEATHER_PREF_NAME, Context.MODE_PRIVATE);
update = prefs.getInt(WeatForecastConfigure.REFRESH_UPDATE, -1);
System.out.println(update);
if(update != -1){
Intent widgetUpdate = new Intent();
widgetUpdate.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
widgetUpdate.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] { appWidgetId });
// make this pending intent unique by adding a scheme to it
widgetUpdate.setData(Uri.withAppendedPath(Uri.parse(WeatWidgetProvider.URI_SCHEME +
"://widget/id/"), String.valueOf(appWidgetId)));
PendingIntent newPending = PendingIntent.getBroadcast(context.getApplicationContext(), 0, widgetUpdate, PendingIntent.FLAG_UPDATE_CURRENT);
// schedule the updating
AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarms.setRepeating(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime(), WeatForecastConfigure.convertToMillis(update), newPending);
}
}
}
super.onReceive(context, intent);
}else{
super.onReceive(context, intent);
}
}
有关的OnUpdate()
注释行是故意的。
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds){
Log.d("OnUpdate", "OnUpdate called");
for (int appWidgetId : appWidgetIds) {
// context.startService(new Intent(context,WeatService.class));
}
//super.onUpdate(context, appWidgetManager, appWidgetIds);
}
请帮忙。我不知道如何设置报警更新。无论是我从配置类或从服务做到这一点,这是行不通的。谢谢你。
Please help. I have no idea how to set the alarm to update. Whether I do it from the configuration class or from a service, it does not work. Thanks.
推荐答案
我写了这一切,并意识到它可能只是迷惑你多一些,很好哦。
I wrote all this, and realized it will probably just confused you more, oh well.
下面是我如何更新我的小部件的骨架,它是松散的基础上这一code的 HTTP://$c$c.google.com/p/android-sky/source/browse/#svn%2Ftrunk%2FSky (特别是该UpdateService类。
Here is the skeleton of how I update my widgets, it is loosely based on this code http://code.google.com/p/android-sky/source/browse/#svn%2Ftrunk%2FSky (particularly the UpdateService class.
的主要区别是我的code
The main difference is my code
- 在开始执行更新服务
- 设置报警(广播挂起的意图),提醒有关下次更新的窗口小部件
- 更新窗口小部件并停止服务
- 在接收更新的广播(在供应商的onReceive),然后重新启动该服务
您似乎在试图告诉AppWidgetProvider开球通过的onupdate,我不知道这是否可能?
You seem to be trying to tell the AppWidgetProvider to kickoff through the onUpdate, I'm not sure if this is even possible?
下面是我如何做到这一点半伪code:
Here is how I do it in semi pseudo code:
UpdateService类:
UpdateService class:
//based on (an old) example http://code.google.com/p/android-sky/source/browse/#svn%2Ftrunk%2FSky however other methods I have tried have not been as reliable as this
public void run() {
//set the alarm for the next update
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
long millis = System.currentTimeMillis();
//one alarm to update them all, if you wanted to you could
//add an extra appWidgetId then you might need to encode the intent
//however so it is a unique PendingIntent
Intent updateIntent = new Intent(ACTION_UPDATE_ALL); //ACTION_UPDATE_ALL should be a constant somewhere that can be used to resolve this action com.packagename.ACTION_UPDATE_ALL
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, updateIntent, 0);
// Schedule alarm, and force the device awake for this update
alarmManager.set(AlarmManager.RTC, millis + updateFrequency * DateUtils.MINUTE_IN_MILLIS, pendingIntent);
Log.d(TAG, "Next update should be at: " + DateFormat.format("h:mm:ss", millis + updateFrequency * DateUtils.MINUTE_IN_MILLIS));
while (hasMoreUpdates()) {
int appWidgetId = getNextUpdate();
if (!(appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID)) {
Uri appWidgetUri = ContentUris.withAppendedId(Agenda.getContentUri(context), appWidgetId);
AppWidgetProviderInfo info = manager.getAppWidgetInfo(appWidgetId);
String providerName = info.provider.getClassName();
//if the provider matches one of my widget classes, call the update method
if (providerName.equals(Widget_4_1.class.getName())) {
remoteViews = Widget_4_1.buildUpdate(context, appWidgetUri, dateRows);
}
//perform more actions such as sending remoteViews to the AppWidgetManager
}
}
}
Widget_4_1类:
Widget_4_1 class:
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// If no specific widgets requested, collect list of all
if (appWidgetIds == null) {
appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(
context, AbstractWidget.class));
}
UpdateService.requestUpdate(appWidgetIds);
Intent i = new Intent();
i.setComponent(new ComponentName(context, UpdateService.class));
context.startService(i);
}
//called from service
public static RemoteViews buildUpdate(Context context, Uri appWidgetUri) {
int appWidgetId = (int) ContentUris.parseId(appWidgetUri);
RemoveViews remoteViews = someMethodToBuildView(appWidgetId );
//return view to service
return remoteViews;
}
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
//when the alarm triggers, just update all your widgets, why handle them separately?
if (action.equals(ACTION_UPDATE_ALL)) {
AppWidgetManager manager = AppWidgetManager.getInstance(context);
int[] appWidgetIds = manager.getAppWidgetIds(new ComponentName(context, getClass()));
if(appWidgetIds.length>0){
UpdateService.requestUpdate(appWidgetIds);
Intent updateIntent = new Intent(context, UpdateService.class);
updateIntent.setAction(action);
context.startService(updateIntent);
}
}
//else you could catch a specific action for updating a single widget and
//tell your update service to do it manually
}
AndroidManifest.xml中:
AndroidManifest.xml:
<application>
...
<receiver android:name="com.mypackage.Widget_4_1"
android:label="@string/agenda_widget_name_4_1">
<intent-filter>
<!-- IMPORTANT, needs to match the ACTION_UPDATE_ALL string (e.g. a constant somewhere) -->
<action android:name="com.packagename.UPDATE_ALL" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/widget_4_1" />
</receiver>
...
</application>
希望我没有让你感到困惑。
Hope I haven't confused you.
由于这code是复制/从我的项目的借口错字的等等,我会解决这些问题各部分粘贴为他们指出了。
As this code is copy/pasted from various parts of my project excuse typo's etc, I will fix them as they are pointed out.
这篇关于更新AppWidget定期从服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!