Невозможно добавить нулевой токен окна; работает ли ваша деятельность?

Я хочу показать пользовательское всплывающее меню, когда пользователь нажимает на плавающий значок

значок float создается с помощью службы, и у меня нет активности

это мой плавающий код значка

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

все отлично, но когда я нажимаю кнопку приложения с плавающей кнопкой, и эта ошибка отображается на 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?

но у меня нет активности?!

я хочу, чтобы всплывающее меню отображалось после щелчка пользователем по значку float; но всплывающее меню может показывать только текст;

как я могу показать всплывающее меню с иконками?

Ответ 1

У меня была такая же проблема, как и у вас, похоже, вы использовали учебник с 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);  
    }

Если вы хотите, чтобы это выглядело как всплывающее окно, просто добавьте прозрачный серый вид в качестве фона и добавьте в него onClickListener, чтобы удалить вид из объекта windowManager.

Я знаю, что это не так удобно, как всплывающее окно, но из моего опыта это самый надежный способ.

и не забудьте добавить разрешение в файл манифеста

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

Ответ 2

Если вы используете getApplicationContext() в качестве Context в Activity для такого диалога, как этот

Dialog dialog = new Dialog(getApplicationContext());

затем используйте YourActivityName.this

Dialog dialog = new Dialog(YourActivityName.this);

Ответ 3

Вам нужно передать свою активность в конструкторе

 PopupWindow popupWindow = new PopupWindow(YourActivity.this)

Ответ 4

Эта ошибка возникает, когда вы пытаетесь показать popUpWindow слишком рано, чтобы исправить это, присвоить идентификатор основной раскладке как main_layout и использовать приведенный ниже код

Джава:

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

Котлин:

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

Кредит @kordzik

Ответ 5

Используйте этот Dialog dialog = new Dialog(theActivity.this); Вместо Dialog dialog = new Dialog(getApplicationContext); или Dialog dialog = new Dialog(context);

Ответ 6

PopupWindow может быть привязан только к Activity. В вашем случае вы пытаетесь добавить PopupWindow в service, что неверно.

Чтобы решить эту проблему, вы можете использовать пустой и прозрачный Activity. При щелчке значка с плавающей точкой запустите Activity и onCreate Activity, покажите PopupWindow.

При увольнении PopupWindow вы можете finish прозрачный Activity. Надеюсь, это поможет вам.

Ответ 7

У меня была та же проблема, я исправил это с помощью решения @Redman и некоторых других,

Вот что я сделал.

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

добавил метод Runnable и в методе onDestroy я проверил, показывает ли всплывающее окно, ноль или нет.

 @Override
protected void onDestroy() {
    super.onDestroy();

    if (popupWindow.isShowing())
    {
        popupWindow.dismiss();
        popupWindow=null;
    }
    }

Ответ 8

используйте YOURACTIVITY.this вместо getApplicationContext()

Ответ 9

Эта ошибка вызвана передачей неверного контекста.

Вы должны передать свою активность как контекст, getApplicationContext() не будет работать.

Следовательно, приведите ваш контекст к деятельности.

В Котлине

context as HomeActivity

Ответ 10

Если вы используете getBaseContext() или getApplicationContext() в качестве контекста для диалога, как это

Dialog dialog = new Dialog(getBaseContext()); 

или же

Dialog dialog = new Dialog(getApplicationContext());

затем используйте YourActivityName.this

Диалог диалога = новый диалог (YourActivityName.this);

Ответ 11

Вы не должны помещать windowManager.addView в onCreate

Попробуйте вызвать windowManager.addView после onWindowFocusChanged, и статус hasFoucus будет истинным.

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    //code here
    //that you can add a flag that you can call windowManager.addView now.
}