使用 AlarmManager 更新应用程序小部件
我正在尝试比 1.6docs 规定的 30 分钟限制更频繁地更新 Widget。在阅读了 SO 中的几乎每一篇文章、开发人员文档以及各种其他来源之后,我认为我已经达到了可以实现它的程度。于是,我尝试了,但失败了。从那时起,我又搜索了更多论坛和解决方案,但似乎无法更新。
我有一个设置 AlarmManager 的 Update 类:
public class Update extends Service{
@Override
public void onStart(Intent intent, int startId) {
String currentTemp = Battery.outputTemp;
String currentLevel = Battery.outputLevel;
String currentCard = Battery.outputCard;
String currentInternal = Battery.memory;
String currentRam = String.valueOf(Battery.outputRam).substring(0, 3) + "MB";
// Change the text in the widget
RemoteViews updateViews = new RemoteViews(
this.getPackageName(), R.layout.main);
//update temp
updateViews.setTextViewText(R.id.batteryTemp, currentTemp);
//update %
updateViews.setTextViewText(R.id.batteryLevel, currentLevel);
//update level
updateViews.setTextViewText(R.id.sdCard, currentCard);
//update internal memory
updateViews.setTextViewText(R.id.internal, currentInternal);
//update ram
updateViews.setTextViewText(R.id.ram, currentRam);
ComponentName thisWidget = new ComponentName(this, Widget.class);
AppWidgetManager manager = AppWidgetManager.getInstance(this);
manager.updateAppWidget(thisWidget, updateViews);
}
@Override
public IBinder onBind(Intent intent) {
// no need to bind
return null;
}
}
这导致我的小部件类中的 onReceive 频繁触发(我有一个 toast 来查看它何时触发),但它没有任何意图(toast 旨在按原样显示此内容)已收到,但内容为空)。
我无法弄清楚(我是一个相对新手 - 两个月的缓慢 Android 开发),并感谢你们所拥有的任何见解。
这是我的小部件类供参考:
public class Widget extends AppWidgetProvider {
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
AlarmManager alarmManager;
Intent intent = new Intent(context, Update.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(System.currentTimeMillis());
cal.add(Calendar.SECOND, 10);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal
.getTimeInMillis(), 5 * 1000, pendingIntent);
String currentTemp = Battery.outputTemp;
String currentLevel = Battery.outputLevel;
String currentCard = Battery.outputCard;
String currentInternal = Battery.memory;
String currentRam = String.valueOf(Battery.outputRam).substring(0, 3)
+ "MB";
// Change the text in the widget
RemoteViews updateViews = new RemoteViews(context.getPackageName(),
R.layout.main);
// update temp
updateViews.setTextViewText(R.id.batteryTemp, currentTemp);
appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
// update %
updateViews.setTextViewText(R.id.batteryLevel, currentLevel);
appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
// update level
updateViews.setTextViewText(R.id.sdCard, currentCard);
appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
// update internal memory
updateViews.setTextViewText(R.id.internal, currentInternal);
appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
// update ram
updateViews.setTextViewText(R.id.ram, currentRam);
appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
Toast
.makeText(context, intent.getAction() + context,
Toast.LENGTH_LONG).show();
Bundle extras = intent.getExtras();
if (extras != null) {
AppWidgetManager appWidgetManager = AppWidgetManager
.getInstance(context);
ComponentName thisAppWidget = new ComponentName(context
.getPackageName(), Widget.class.getName());
int[] appWidgetIds = appWidgetManager
.getAppWidgetIds(thisAppWidget);
onUpdate(context, appWidgetManager, appWidgetIds);
}
}
}
I am trying to update a Widget more frequently than the 30 minute restriction imposed by the 1.6docs. After reading nearly every post in SO, and the developer docs, and various other sources, I thought I had got to a point where i could implement it. And so, I tried, and failed. Since then, I have trawled yet more forums and solutions, and I cannot seem to get it to update.
I have an Update class that sets the AlarmManager:
public class Update extends Service{
@Override
public void onStart(Intent intent, int startId) {
String currentTemp = Battery.outputTemp;
String currentLevel = Battery.outputLevel;
String currentCard = Battery.outputCard;
String currentInternal = Battery.memory;
String currentRam = String.valueOf(Battery.outputRam).substring(0, 3) + "MB";
// Change the text in the widget
RemoteViews updateViews = new RemoteViews(
this.getPackageName(), R.layout.main);
//update temp
updateViews.setTextViewText(R.id.batteryTemp, currentTemp);
//update %
updateViews.setTextViewText(R.id.batteryLevel, currentLevel);
//update level
updateViews.setTextViewText(R.id.sdCard, currentCard);
//update internal memory
updateViews.setTextViewText(R.id.internal, currentInternal);
//update ram
updateViews.setTextViewText(R.id.ram, currentRam);
ComponentName thisWidget = new ComponentName(this, Widget.class);
AppWidgetManager manager = AppWidgetManager.getInstance(this);
manager.updateAppWidget(thisWidget, updateViews);
}
@Override
public IBinder onBind(Intent intent) {
// no need to bind
return null;
}
}
This has caused my onReceive in my widget class to fire frequently (i have a toast to see when it fires), yet it carries no intent (the toast is meant to display this as they are received but it is blank).
I cannot figure it out (i'm a relative newb-2 months of slow android dev), and appreciate any insight you guys have.
heres my widget class for reference:
public class Widget extends AppWidgetProvider {
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
AlarmManager alarmManager;
Intent intent = new Intent(context, Update.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(System.currentTimeMillis());
cal.add(Calendar.SECOND, 10);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal
.getTimeInMillis(), 5 * 1000, pendingIntent);
String currentTemp = Battery.outputTemp;
String currentLevel = Battery.outputLevel;
String currentCard = Battery.outputCard;
String currentInternal = Battery.memory;
String currentRam = String.valueOf(Battery.outputRam).substring(0, 3)
+ "MB";
// Change the text in the widget
RemoteViews updateViews = new RemoteViews(context.getPackageName(),
R.layout.main);
// update temp
updateViews.setTextViewText(R.id.batteryTemp, currentTemp);
appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
// update %
updateViews.setTextViewText(R.id.batteryLevel, currentLevel);
appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
// update level
updateViews.setTextViewText(R.id.sdCard, currentCard);
appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
// update internal memory
updateViews.setTextViewText(R.id.internal, currentInternal);
appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
// update ram
updateViews.setTextViewText(R.id.ram, currentRam);
appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
Toast
.makeText(context, intent.getAction() + context,
Toast.LENGTH_LONG).show();
Bundle extras = intent.getExtras();
if (extras != null) {
AppWidgetManager appWidgetManager = AppWidgetManager
.getInstance(context);
ComponentName thisAppWidget = new ComponentName(context
.getPackageName(), Widget.class.getName());
int[] appWidgetIds = appWidgetManager
.getAppWidgetIds(thisAppWidget);
onUpdate(context, appWidgetManager, appWidgetIds);
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是我的解决方案,如何比 30 分钟更频繁地自动更新小部件。我使用警报管理器。在使用 AlarmManager 刷新应用程序小部件之前,请确保您知道自己在做什么,因为这种技术可能会耗尽设备的电池。
详细了解 Android 文档中的小部件更新 - 尤其是 updatePeriodMillis 参数。
这是我的 Manifest.xml 的一部分。我定义了自定义操作 AUTO_UPDATE。
这是我的 AppWidget.java 的一部分。在 onReceive 方法中,我处理自定义操作 AUTO_UPDATE。在 onEnabled 和 onDisabled 方法中,我启动/停止警报。
这是我的 AppWidgetAlarm.java,它启动/停止警报。警报管理器向 AppWidget 发送广播。
This is my solution, how to automatically update widget more frequently than the 30 minutes. I use AlarmManager. Before you use AlarmManager for refreshing appwidget, make sure you know what you do, because this technique could drain the device's battery.
Read more about widget update in Android doc - especially about updatePeriodMillis parameter.
This is part of my Manifest.xml. I define custom action AUTO_UPDATE.
This is part of my AppWidget.java. In onReceive method, I handle my custom action AUTO_UPDATE. In onEnabled and onDisabled methods, I start/stop alarm.
This is my AppWidgetAlarm.java, which starts/stops alarm. Alarm manager sends broadcast to AppWidget.
不,你没有。
AlarmManager
出现在代码片段中的任何地方。您确实在第二个代码片段中引用了
AlarmManager
。那里的问题包括:每次应用程序小部件更新时,您都设置一个新的重复闹钟
您在闹钟上设置 5 秒的频率,这太疯狂了
您在
_WAKEUP
闹钟上设置了 5 秒频率,我认为这是在某些司法管辖区逮捕您的理由您的说法毫无意义
onReceive()
方法,甚至忽略临时Toast
您假设您的
Toast
中的Intent
上会有一个操作字符串,但在创建该操作字符串时没有指定操作字符串。您在警报的PendingIntent
中放入的Intent
No, you don't.
AlarmManager
appears nowhere in the code snippet.You do have a reference to
AlarmManager
in the second code snippet. Problems there include:You are setting a new repeating alarm every time the app widget updates
You are setting a 5 second frequency on the alarm, which is utter insanity
You are setting a 5 second frequency on a
_WAKEUP
alarm, which I think is grounds for your arrest in some jurisdictionsYou have a pointless
onReceive()
method, even ignoring the temporaryToast
You are assuming that there will be an action string on the
Intent
in yourToast
, but you do not specify an action string when you create theIntent
that you put in thePendingIntent
for the alarmYour code refers to what I presume are static data members on a
Battery
class, but it is rather likely those are all empty/null... or at least they would be, if you had a sane frequency on the alarm感谢这个例子 - 我在使用更高版本的 Android 时也遇到了问题。
这篇文章让它对我有用:
小部件案例不起作用(请参阅 Larry Schiefer 的回答)。
因此,用上面的代码替换它:
用 ref 中的这个:
完成了这项工作。
Thanks for this example - I also had problems using a later Android version.
This post made it work for me:
widget case that doesn't work (see the answer from Larry Schiefer).
So substituting for this from the code above:
with this from the ref:
did the job.
petrnohejl 解决方案的一点修改版本。这个正在我的项目中工作。 (用 kotlin 编写):
这是 Manifest.xml 的一部分。我添加了以下操作:AUTO_UPDATE、APPWIDGET_UPDATE、APPWIDGET_ENABLED、APWIDGET_DISABLED。
这是 AppWidget.kt 的一部分。这里我实现了onUpdate()、onEnabled()、onDisabled()、onReceive()函数。
这是 AppWidgetAlarm.kt。这是我的主要修改。答案对我没有帮助,但它正在发挥作用。我在这里设置了一个重复闹钟。 (https://developer.android.com/training/scheduling/alarms)
A little bit modified version of petrnohejl's solution. This one is working in my project. (written in kotlin):
This is part of the Manifest.xml. I added the following actions: AUTO_UPDATE, APPWIDGET_UPDATE, APPWIDGET_ENABLED, APWIDGET_DISABLED.
This is part of the AppWidget.kt. Here I implemented the onUpdate(), onEnabled(), onDisabled(), onReceive() functions.
And this is the AppWidgetAlarm.kt. Here it is my main modification. The answers didn't help me, but it is working. I set here a repeating alarm. (https://developer.android.com/training/scheduling/alarms)