7

I need to launch a popup window from a service to do something specific inside my application. I do not seem to find a good way to do it. Inside onCreate() I create the popup window but when I launch it with showAtLocation I get this error:

10-06 13:39:49.573: ERROR/AndroidRuntime(5966): Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?

Can someone please help? Thanks,

-em

emi
  • 91
  • 1
  • 1
  • 3

2 Answers2

8

I had the same problem and here if how i solved it. At first time i've tried to use Android's native PopupWindow class, but later i decided to use WindowManager like this way :

public class MyService extends Service {

private View mView;

private WindowManager.LayoutParams mParams;
private WindowManager mWindowManager;

@Override
public void onCreate() {
    super.onCreate();

    mView = new MyLoadView(this);

    mParams = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.MATCH_PARENT, 150, 10, 10,
            WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
            WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
            PixelFormat.TRANSLUCENT);

    mParams.gravity = Gravity.CENTER;
    mParams.setTitle("Window test");

    mWindowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
    mWindowManager.addView(mView, mParams);

}

@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onDestroy() {
    super.onDestroy();
    ((WindowManager)getSystemService(WINDOW_SERVICE)).removeView(mView);
    mView = null;
}

public class MyLoadView extends View {

    private Paint mPaint;

    public MyLoadView(Context context) {
        super(context);
        mPaint = new Paint();
        mPaint.setTextSize(50);
        mPaint.setARGB(200, 200, 200, 200);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawText("test test test", 0, 100, mPaint);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}
}

And you can call this service class via intent :

intent = new Intent(mContext, MyService.class);
if (intent != null) {
     getContext().startService(intent);
}

Also, set permission in your manifest file :

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

I referenced Android's LoadAverageService.java class, and i finally created a popup window from service! This is a very simple example, so you might need to add something more if you want to develop complex functions. Hope this will help you and others.

Nari Kim Shin
  • 2,459
  • 1
  • 25
  • 33
0

Service runs in background without UI so you have to start some avtivity with calling startActivity with appropriate Intent.

slkorolev
  • 5,883
  • 1
  • 29
  • 32
  • thanks. Could you be a bit more specific? My goal is to launch the popup window from the service without going through an activity. In particular, I want to launch the popup window and have it sit on top of all the other windows as the user normally uses the phone. Can this be done? – emi Oct 06 '11 at 18:04
  • I think you have to start an activity anyway. You can assign it Theme.Dialog theme to make it look like dialog on top of current user screen. Just found a dsicussion [here](http://stackoverflow.com/questions/2394477/make-android-activity-looks-like-dialog). – slkorolev Oct 06 '11 at 18:09
  • you mean starting activity X from the service and having activity X launch the dialog? – emi Oct 06 '11 at 18:36
  • Yes. As in the discussion they assign Theme.Translucent.NoTitleBar to the activity X and then show some dialog. – slkorolev Oct 06 '11 at 18:51
  • ok. One thing: would everything else underneath the activity clickable as the activity was not present? I need the dialog remaining visible while the user performs normal operations with the phone (changing views, apps etc) – emi Oct 06 '11 at 19:12
  • Now I understand the idea. To my knowledge it hardly can be done. – slkorolev Oct 06 '11 at 19:20