应用程序小部件更新服务有时会强制关闭 - 需要帮助!

发布于 2024-11-07 17:59:30 字数 3822 浏览 1 评论 0原文

这个问题的背景。我有一个与我的应用程序关联的应用程序小部件,它使用更新服务定期更新,该服务将 http 发布到服务器并使用从服务器接收的数据更新小部件。

我从测试和用户报告中注意到,当小部件更新并且网络状态从可用变为不可用时,这种强制关闭的特定实例会定期发生(但很少见)。因为我在纽约地铁的手机上注意到了这一点。

在调试时,我发现如果发生了 http post 并且网络状态在收到响应之前发生了变化,它基本上会收到 IOException。因此,我处理了这个异常,并在这种特殊情况下使用默认更新更新了小部件。效果很好。

但有趣的是,我再次注意到这个强制关闭,并且已经没有办法解决这个问题了。

有没有人遇到过这种情况并知道我该如何处理?

 java.lang.NullPointerException
    at android.widget.RemoteViews$ReflectionAction.writeToParcel(RemoteViews.java:399)
    at android.widget.RemoteViews.writeToParcel(RemoteViews.java:1003)
    at com.android.internal.appwidget.IAppWidgetService$Stub$Proxy.updateAppWidgetProvider(IAppWidgetService.java:402)
    at android.appwidget.AppWidgetManager.updateAppWidget(AppWidgetManager.java:283)
    at com.tyu.android.TyuWidget$UpdateService$1.run(TyuWidget.java:167)

一些代码片段可能会帮助所有专家更好地理解问题并帮助初学者。

@Override
public void onReceive(Context context, Intent intent) {
        check_intent = intent.getAction();
            if(check_intent.equals("android.appwidget.action.APPWIDGET_UPDATE")){
        this.onUpdate(context, intent);
        }   
}

这是 OnUpdate 方法的代码片段。

    public void onUpdate(Context context, Intent intent){
            Intent widgetUpdate = new Intent(context, TyuWidget.class);
            widgetUpdate.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
            AlarmManager alarms = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
            PendingIntent newPending = PendingIntent.getBroadcast(context, 0, widgetUpdate,PendingIntent.FLAG_UPDATE_CURRENT);
            alarms.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime()+ PERIOD, newPending);
            context.startService(new Intent(context, UpdateService.class));

}

UpdateService 类的 OnStart 方法内的线程用于更新小部件。

widgetUpdateThread = new Thread(){
                @Override
                public void run(){
                    RemoteViews updateViews = buildUpdate(getApplicationContext());
                    if(updateViews!=null){
                        ComponentName thisWidget = new ComponentName(getApplicationContext(), TyuWidget.class);
                        AppWidgetManager manager = AppWidgetManager.getInstance(getApplicationContext());
                        manager.updateAppWidget(thisWidget, updateViews);
                    }
                    else{
                        updateViews = new RemoteViews(getApplicationContext().getPackageName(), R.layout.tuwidget);
                        updateViews.setImageViewResource(R.id.ad, R.drawable.tyu_null_game);
                        Intent defineIntent1 = new Intent(getApplicationContext(), Tyu3.class);
                        PendingIntent pendingIntent1 = PendingIntent.getActivity(getApplicationContext(),
                                0 /* no requestCode */, defineIntent1, 0 /* no flags */);
                        updateViews.setOnClickPendingIntent(R.id.tuwidget, pendingIntent1);
                        ComponentName thisWidget = new ComponentName(getApplicationContext(), TyuWidget.class);
                        AppWidgetManager manager = AppWidgetManager.getInstance(getApplicationContext());
                        manager.updateAppWidget(thisWidget, updateViews);

                    }
                }
            };             
            widgetUpdateThread.start();  

buildUpdate方法代码片段。

public RemoteViews buildUpdate(Context context) {   

httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
response = httpclient.execute(httppost);
entity = response.getEntity();
is = entity.getContent();

//etc etc...and then I return the update view and it gets updated.  
} 

感谢您的帮助。

Background to this problem. I have an appwidget associated with my app that updates at set intervals periodically, using an Update Service that does http posts to server and updates the widget with data received from the server.

What I have noticed from my tests and user reports is that this particular instance of force close happens periodically (but rare) when its time for the widget to update and the network state changes from available to unavailable. Since I have noticed this on my phone in NYC subways.

While debugging I figured that if the http post has happened and the network state changes before the response has been received, it basically receives a IOException. So I handled this exception and updated the widget in this particular case with a default update. It worked fine.

But interestingly I have noticed this Force Close again and am running out of ideas how to resolve this.

Has anyone encountered this before and know how I can handle this?

 java.lang.NullPointerException
    at android.widget.RemoteViews$ReflectionAction.writeToParcel(RemoteViews.java:399)
    at android.widget.RemoteViews.writeToParcel(RemoteViews.java:1003)
    at com.android.internal.appwidget.IAppWidgetService$Stub$Proxy.updateAppWidgetProvider(IAppWidgetService.java:402)
    at android.appwidget.AppWidgetManager.updateAppWidget(AppWidgetManager.java:283)
    at com.tyu.android.TyuWidget$UpdateService$1.run(TyuWidget.java:167)

Some code snippets that might help all you experts to better understand the problem and help a beginner.

@Override
public void onReceive(Context context, Intent intent) {
        check_intent = intent.getAction();
            if(check_intent.equals("android.appwidget.action.APPWIDGET_UPDATE")){
        this.onUpdate(context, intent);
        }   
}

Here is the OnUpdate method code snippet.

    public void onUpdate(Context context, Intent intent){
            Intent widgetUpdate = new Intent(context, TyuWidget.class);
            widgetUpdate.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
            AlarmManager alarms = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
            PendingIntent newPending = PendingIntent.getBroadcast(context, 0, widgetUpdate,PendingIntent.FLAG_UPDATE_CURRENT);
            alarms.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime()+ PERIOD, newPending);
            context.startService(new Intent(context, UpdateService.class));

}

Thread inside OnStart method of UpdateService class that updates the widget.

widgetUpdateThread = new Thread(){
                @Override
                public void run(){
                    RemoteViews updateViews = buildUpdate(getApplicationContext());
                    if(updateViews!=null){
                        ComponentName thisWidget = new ComponentName(getApplicationContext(), TyuWidget.class);
                        AppWidgetManager manager = AppWidgetManager.getInstance(getApplicationContext());
                        manager.updateAppWidget(thisWidget, updateViews);
                    }
                    else{
                        updateViews = new RemoteViews(getApplicationContext().getPackageName(), R.layout.tuwidget);
                        updateViews.setImageViewResource(R.id.ad, R.drawable.tyu_null_game);
                        Intent defineIntent1 = new Intent(getApplicationContext(), Tyu3.class);
                        PendingIntent pendingIntent1 = PendingIntent.getActivity(getApplicationContext(),
                                0 /* no requestCode */, defineIntent1, 0 /* no flags */);
                        updateViews.setOnClickPendingIntent(R.id.tuwidget, pendingIntent1);
                        ComponentName thisWidget = new ComponentName(getApplicationContext(), TyuWidget.class);
                        AppWidgetManager manager = AppWidgetManager.getInstance(getApplicationContext());
                        manager.updateAppWidget(thisWidget, updateViews);

                    }
                }
            };             
            widgetUpdateThread.start();  

buildUpdate method code snippet.

public RemoteViews buildUpdate(Context context) {   

httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
response = httpclient.execute(httppost);
entity = response.getEntity();
is = entity.getContent();

//etc etc...and then I return the update view and it gets updated.  
} 

Thanks for the help.

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

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

发布评论

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

评论(2

一抹淡然 2024-11-14 17:59:30

扩展 Service 类的 UpdateService 类的 OnStart() 方法内的线程造成了问题。

解决方案:

摆脱了 widgetUpdateThread 线程,而不是扩展 Service 类,而是使用 IntentService。这会自动生成一个线程并且像一个魅力一样工作。当使用 IntentService 时,我将代码放在 @Override onHandleIntent 中,而不是 OnStart,瞧!即使并行使用 CPU 和内存密集型应用程序(如 FruitNinja),也不会强制关闭。

伙计们! IntentService受到开发者社区和Android Framework工程师的强烈推荐。因此,在更新小部件时请检查一下。

The thread inside OnStart() method of the UpdateService class which extended the Service class was creating the problem.

Solution:

Got rid of the widgetUpdateThread thread and instead of extending Service class, used IntentService. This automatically spawns a thread and works like a charm. Instead of OnStart, when using IntentService I put the code inside @Override onHandleIntent and Voila! No force close even when using apps in parallel that are very very CPU and memory intensive like FruitNinja.

Guys! IntentService is highly recommended by the developer community and Android Framework engineers. So check it out while updating widgets.

二手情话 2024-11-14 17:59:30

我认为 manager.updateAppWidget(thisWidget, updateViews) 中的 thisWidget 值可能为 null。

希望这有帮助。
光盘。

I think thisWidget value may be null in manager.updateAppWidget(thisWidget, updateViews).

Hope this helps.
CD.

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