Android 应用程序小部件更新问题

发布于 2024-10-22 05:30:46 字数 4156 浏览 3 评论 0原文

这就是我正在处理的事情。

我有一个与我的 Android 应用程序关联的小部件,仅当屏幕打开时我想每 10 分钟更新一次(当前使用 AlarmManager)。如果屏幕关闭,则未决意图的警报将被取消。一旦屏幕再次亮起,我会检查上次更新时间和当前时间是否有 10 分钟或更长时间的差异,如果是,我会发送广播来更新小部件。

发生的情况和问题是待处理 Intent 的警报可能不会被取消(可能),并且对屏幕关闭时堆积的所有待处理 Intent 警报执行小部件更新。

这是一些代码片段。

@Override
public void onReceive(Context context, Intent intent) {
        check_intent = intent.getAction();

            if(check_intent.equals("android.appwidget.action.APPWIDGET_UPDATE")){

                 mAppPreferences = PreferenceManager.getDefaultSharedPreferences(context);
                 int saved_num_widgets = mAppPreferences.getInt(NUM_WIDGETS, 0);
        /*Check if there is atleast one widget on homescreen*/       
                 if (saved_num_widgets>0){
                        boolean check = CheckScreenOn.check_screen_on(context);
/*Check if Screen is ON*/
                            if(check == true){
                                                Intent widgetUpdate = new Intent(context, MyWidget.class);
                                                widgetUpdate.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
                                                alarms = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
                                                newPending = PendingIntent.getBroadcast(context, 0, widgetUpdate,0);
                                                alarms.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime()+ PERIOD, newPending);
                                                context.startService(new Intent(context, UpdateService.class));
                            }
                            else{
                                alarms.cancel(newPending);
/*Screen is OFF no point updating the widget, cancel Alarms and do nothing*/
                            }
                     }
                     else{
                            int duration = Toast.LENGTH_LONG;
                            CharSequence text = "Please place My Widget on your home screen to keep earning money.";
                            Toast toast = Toast.makeText(context, text, duration);
                            toast.show();
                     }
                    }   
                if(check_intent.equals("android.appwidget.action.APPWIDGET_ENABLED")){
                    this.onEnabled(context);
                }
                if(check_intent.equals("android.appwidget.action.APPWIDGET_DELETED")){
                    this.onDeleted(context);
                }
                if(check_intent.equals("android.appwidget.action.APPWIDGET_DISABLED")){
                    this.onDisabled(context);
                }


    }

这是接收 SCREEN_ON 广播的广播接收器,如果当前时间 - 上次小部件更新时间 >= 10 分钟,则发出小部件更新请求。

registerReceiver(new BroadcastReceiver() {

              @Override
              public void onReceive(Context context, Intent intent) {
                // ... 
                long update_interval = mAppPreferences.getLong(LASTUPDATETIME, 0);
                long curtimemillis = System.currentTimeMillis();
                long calculate_interval = curtimemillis - update_interval;
                if(calculate_interval >= PERIOD){
                    int saved_num_widgets = mAppPreferences.getInt(NUM_WIDGETS, 0);

                    if (saved_num_widgets>0){

                               alarms.cancel(newPending);
                            Intent widgetUpdate = new Intent(context, MyWidget.class);
                            widgetUpdate.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
                            context.sendBroadcast(widgetUpdate);
                        }

                    }

                  }
                }, new IntentFilter(Intent.ACTION_SCREEN_ON));

假设最后一次更新发生在上午 10:00,屏幕关闭了 30 分钟。当屏幕亮起时,小部件会立即更新为pendingIntent 存储的所有警报。我希望小部件更新仅在屏幕再次亮起时发生一次。

最初我了解到 AlarmManager.ELAPSED_REALTIME 在设备从空闲状态唤醒时触发。

我不知道为什么闹钟取消不起作用。其他一切都按预期进行。

顺便说一句,我已经在各种设备上对 10 分钟小部件更新进行了性能测试,这对可用资源来说根本没有压力。此外,所提供的服务甚至不会显示在 Android 设备的电池使用监视器中。

非常感谢任何帮助。

Here is what I am dealing with.

I have a widget associated to my Android App which I want to update every 10 minutes (currently using AlarmManager) only if the screen is ON. If the screen is OFF the alarms for the pendingIntent are cancelled. Once the screen comes ON again I check if the last update and current time has a difference of 10 minutes or more, if it is I send out a broadcast to update the widget.

What happens and is the problem is the alarms for the pending Intent probably are not cancelled (probably) and the widget update is executed for all the alarms for the pendingIntent that were stacked up when the screen was OFF.

Here are some code snippets.

@Override
public void onReceive(Context context, Intent intent) {
        check_intent = intent.getAction();

            if(check_intent.equals("android.appwidget.action.APPWIDGET_UPDATE")){

                 mAppPreferences = PreferenceManager.getDefaultSharedPreferences(context);
                 int saved_num_widgets = mAppPreferences.getInt(NUM_WIDGETS, 0);
        /*Check if there is atleast one widget on homescreen*/       
                 if (saved_num_widgets>0){
                        boolean check = CheckScreenOn.check_screen_on(context);
/*Check if Screen is ON*/
                            if(check == true){
                                                Intent widgetUpdate = new Intent(context, MyWidget.class);
                                                widgetUpdate.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
                                                alarms = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
                                                newPending = PendingIntent.getBroadcast(context, 0, widgetUpdate,0);
                                                alarms.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime()+ PERIOD, newPending);
                                                context.startService(new Intent(context, UpdateService.class));
                            }
                            else{
                                alarms.cancel(newPending);
/*Screen is OFF no point updating the widget, cancel Alarms and do nothing*/
                            }
                     }
                     else{
                            int duration = Toast.LENGTH_LONG;
                            CharSequence text = "Please place My Widget on your home screen to keep earning money.";
                            Toast toast = Toast.makeText(context, text, duration);
                            toast.show();
                     }
                    }   
                if(check_intent.equals("android.appwidget.action.APPWIDGET_ENABLED")){
                    this.onEnabled(context);
                }
                if(check_intent.equals("android.appwidget.action.APPWIDGET_DELETED")){
                    this.onDeleted(context);
                }
                if(check_intent.equals("android.appwidget.action.APPWIDGET_DISABLED")){
                    this.onDisabled(context);
                }


    }

Here is the BroadcastReceiver that receives the SCREEN_ON broadcast and sends out the request for the widget update if current time - last time widget was updated >= 10 minutes.

registerReceiver(new BroadcastReceiver() {

              @Override
              public void onReceive(Context context, Intent intent) {
                // ... 
                long update_interval = mAppPreferences.getLong(LASTUPDATETIME, 0);
                long curtimemillis = System.currentTimeMillis();
                long calculate_interval = curtimemillis - update_interval;
                if(calculate_interval >= PERIOD){
                    int saved_num_widgets = mAppPreferences.getInt(NUM_WIDGETS, 0);

                    if (saved_num_widgets>0){

                               alarms.cancel(newPending);
                            Intent widgetUpdate = new Intent(context, MyWidget.class);
                            widgetUpdate.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
                            context.sendBroadcast(widgetUpdate);
                        }

                    }

                  }
                }, new IntentFilter(Intent.ACTION_SCREEN_ON));

Lets say that the last update happened at 10:00 am and the screen was off for 30 minutes. When the screen comes on, the widget gets updated for all the alarms stored for the pendingIntent at once. I want the widget update to happen only once when the screen come on again.

Initially I understood that AlarmManager.ELAPSED_REALTIME triggers when the devices wakes up from being idle.

I don't know why the alarm cancel don't work. Everything else works as expected.

By the way I have done performance tests on the 10 minute widget update on variety of devices and it is not at all a strain on available resources. Moreover the delivered the service does not even show up in the Battery Use monitor for Android devices.

Any help is much appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

土豪我们做朋友吧 2024-10-29 05:30:46

我也见过这个。将其更改为使用接收 SCREEN_OFF 或 SCREEN_ON 并手动停止/启动警报服务的广播接收器。

抱歉,这不是您想要的答案:-)

I've seen this as well. Changed it to use a broadcast receiver that receives SCREEN_OFF or SCREEN_ON and stopping/starting the Alarm service manually.

Not the answer you may of been wanting sorry :-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文