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

Zel*_*mir 14 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
Run Code Online (Sandbox Code Playgroud)

寻找答案让我觉得我正在尝试一些目前无法实现的东西(Android 2.2).或者也许是.

Zel*_*mir 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()).如果你不这样做,请按返回键取消对话框,但让你进入当前活动,这是透明的,并向用户看,就像是非常错误.


Pro*_*mus 6

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

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

我没有创建任何额外的自定义intent类,只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);
Run Code Online (Sandbox Code Playgroud)

并在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();
}
Run Code Online (Sandbox Code Playgroud)

最后,在服务中,重写onStartCommand()方法并从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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 使用startService()返回结果是比使用广播更好的解决方案.我经常使用这种方法. (2认同)