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:
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.
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.
From a Service, you can easily show a Material Design styled Dialog manipulating its Window type, attributes and LayoutParams.
setTitle(CharSequence title)AlertDialog alertDialog = alertDialogBuilder. create(); alertDialog. show(); This will create the alert dialog and will show it on the screen.
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.
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:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With