Search code examples
javaandroidkotlinserviceandroid-alertdialog

How to show Alert Dialog box in Service android


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"/>

Solution

  • 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