将AlertDialog显示为Service中的系统覆盖窗口

时间:2010-09-28 15:04:15

标签: android

我遇到了从Service显示AlertDialog的问题。我可以使用Toast或使用WindowManager(TYPE_SYSTEM_ALERT或TYPE_SYSTEM_OVERLAY)显示自定义布局窗口。但是,我不想使用自定义布局,我更喜欢直接使用不错的AlertDialog GUI。

情景:

  • 正在运行服务。没有活动活动。
  • 在某些外部事件上,服务发送通知
  • 当用户按下通知时,将通过PendingIntent通知服务并显示AlertDialog(使用AlertDialog.Builder(this)创建)

错误:

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

搜索答案会让我觉得我正在尝试一些目前无法实现的功能(Android 2.2)。或者也许是。

2 个答案:

答案 0 :(得分:25)

找到了符合描述情景的解决方案。

  • 已创建新活动并从服务启动。但是,它是半透明背景的活动。此类活动在super.setContentView()中没有行onCreate()。更重要的是,确保透明度

    @android:风格/ Theme.Translucent

在AndroidManifest.xml GUI中为此活动的主题标记下输入

。因此,添加到清单xml的新行是

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

  • onCreate()实际显示AlertDialog

  • 按下AlertDialog按钮会导致Dialog和Activity关闭并发送Intent(或使用其他方法)将结果传递给服务。

  • 确保为Dialog定义了setOnDismissListener()(实现应该在activity上调用finish())。如果你不这样做,请按返回键取消对话框,但让你进入当前活动,这是透明的,并向用户看,就像是非常错误。

答案 1 :(得分:6)

感谢您的解决方案。 我遇到了同样的问题,并在你的帮助下解决了问题。

我把这个答案只是为了分享我将结果传递回服务的方式。

我没有创建任何额外的自定义意图类,只通过Intent.putExtra()方法解决了结果传递问题。

在服务中,使用此代码启动DialogActivity,在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);

DialogActivity中,完成如下:

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();
}

最后,在服务中,覆盖onStartCommand()方法并从意图中获取结果。

@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;
}

我不确定这种方式是否是一个很好的解决方案,至少它对我有用。希望这对像我这样的人有用。

完整的来源可以在这里找到: