应用程序被强制停止后小部件无法正常启动

2022-01-18 00:00:00 widget android java

我有一个小部件,它根据按下的各种小部件按钮启动到特定页面.当我有应用程序在内存中时它工作正常(即从部署(运行/调试),但是当我强制停止应用程序时,小部件不再正常工作.

I have a widget which launches to a particular page based on the various widget buttons pressed. It works fine when I have the app in-memory (i.e. from deploy (run / debug), however when I force stop the app, the widget no longer functions properly.

当app被强制停止后,第一次点击widget正常工作,并调用对应Activity的onCreate.然后,当按下 home 键,并按下不同的 widget 按钮时,会调用前一个 widget Activity 的 onRestart 方法.

When the app has been force stopped, the first click of the widget works properly, and the onCreate for the corresponding Activity is called. Then, when the home key is pressed, and a different widget button is pressed, the onRestart method of the previous widget Activity is called.

奇怪的是,没有出现日志消息,并且由于无法连接调试器,因此测试起来相当困难.有什么特别是我做错了吗?

It is odd, b/c the log messages do not appear, and since the debugger cannot be connected, it's been rather difficult to test. Is there anything in particular that I'm doing wrong?

流程是 --> WidgetDispatchActivity(处理真正的小部件目的地)--> ViewActivity> --> 进一步分支(DetailViewActivity 在下面的例子)

The flow is --> WidgetDispatchActivity (handle true widget destination) --> ViewActivity> --> further branch (DetailViewActivity in below example)

onUpdate 小部件:

onUpdate(){
...


       Intent viewIntent = new Intent(context, WidgetDispatchActivity.class);
                    viewIntent.putExtra("launch", WidgetInfo.VIEW_ACTIVITY);
                    PendingIntent viewPendIntent = PendingIntent.getActivity(context, 2, viewIntent, PendingIntent.FLAG_UPDATE_CURRENT);

...
}

WidgetDispatchActivity 的onCreate:

WidgetDispatchActivity's onCreate:

 Bundle b = getIntent().getExtras();
        if (b != null && b.isEmpty()){
            Log.i(LOG_TAG, "EMPTY BUNDLE ON WIDGET!");
        }else{
            Log.i(LOG_TAG, "WIDGET BUNDLE HAS ITEMS!");
        }

        String destination = null;
        if (b != null && b.containsKey("launch")){
            destination = b.getString("launch");
            Log.i(LOG_TAG, "WIDGET ITEM FROM BUNDLE WAS: " + destination);
        }
        else{
            Log.i(LOG_TAG, " "launch" item was not inside bundle!");
        }

        if(destination != null) {
            Log.i(LOG_TAG, "PendingIntent received from widget!");
            Intent goTo = new Intent(this, ViewActivity.class);
               ...
}
}

LogCat

10-10 20:38:00.935: INFO/ActivityManager(58): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10200000 cmp=com.android.launcher/com.android.launcher2.Launcher }
10-10 20:38:00.956: INFO/DetailViewActivity(1154): ONPAUSE
10-10 20:38:00.975: WARN/InputManagerService(58): Ignoring hideSoftInput of: com.android.internal.view.IInputMethodClient$Stub$Proxy@450366d0
10-10 20:38:02.545: INFO/ActivityManager(58): Starting activity: Intent { flg=0x10000000 cmp=com.starbucks.mobilecard/com.xxx.xxx.widget.WidgetDispatchActivity bnds=[198,298][224,321] (has extras) }
10-10 20:38:02.585: INFO/ViewActivity(1154): ONRESTART
10-10 20:38:02.585: INFO/ViewActivity(1154): WIDGET LAUNCH:: == false

ViewActivity onRestart:

ViewActivity onRestart:

protected void onRestart(){
        super.onRestart();
        Log.i(LOG_TAG,"ONRESTART");

        Log.i(LOG_TAG,"WIDGET LAUNCH:: == " + WidgetInfo.getInstance().wasLaunchedFromWidget());
                 ...
}

AndroidManifest:

AndroidManifest:

<activity android:name="com.xxx.xxx.ui.cards.ViewActivity" android:label="@string/_view_title" android:finishOnTaskLaunch="true" android:clearTaskOnLaunch="true" android:screenOrientation="portrait"/>

<activity android:name="com.xxx.xxx.widget.WidgetDispatchActivity" android:label="@string/widget_dispatch_title" android:finishOnTaskLaunch="true"/>

推荐答案

Willmel,

强制关闭时阻止小部件工作的第一步是实现 onDestroy().在这里,您需要确保与您的 WidgetHost、HostViews 和 RemoteViews 进行通信,它们构成了您的 Widget 通信.

The first step in stopping your widgets from working when you Force Close is implementing your onDestroy(). Here you will want to make sure you talk to your WidgetHost, the HostViews and the RemoteViews that make up your Widget communications.

此语句阻止 WidgetHost 接收来自 Android 的任何事件.myHost 是对象,通常是一个 Activity,它持有对您的 Widget 的引用.

This statement stops the WidgetHost from receiving any events from Android. myHost is the object, often an Activity that is holding the references to your Widget.

// Stop the Widgets from fidgeting
    myHost.stopListening();
    myHost = null;

从那里,您需要删除对您可能引用的任何 HostView 的任何引用.这是通过简单地获取引用并将其设置为 null 来完成的.在我的 onDestroy() 我使用以下循环...

From there, you'll want to remove any reference to any of the HostViews you might have a reference to. This is done by simply grabbing the reference and setting it to null. In my onDestroy() I use the following loop...

if (appWidgets != null) {
    final int count = appWidgets.size();
    for (int i = 0; i < count; i++) {
        final Widget launcherInfo = appWidgets.get(i);
        launcherInfo.hostView = null;
    }
}

在这里,launcherInfo 是我扩展的 AppWidget 对象.hostView 指的是我的 AppWidgetHostView(这是代表我的 Widget 的视图).appWidgets 数组是我的启动器正在跟踪的小部件列表.总的来说很简单.

In here, launcherInfo is my extended AppWidget object. hostView refers to my AppWidgetHostView (which is the view that represents my Widget). The appWidgets array is my list of Widgets that my launcher is tracking. Pretty simple over all.

使用 Widget 和 WidgetHost 可能会出现问题,具体取决于您的设置.上面这句话放在对的地方确实有助于减轻痛苦.

Working with Widgets and WidgetHosts can be problematic, depending on your set up. The above statements in the right place really help to ease the suffering.

模糊逻辑

相关文章