100

I want to show a custom popup menu when the user clicks on a floating icon

the floating icon create with service and i have no activity

this is my floating icon code

public class copy_actions_service extends Service
{
    ImageView copy_ImageView;
    WindowManager windowManager;
    WindowManager.LayoutParams layoutParams;

    @Override
    public IBinder onBind(Intent arg0)
    {
        // TODO Auto-generated method stub
        return null;
    }
    
    @Override
    
    public void onCreate()
    {
        windowManager=(WindowManager)getSystemService(WINDOW_SERVICE);
        
        copy_ImageView=new ImageView(this);
        copy_ImageView.setImageResource(R.drawable.ic_launcher);
        copy_ImageView.setAlpha(245);
        copy_ImageView.setOnClickListener(new OnClickListener()
        {
            
            @Override
            public void onClick(View arg0)
            {
                showCustomPopupMenu();
            }
        });
        
        layoutParams=new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT);
        
        layoutParams.gravity=Gravity.TOP|Gravity.CENTER;
        layoutParams.x=0;
        layoutParams.y=100;
        
        windowManager.addView(copy_ImageView, layoutParams);

    }
    
    private void showCustomPopupMenu()
    {
        LayoutInflater layoutInflater=(LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View view=layoutInflater.inflate(R.layout.xxact_copy_popupmenu, null);
        
        PopupWindow popupWindow=new PopupWindow();
        popupWindow.setContentView(view);
        popupWindow.setWidth(LinearLayout.LayoutParams.WRAP_CONTENT);
        popupWindow.setHeight(LinearLayout.LayoutParams.WRAP_CONTENT);
        popupWindow.setFocusable(true);

        popupWindow.showAtLocation(view, Gravity.NO_GRAVITY, 0, 0);             
    }
}

everything fine but when i click on the float button app stop and this error is shown on logcat :(

11-23 02:18:58.217: E/AndroidRuntime(3231): android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?

but I have no activity?

I want to popup menu show after user click on float icon; but popup menu only can show text;

how can I show a popup menu with icons?

HamidTB
  • 1,219
  • 3
  • 11
  • 15

9 Answers9

216

If you're using getApplicationContext() as Context in Activity for the dialog like this

Dialog dialog = new Dialog(getApplicationContext());

then use YourActivityName.this

Dialog dialog = new Dialog(YourActivityName.this);
Kishan Solanki
  • 11,648
  • 2
  • 65
  • 69
24

This error happens when you are trying to show pop-up window too early, to fix it, give Id to the main layout as main_layout and use the below code:

Java:

 findViewById(R.id.main_layout).post(new Runnable() {
   public void run() {
       popupWindow.showAtLocation(findViewById(R.id.main_layout), Gravity.CENTER, 0, 0);
   }
});

Kotlin:

 main_layout.post {
      popupWindow?.showAtLocation(main_layout, Gravity.CENTER, 0, 0)
    }

Credit to @kordzik

Manohar
  • 19,149
  • 8
  • 90
  • 129
18

I had the same problem as you, it looks like you used the tutorial from http://www.piwai.info/chatheads-basics like I did. The problem is that you cannot reliably pass the current activity to the popup window, because you have no control over the current activity. It looks like there might be a unreliable way to get the current activity, but I don't recommend that.

The way I fixed it for my app was to not use the popup window, but instead make my own through the window manager.

private void showCustomPopupMenu()
{
    windowManager2 = (WindowManager)getSystemService(WINDOW_SERVICE);
    LayoutInflater layoutInflater=(LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view=layoutInflater.inflate(R.layout.xxact_copy_popupmenu, null);
    params=new WindowManager.LayoutParams(
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.TYPE_PHONE,
        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
        PixelFormat.TRANSLUCENT
    );

    params.gravity=Gravity.CENTER|Gravity.CENTER;
    params.x=0;
    params.y=0;
    windowManager2.addView(view, params);  
}

If you want this to look like a popup window, just add a transparent gray view as the background and add a onClickListener to it to remove the view from the windowManager object.

I know this isn't as convenient as a popup, but from my experience, it is the most reliable way.

and don't forget to add permission in your manifest file

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
Donald Duck
  • 7,638
  • 19
  • 69
  • 90
skit456
  • 230
  • 1
  • 4
  • how to dismiss this windowmanager when user click outside this view? – nidhi May 07 '18 at 11:27
  • @nidhi use `windowManager2.removeViewImmediate(view);` but make your inflated view a global variable `private View view;` – Pierre Feb 18 '20 at 08:19
  • 3
    this error happens at `windowManager.addView(view, params)` as well - `Caused by android.view.WindowManager$BadTokenException Unable to add window -- token null is not valid; is your activity running?` – user924 May 19 '21 at 11:10
11

You need to pass your activity in the constructor

 PopupWindow popupWindow = new PopupWindow(YourActivity.this)
SacreDeveloper
  • 1,225
  • 1
  • 9
  • 15
5

If you use another view make sure to use view.getContext() instead of this or getApplicationContext()

2

I was getting this error while trying to show DatePicker from Fragment.

I changed

val datePickerDialog = DatePickerDialog(activity!!.applicationContext, ...)

to

val datePickerDialog = DatePickerDialog(requireContext(), ...)

and it worked just fine.

Ananth
  • 2,372
  • 25
  • 38
2

In my case, I was inflating a PopupMenu at the very beginning of the activity i.e on onCreate()... I fixed it by putting it in a Handler

  new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                PopupMenu popuMenu=new PopupMenu(SplashScreen.this,binding.progressBar);
                popuMenu.inflate(R.menu.bottom_nav_menu);
                popuMenu.show();
            }
        },100);
AgentP
  • 4,794
  • 2
  • 22
  • 39
1

PopupWindow can only be attached to an Activity. In your case you are trying to add PopupWindow to service which is not right.

To solve this problem you can use a blank and transparent Activity. On click of floating icon, launch the Activity and on onCreate of Activity show the PopupWindow.

On dismiss of PopupWindow, you can finish the transparent Activity. Hope this helps you.

rafsanahmad007
  • 23,761
  • 6
  • 46
  • 59
KR_Android
  • 1,129
  • 9
  • 19
  • i want show popup menu after click on float icon; i can do this but popup menu only show text not icon; how i can make an custom popup menu with icon ? – HamidTB Nov 23 '14 at 11:07
0

You should not put the windowManager.addView in onCreate

Try to call the windowManager.addView after onWindowFocusChanged and the status of hasFoucus is true.

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    //code here
    //that you can add a flag that you can call windowManager.addView now.
}
adiga
  • 31,610
  • 8
  • 53
  • 74
Bruce
  • 1,679
  • 1
  • 12
  • 12
  • This solution almost worked for me, in the sense that it did not make crash the application, but the problem is that also when you dismiss the window the `onWindowFocusChanged` is called again thus showing the window repeatedly – Tiziano Mischi Aug 25 '20 at 16:34