Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Display AlertDialog as system overlay window from Service

Tags:

android

I have issue with displaying AlertDialog from Service. I am able to display custom layout window using Toast or using WindowManager(TYPE_SYSTEM_ALERT or TYPE_SYSTEM_OVERLAY). But, I do not want to use custom layout, I prefer to use nice AlertDialog GUI directly.

Scenario:

  • Running Service. No active Activity present.
  • On some external event, Service sends Notification
  • When user press Notification, Service is informed via PendingIntent and AlertDialog should be displayed (created with AlertDialog.Builder(this))

Error:

ERROR/AndroidRuntime(1063): Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application

Searching for the answer lead me to impression that I am trying something that is currently not possible (Android 2.2). Or maybe it is.

like image 595
Zelimir Avatar asked Sep 28 '10 15:09

Zelimir


People also ask

Can we show dialog from service?

You cannot show a dialog. But you can go the alernative way by inflating your customized view so that you can show a dialog on the screen whenver certain conditions are met.

Can we show dialog from service android?

From a Service, you can easily show a Material Design styled Dialog manipulating its Window type, attributes and LayoutParams.

How do I use AlertDialog?

setTitle(CharSequence title)AlertDialog alertDialog = alertDialogBuilder. create(); alertDialog. show(); This will create the alert dialog and will show it on the screen.


2 Answers

Solution that matches described scenario has been found.

  • New Activity has been created and started from Service. However, it is activity with translucent background. Such activity does not have line super.setContentView() in onCreate(). More important, to ensure transparency

    @android:style/Theme.Translucent

is entered under Theme tag for this activity in AndroidManifest.xml GUI. So, new line added to the manifest xml is

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

  • In onCreate() actual display of AlertDialog occurs

  • Press on AlertDialog buttons causes Dialog and Activity closing and sending of the Intent (or use of some other means) to deliver result to the Service.

  • Be sure that you defined setOnDismissListener() for the Dialog (implementation should call finish() on activity). If you do not do that press on the Back key cancels dialog but leaves you in the current activity which is transparent and looks to user like something is really wrong.

like image 177
Zelimir Avatar answered Oct 12 '22 20:10

Zelimir


Thank you for your solution. I faced the same problem and worked out with your help.

I put this answer just to share my way for passing result back to the service.

I didn't create any additional custom intent class and solved the result passing problem by only Intent.putExtra() methods with some tricks.

In the service, use this code to start the DialogActivity which display the alert dialog in onCreate().

Intent intent = new Intent(this.getApplicationContext(), DialogActivity.class); 
intent.putExtra(DialogActivity.CLASS_KEY, this.getClass().getCanonicalName());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

And in the DialogActivity, finish it like this:

private void returnOk(boolean ok) {
    Intent srcIntent = this.getIntent();
    Intent tgtIntent = new Intent();
    String className = srcIntent.getExtras().getString(CLASS_KEY);
    Log.d("DialogActivity", "Service Class Name: " + className);
    ComponentName cn = new ComponentName(this.getApplicationContext(), className);
    tgtIntent.setComponent(cn);
    tgtIntent.putExtra(RESULT_KEY, ok ? RESULT_OK : RESULT_CANCEL);
    this.startService(tgtIntent);
    this.finish();
}

At last, in the service, override the onStartCommand() method and get the result from the intent.

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    int ret = super.onStartCommand(intent, flags, startId);
    Bundle extras = intent.getExtras();
    if (extras != null) {
        int result = extras.getInt(DialogActivity.RESULT_KEY, -1);
        if (result >= 0) {
            if (result == DialogActivity.RESULT_OK) {
                // Your logic here...
            }
        } else {
            // Your other start logic here...
        }
    }
    return ret;
}

I am not sure whether this way is a good solution, at least it works for me. Hope this will be helpful for someone else like me.

The complete source can be found here:

  • https://github.com/programus/floating-nice/blob/master/eclipse-project/FloatingNice/src/org/programus/android/floatings/activities/DialogActivity.java
  • https://github.com/programus/floating-nice/blob/master/eclipse-project/FloatingNice/src/org/programus/android/floatings/services/SleepService.java
like image 41
Programus Avatar answered Oct 12 '22 20:10

Programus