5

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.

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?

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

onUpdate for widget:

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'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:

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

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

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"/>
William Melani
  • 4,270
  • 1
  • 21
  • 44
  • 1
    Willmel, I can't be sure without seeing more of your code, but I believe you may be missing some important unregistration code for your AppWdiget when the application is Force Closed. AppWidgets work a little differently than other Components as they are components themselves. They must be removed from the Provider and the RemoteView removed, otherwise, you get multiple instances of the same widget. This is a recipe for a memory leak. – Fuzzical Logic Oct 14 '11 at 10:23
  • @FuzzicalLogic thanks for the reply. I'm looking for anything on google about 'unregistering app widget', but don't seem to find anything. Do you have a link/example? – William Melani Oct 14 '11 at 16:53
  • Willmel, I noticed you applied the bounty. Does this mean that your problem is solved? – Fuzzical Logic Oct 19 '11 at 06:37
  • @FuzzicalLogic well actually no, but the project I was working on got de-scoped, so I have to table it for now and work on other things. I greatly appreciate your help though, I learned quite a bit more about android widgets! Thanks – William Melani Oct 19 '11 at 16:36

1 Answers1

1

Willmel,

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.

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;

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;
    }
}

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.

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.

FuzzicalLogic

Fuzzical Logic
  • 12,947
  • 2
  • 30
  • 58
  • Thanks for the reply. This does not appear to be the same widget technique that I have already (Mine looks similar to this blog : http://ericosgood.com/prog/android-appwidget-tutorial/). I can't seem to find one similar to yours (using `Service`? I apologize to bug you again, but do you have a link / code to show AppWidgetProvider and Service are interfaced together? My only real widget requirement is that it can be 'force updated' within the app whenever I need it to be. – William Melani Oct 14 '11 at 22:18
  • I am confused by your post. AppWidgetProvider is a Receiver, not a Service. AppWidgetHost is in the Activity that holds the RemoteView created by your AppWidgetProvider. If you are in control of that Activity, then this is what needs to be adjusted. If you are not in control of that Activity, then I was mistaken and the bug may or may not be yours. Does this provide the clarification you need? – Fuzzical Logic Oct 15 '11 at 05:46
  • To answer your question more effectively, your Home Screen has a AppWidgetHost. Any Activity may have one. Based on your description, I assumed you were controlling the destination Activity (which should hold the Host). If you do not, then my answer and comments do not apply. :) – Fuzzical Logic Oct 15 '11 at 05:53
  • 1
    And for further clarification, yes, I can provide an example. However, if you are not in control of the destination Activity as I thought you were, then it may be of no benefit to you. – Fuzzical Logic Oct 15 '11 at 06:55
  • I'm in control of the destination in that it will always be an activity in my app. The underlying issue for me is more that pages are not destroyed when the app is backgrounded, and they open on top of the widget launching activity before it can execute. It looks like the AppWidgetHost paradigm is almost for creating a `Launcher`, which is not what I'm looking for. – William Melani Oct 17 '11 at 23:58
  • The AppWidgetHost is not for creating a Launcher. The AppWidgetHost is for any Activity that uses AppWidgets. The extent of use and creation of icons is what defines a Launcher. Your AppWidget will always interface with an AppWidgetHost whether you want define it or not. Your definition and implementation of it just tells the Android OS that you are in control, rather than the OS using its default implementation. Its very similar to the Application object. You can override it and manage your own instructions, or you can let the OS do what it thinks it needs to. – Fuzzical Logic Oct 18 '11 at 17:17
  • @FuzzicalLogic please check my question http://stackoverflow.com/questions/33016470/widget-not-working-after-force-quit-app?noredirect=1#comment53855932_33016470 – Ziad Halabi Oct 08 '15 at 13:13