Reputation: 3772
I am creating a widget similar to Google search widget for android.
How're they implementing the quick action popup on clicking the filter? (The left most item with 'g' logo)
Here's the code for it - In my app widget provider I have the following -
Intent activityIntent = new Intent(context, SearchActivity.class);
Bundle infoBundle = new Bundle();
infoBundle.putBoolean(HOME_BUTTON_CLICKED, true);
activityIntent.putExtras(infoBundle);
activityIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent homeButtonPI = PendingIntent.getActivity(context, requestCode, activityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.homeButton, homeButtonPI);
In my SearchActivity I have this in my onCreate() -
if(bundle.getBoolean(CMWidget.HOME_BUTTON_CLICKED)) {
showQuickAction((ImageButton)findViewById(R.id.home_button));
}
Here is the showQuickAction() function which actually brings the popup window -
public void showQuickAction(View view){
//populate the quick action
quickAction = new QuickAction(view, SearchActivity.this);
final ImageButton homeButton = (ImageButton)findViewById(R.id.home_button);
final ActionItem quickActionEverything = new ActionItem();
quickActionEverything.setTitle("Everything");
quickActionEverything.setIcon(getResources().getDrawable(R.drawable.logo));
quickActionEverything.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
quickAction.dismiss();
CONTENT_TYPE = CONTENT_EVERYTHING;
homeButton.setImageResource(R.drawable.logo_arrow);
searchBox.setHint(R.string.search);
if(previousContentType != CONTENT_TYPE && queryString.length() != 0){
emptyListContents();
cancelRunningWSCall();
startSearch(queryString);
}
else if(queryString.length() != 0 )
populateList(CONTENT_TYPE);
else if(queryString.length() == 0)
showRecentSearches();
showSoftKeyboard();
previousContentType = CONTENT_TYPE;
}
});
final ActionItem quickActionContacts = getQuickActionItem(homeButton, CONTENT_CONTACTS, R.drawable.contacts, R.drawable.contacts_arrow);
final ActionItem quickActionMails = getQuickActionItem(homeButton, CONTENT_MAILS, R.drawable.mails, R.drawable.mails_arrow);
final ActionItem quickActionCalendars = getQuickActionItem(homeButton, CONTENT_CALENDARS, R.drawable.calendars, R.drawable.calendars_arrow);
final ActionItem quickActionDocuments = getQuickActionItem(homeButton, CONTENT_DOCUMENTS, R.drawable.docs, R.drawable.docs_arrow);
quickAction.addActionItem(quickActionEverything);
quickAction.addActionItem(quickActionMails);
quickAction.addActionItem(quickActionCalendars);
quickAction.addActionItem(quickActionDocuments);
quickAction.show();
}
And here is my stacktrace as well -
STACK_TRACE=java.lang.RuntimeException: Unable to start activity ComponentInfo{com.test.android/com.test.android.SearchActivity}: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2787)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2803)
at android.app.ActivityThread.access$2300(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2136)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:144)
at android.app.ActivityThread.main(ActivityThread.java:4937)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
at android.view.ViewRoot.setView(ViewRoot.java:509)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
at android.view.Window$LocalWindowManager.addView(Window.java:424)
at android.widget.PopupWindow.invokePopup(PopupWindow.java:828)
at android.widget.PopupWindow.showAsDropDown(PopupWindow.java:740)
at com.test.android.QuickAction.show(QuickAction.java:68)
at com.test.android.SearchActivity.showQuickAction(SearchActivity.java:1541)
at com.test.android.SearchActivity.onCreate(SearchActivity.java:219)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1069)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2751)
... 11 more
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
at android.view.ViewRoot.setView(ViewRoot.java:509)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
at android.view.Window$LocalWindowManager.addView(Window.java:424)
at android.widget.PopupWindow.invokePopup(PopupWindow.java:828)
at android.widget.PopupWindow.showAsDropDown(PopupWindow.java:740)
at com.test.android.QuickAction.show(QuickAction.java:68)
at com.test.android.SearchActivity.showQuickAction(SearchActivity.java:1541)
at com.test.android.SearchActivity.onCreate(SearchActivity.java:219)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1069)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2751)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2803)
at android.app.ActivityThread.access$2300(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2136)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:144)
at android.app.ActivityThread.main(ActivityThread.java:4937)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)
EDIT: I moved the showQuickAction() function to onResume() and also to onStart(). No luck :(
Here's another stack trace -
java.lang.RuntimeException: Unable to resume activity {com.test.android/com.test.android.SearchActivity}: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3347)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3362)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2808)
at android.app.ActivityThread.access$2300(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2136)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:144)
at android.app.ActivityThread.main(ActivityThread.java:4937)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
at android.view.ViewRoot.setView(ViewRoot.java:509)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
at android.view.Window$LocalWindowManager.addView(Window.java:424)
at android.widget.PopupWindow.invokePopup(PopupWindow.java:828)
at android.widget.PopupWindow.showAsDropDown(PopupWindow.java:740)
at com.test.android.QuickAction.show(QuickAction.java:68)
at com.test.android.SearchActivity.showQuickAction(SearchActivity.java:1546)
at com.test.android.SearchActivity.onResume(SearchActivity.java:262)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1255)
at android.app.Activity.performResume(Activity.java:3864)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3337)
... 12 more
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
at android.view.ViewRoot.setView(ViewRoot.java:509)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
at android.view.Window$LocalWindowManager.addView(Window.java:424)
at android.widget.PopupWindow.invokePopup(PopupWindow.java:828)
at android.widget.PopupWindow.showAsDropDown(PopupWindow.java:740)
at com.test.android.QuickAction.show(QuickAction.java:68)
at com.test.android.SearchActivity.showQuickAction(SearchActivity.java:1546)
at com.test.android.SearchActivity.onResume(SearchActivity.java:262)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1255)
at android.app.Activity.performResume(Activity.java:3864)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3337)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3362)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2808)
at android.app.ActivityThread.access$2300(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2136)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:144)
at android.app.ActivityThread.main(ActivityThread.java:4937)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)
Upvotes: 2
Views: 1394
Reputation:
They start a normal Activity via a PendingIntent
with an action that indicates that the activity should display this submenu.
See the logcat when you click on that button:
I/ActivityManager( 167): Starting: Intent { act=com.android.quicksearchbox.action.QSB_AND_SELECT_CORPUS flg=0x14200000 pkg=com.google.android.googlequicksearchbox cmp=com.google.android.googlequicksearchbox/.SearchActivity bnds=[14,86][86,169] (has extras) } from pid -1
as opposed to when you click the search field:
I/ActivityManager( 167): Starting: Intent { act=android.search.action.GLOBAL_SEARCH flg=0x14200000 pkg=com.google.android.googlequicksearchbox cmp=com.google.android.googlequicksearchbox/.SearchActivity bnds=[86,95][384,160] (has extras) } from pid -1
(act=..
is the action sent with the intent)
Edit to adress the new details, see the comments here:
I think the problem here is that you try to open that Quickaction dialog from onCreate()
. Your activity gets prepared in there, but it is not yet visible. If you now add the dialog, it references it's parent activity and notes that it isn't visible. Which gives you this error. Try to move the parsing of the extra and the creation of the quickaction dialog to a later point in the activity lifecyle. I guess onStart()
is the best place for this.
Upvotes: 2