Balaji Khadake
Balaji Khadake

Reputation: 3479

How to show status notification or popup dialog from background service?

I have created bootup Service which listen for incoming messages in my application. Service is continuosly running in backgroung thought application is closed that is user goes offline. While user is offline and there is new message I have to show notifiacation on status bar or popup dialog(Here in this situaction service is not bound to any of Activity). I am facing following problems:

  1. While creating notification I am not getting Context and Activity.
  2. While I am displaying dialog from service class I am getting exception as "Can't create handler inside thread that has not called Looper.prepare()".

I am new one for android services part and don't know hoe to solve this. Can anybody guide me how to do this? Is there any link which will guide me for this? I got stucked due to this problem. Help highly appreciated. Thanks.

Upvotes: 3

Views: 8860

Answers (4)

chakrapani
chakrapani

Reputation: 1371

We can show dialog from service only if it is a system alert dialog. So, set TYPE_SYSTEM_ALERT window layout parameter to Dialog as follows,

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

But, it needs SYSTEM_ALERT_WINDOW permission. So, don't forget to add this permissin in Manifest file.

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

Edit: Better option to show dialog is to start activity as one of the below ways.

  1. Start Activity with Dialog Theme (android:theme="@android:style/Theme.Dialog") -(or)
  2. Start Translucent Activity and show Dialog in it.

Note: You should add Intent.FLAG_ACTIVITY_NEW_TASK to intent

Happy coding ... :)

Upvotes: 1

Aashish Vivekanand
Aashish Vivekanand

Reputation: 449

To add an Alert Dialog from Service, this worked fine

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

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

            // Set to TYPE_SYSTEM_ALERT so that the Service can display it
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                dialogWindow.setType(WindowManager.LayoutParams.TYPE_TOAST);
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                dialogWindow.setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
            }
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
            {
                dialogWindow.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
            }
            dialog.show();

But using TYPE_SYSTEM_ALERT might trigger Google takedown policy of apps using dangerous permissions. Make sure you have a valid justification in case google requires it.

Upvotes: 1

Sherif elKhatib
Sherif elKhatib

Reputation: 45942

You can send a notification and specify what Activity should be run when user initiates it:

 private void sendNotification(Bundle bundle){
    String ns = Context.NOTIFICATION_SERVICE;
    NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
    int icon = R.drawable.icon;
    CharSequence tickerText = "bla bla";
    long when = System.currentTimeMillis();
    Notification notification = new Notification(icon, tickerText, when);
    Context context = getApplicationContext();
    CharSequence contentTitle = "My notification";
    CharSequence contentText = "Hello World!";
    Intent notificationIntent = new Intent(this, ACTIVITY_YOU_WANT_TO_START.class);
    if(bundle!=null)
        notificationIntent.putExtras(bundle); //you may put bundle or not
    PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
    notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
    int any_ID_you_want = 1; 
    //if you send another notification with same ID, this will be replaced by the other one
    mNotificationManager.notify(HELLO_ID, notification);
}

//To play a sound add this:
notification.sound = Uri.parse("file:///sdcard/notification/ringer.mp3"); //for example

You can start another Activity:

private boolean startActivity(Bundle bundle){
    Intent myIntent = new Intent(mContext, ACTIVITY_YOU_WANT_TO_START.class);
    if(bundle!=null)
         myIntent.putExtras(bundle);//optional
    myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    getApplication().startActivity(myIntent);
    return true;
}

Upvotes: 4

Dhrubo
Dhrubo

Reputation: 725

In addition to Sheriff's answer , you have to use following theme

android:theme="@android:style/Theme.Dialog"

for that Activity in AndroidManifest.xml . Then you will get a Dialog. :)

Upvotes: 2

Related Questions