如何在Android中扩展Application类的类中显示对话框框?

18

我希望在特定条件下显示一个对话框,但现在只为演示目的,我想从扩展Application类的类中显示一个对话框。 以下是我的代码

public class ControlApplication extends Application
{
    @Override
    {
    super.onCreate();
    final Dialog dialog = new Dialog ( getApplicationContext() ); 
    dialog.setTitle("zakasssssssssssssssssss");
    dialog.setCancelable(false);
    dialog.show();
}

}

但在dialog.show()处,我收到了以下错误:

Attempted to add window with non-application token WindowToken{4067a268 token=null}.  Aborting.
D/AndroidRuntime( 1923): Shutting down VM
W/dalvikvm( 1923): threadid=1: thread exiting with uncaught exception (group=0x40015560)
E/AndroidRuntime( 1923): FATAL EXCEPTION: main
E/AndroidRuntime( 1923): java.lang.RuntimeException: Unable to create application 
com.test.shrenik.ControlApplication: android.view.WindowManager$BadTokenException: 
Unable to add window -- token null is not for an application
E/AndroidRuntime( 1923):    at android.app.ActivityThread.handleBindApplication(ActivityThread.java:3275)
E/AndroidRuntime( 1923):    at android.app.ActivityThread.access$2200(ActivityThread.java:117)
E/AndroidRuntime( 1923):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:969)
E/AndroidRuntime( 1923):    at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime( 1923):    at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime( 1923):    at android.app.ActivityThread.main(ActivityThread.java:3683)
E/AndroidRuntime( 1923):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 1923):    at java.lang.reflect.Method.invoke(Method.java:507)
E/AndroidRuntime( 1923):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
E/AndroidRuntime( 1923):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
E/AndroidRuntime( 1923):    at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime( 1923): Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
E/AndroidRuntime( 1923):    at android.view.ViewRoot.setView(ViewRoot.java:531)
E/AndroidRuntime( 1923):    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
E/AndroidRuntime( 1923):    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
E/AndroidRuntime( 1923):    at android.app.Dialog.show(Dialog.java:241)
E/AndroidRuntime( 1923):    at com.andromeda.ui.pandora.ControlApplication.onCreate(ControlApplication.java:38)
E/AndroidRuntime( 1923):    at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:969)
E/AndroidRuntime( 1923):    at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:969)
E/AndroidRuntime( 1923):    at android.app.ActivityThread.handleBindApplication(ActivityThread.java:3272)
E/AndroidRuntime( 1923):    ... 10 more

有人可以提供任何解决方案吗?


为什么不在你希望显示对话框的活动中调用dialog.show()呢? - Leo
我有许多活动,特定条件后我想显示对话框,因此在每个活动中编写相同的代码是没有意义的。 - shankey
你可以将你的"dialog"变量设为"ControlApplication"类的属性,然后编写一个getter方法。然后你可以在"ControlApplication"中设置一些条件来影响"dialog",然后在每个活动中调用类似这样的语句:((Application)getApplicationContext()).getDialog().show()。希望对你有所帮助 :) - Leo
@LeoLink 这样做不行。你不能使用应用程序上下文来创建对话框。 - ahodder
啊,我忘了这件事了,但是你为什么想要在活动应用的onCreate被调用时显示一个对话框呢?如果你不想多次编写代码片段,可以编写一个函数并传递参数给它。 - Leo
显示剩余2条评论
3个回答

9

您的程序可以按照您的意愿运行!**

** Just remember that you need to think about the consequences of its actions.

public class MyApplication extends Application {
        /** 
        * show example alertdialog on context -method could be moved to other class 
        * (eg. MyClass) or marked as static & used by MyClas.showAlertDialog(Context)
        * context is obtained via getApplicationContext() 
        */
        public void showAlertDialog(Context context) {
            /** define onClickListener for dialog */
            DialogInterface.OnClickListener listener 
                  = new   DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                // do some stuff eg: context.onCreate(super)
                }
            };

            /** create builder for dialog */
            AlertDialog.Builder builder = new AlertDialog.Builder(context)
                .setCancelable(false)
                .setMessage("Messag...")
                .setTitle("Title")
                .setPositiveButton("OK", listener);
            /** create dialog & set builder on it */
            Dialog dialog = builder.create();
            /** this required special permission but u can use aplication context */ 
            dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
            /** show dialog */
            dialog.show();
        }

        @Override
        public void onCreate() {
            showAlertDialog(getApplicationContext());
        }
}

imports for abowe:

import android.app.AlertDialog;
import android.app.Application;
import android.app.Dialog; 
import android.content.Context;
import android.content.DialogInterface; 
import android.view.WindowManager;

edity:

You cannot **display an application window/dialog through a Context that is not an Activity or Service. Try passing a valid activity reference

** u can use application context to create dialog by adding before call to Dialog.show();

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

- but this requires permission:  

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

Ref:


这需要特殊权限。对我来说这不是解决方案。 - rekire
你刚刚在代码中添加了一条注释,但当你想在活动之外显示对话框时仍需要该权限。 - rekire
@rekire - 看编辑 - 当你告诉我想在哪里显示对话框时,给你一个解决方案是很简单的。 - ceph3us
TYPE_SYSTEM_ALERT已经过时!! - Mohammed Alloboany

2

您不能使用应用程序[或服务]上下文。如果您真的想要从应用程序显示对话框,您将不得不向其传递Activity上下文。您也可以存储Activity上下文,但我不建议这样做。因为Activity上下文在完成后会被撤销,这会导致程序崩溃。正如@LeoLink所说,只需直接从您的Activity中调用即可。

例如编辑

class MyDialog {
    public Dialog show(Context context) {
        Dialog d = new Dialog(context);
        d.setTitle("I'm a dialog");
        d.setMessage("I'm a message");
        return d.show();
    }
}

我有许多活动,并且在特定条件下,我想显示对话框,如何获取Activity上下文并将其传递给ControlApplication类? - shankey
如果你一心想要这么做,再次强调我<b>不建议</b>这样做,那么在你的应用程序中放置一个Activity变量。然后调用Context.getApplicationContext()并将其转换为您的特定应用程序,并调用通过该方法传递活动上下文的方法,就像普通的setter一样。然而,如果您这样做,请不要依赖它,并且请不要忘记每次更改活动时都必须更改它,否则它将无法正常工作。 - ahodder

1

Application类用于保存可以被你的活动使用的数据,而不是与UI交互。从你想要显示它的活动中显示对话框。

编辑:如果你想从多个活动调用代码,你可以为这些活动创建一个超类,其中包含具有对话框的代码。然后在你想要显示对话框的所有活动中扩展此超类,并从那里调用它。


2
但是从同一个类中我可以显示Toast,为什么我不能显示Dialog? - shankey
我有许多活动,特定条件后我想显示对话框,因此在每个活动中编写相同的代码是没有意义的。 - shankey
Toast更像是设备功能而不是应用程序功能。 - ahodder
@shankey 你不必写相同的代码。请参考我的更新。 - ahodder
如果你真的想在你的应用程序中使用那段代码(我仍然认为这是不好的实践),那么你应该将活动传递给方法。然后使用活动作为对话框的上下文,它会起作用。但是我更愿意为所有你的活动创建一个超类,其中包括特定的代码(包括你的对话框代码)。 - Guillaume

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接