无法添加窗口 - 令牌null无效; 你的活动在运行吗?

Ham*_*dTB 29 android

我想在用户点击浮动图标时显示自定义弹出菜单

浮动图标使用服务创建,我没有活动

这是我的浮动图标代码

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);             
    }
}
Run Code Online (Sandbox Code Playgroud)

一切都很好,但当我点击浮动按钮应用程序停止,这个错误显示在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?
Run Code Online (Sandbox Code Playgroud)

但我没有活动?!

我想在用户点击浮动图标后弹出菜单显示; 但弹出菜单只能显示文字;

如何才能显示带图标的弹出菜单?

Kis*_*nki 52

如果您使用getApplicationContext()作为Context像这样的对话

Dialog dialog = new Dialog(getApplicationContext());
Run Code Online (Sandbox Code Playgroud)

然后使用YourActivityName.this

Dialog dialog = new Dialog(YourActivityName.this);
Run Code Online (Sandbox Code Playgroud)

  • 上面的解决方案不相关。当没有活动时,我们正在寻找上下文。这个解决方案需要一个活动,这绝对不是我们正在寻找的。 (6认同)
  • 如果我使用 Fragment 怎么办 (3认同)
  • 效果完美! (3认同)
  • @Flash然后你可以在Fragment中使用requireActivity() (2认同)
  • 谢谢,拯救了我的一天。 (2认同)
  • 如果您想知道为什么 `YourActivityName.this` 有效但 `getApplicationContext()` 无效,请参阅此答案 /sf/answers/1607701581/ (2认同)

小智 11

我遇到了和你一样的问题,看起来你像我一样使用了http://www.piwai.info/chatheads-basics的教程.问题是您无法将当前活动可靠地传递到弹出窗口,因为您无法控制当前活动.看起来可能有一种不可靠的方式来获取当前活动,但我不建议这样做.

我为我的应用程序修复它的方法是不使用弹出窗口,而是通过窗口管理器自己创建.

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);  
    }
Run Code Online (Sandbox Code Playgroud)

如果您希望它看起来像一个弹出窗口,只需添加一个透明的灰色视图作为背景,并向其添加一个onClickListener以从windowManager对象中删除该视图.

我知道这不像弹出窗口那么方便,但从我的经验来看,这是最可靠的方式.

并且不记得在清单文件中添加权限

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
Run Code Online (Sandbox Code Playgroud)

  • 此错误也发生在 `windowManager.addView(view, params)` 处 - `由 android.view.WindowManager$BadTokenException 导致无法添加窗口 - 令牌 null 无效;您的活动正在运行吗? (3认同)

Moh*_*ane 10

如果您使用另一个,view请确保使用view.getContext()而不是this或getApplicationContext()


Sac*_*per 6

您需要在构造函数中传递您的活动

 PopupWindow popupWindow = new PopupWindow(YourActivity.this)
Run Code Online (Sandbox Code Playgroud)

  • 我没有活动要做;此代码在服务而非活动上运行 (2认同)

Man*_*ddy 6

当您尝试过早显示popUpWindow,要对其进行修复,将ID赋予主布局main_layout并使用以下代码时,会发生此错误

Java:

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

科特林:

 main_layout.post {
      popupWindow?.showAtLocation(main_layout, Gravity.CENTER, 0, 0)
    }
Run Code Online (Sandbox Code Playgroud)

感谢@kordzik