1

Iam new to android,I want to show alert dialog box in service,I used two methods as shown below

First one without Layout

AlertDialog.Builder builder = new AlertDialog.Builder(MyService.this);
builder.setTitle("Test dialog");
builder.setMessage("Content");
builder.setNeutralButton("Ok", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
        System.exit(0);
    }
});
AlertDialog alert = builder.create();
alert.getWindow().setType(WindowManager.LayoutParams.TYPE_TOAST);
alert.show();

but iam getting error like this as shown as below

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.materialdialoginservice, PID: 25846
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
    at android.view.ViewRootImpl.setView(ViewRootImpl.java:993)
    at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:387)
    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:95)
    at android.app.Dialog.show(Dialog.java:344)
    at com.example.materialdialoginservice.MyService$3.run(MyService.java:98)
    at android.os.Handler.handleCallback(Handler.java:883)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:224)
    at android.app.ActivityThread.main(ActivityThread.java:7561)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:995)

Second one with Layout

AlertDialog.Builder builder = new AlertDialog.Builder(MyService.this);
View view = View.inflate(context, R.layout.activity_layout_view, null);
AlertDialog dialog = builder.create();
dialog.setView(view);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {//8.0 new features
    dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY - 1);
} else {
    dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_TOAST);
}
dialog.show();
Window dialogWindow = dialog.getWindow();
dialogWindow.setGravity(Gravity.CENTER);

I am getting error like this,

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.textstuff, PID: 27418
java.lang.RuntimeException: Unable to start service com.example.textstuff.MyService@134fed7 with Intent { cmp=com.example.textstuff/.MyService }: android.view.WindowManager$InvalidDisplayException: Unable to add window android.view.ViewRootImpl$W@124c071 -- the specified display can not be found
    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4196)
    at android.app.ActivityThread.access$2000(ActivityThread.java:233)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1946)
    at android.os.Handler.dispatchMessage(Handler.java:107)
    at android.os.Looper.loop(Looper.java:224)
    at android.app.ActivityThread.main(ActivityThread.java:7561)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:995)

Added permission in Manifest file like this

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW"/>
Durai DD
  • 189
  • 1
  • 10

1 Answers1

0

Just remove :

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // 8.0 new features
    dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY - 1);
} else {
    dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_TOAST);
}

And try :

dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)

UPDATE

In Android 6.0 Marshmallow, the user must explicitly allow your app to "draw over other apps". So add

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

Now in marshmallow use this method to handle runtime permission:

@TargetApi(Build.VERSION_CODES.M)
private void handleOverlaySettings() {
    final Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                                     Uri.parse("package:" + getPackageName()));
    try {
        startActivityForResult(intent, 11);
    } catch (ActivityNotFoundException e) {
        Log.e(TAG, e.getMessage());
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case 11:
            final boolean overlayEnabled = Settings.canDrawOverlays(this);
            // handle the remaining logic
            break;
    }
}

Now show the dialog in service as below:

    final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this, R.style.AppTheme_MaterialDialogTheme);

dialogBuilder.setTitle(R.string.dialog_title);
dialogBuilder.setMessage(R.string.dialog_message);
dialogBuilder.setNegativeButton(R.string.btn_back,
        new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        }
);

final AlertDialog dialog = dialogBuilder.create();
final Window dialogWindow = dialog.getWindow();
final WindowManager.LayoutParams dialogWindowAttributes = dialogWindow.getAttributes();

// Set fixed width (350dp) and WRAP_CONTENT height
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.copyFrom(dialogWindowAttributes);
lp.width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 350, getResources().getDisplayMetrics());
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
dialogWindow.setAttributes(lp);

// Set to TYPE_SYSTEM_ALERT so that the Service can display it
dialogWindow.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
dialogWindowAttributes.windowAnimations = R.style.DialogAnimation;
dialog.show();

All set now this solution should work. Good luck

Ali Nawaz
  • 2,016
  • 20
  • 30