如何从在android中扩展应用程序的类中显示对话框?

Posted

技术标签:

【中文标题】如何从在android中扩展应用程序的类中显示对话框?【英文标题】:How to show Dialog Box from the class which extends Application in android? 【发布时间】:2012-01-24 13:35:42 【问题描述】:

我想在特定条件后显示一个对话框,但对于现在的演示,我想从扩展 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 WindowToken4067a268 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()? 我有很多活动,在特定条件后我想显示该对话框,因此在每个活动中编写相同的代码是没有意义的.. 这样你就可以让你的“对话”变量成为你的“ControlApplication”类的一个属性,然后为它写一个getter。然后你可以在“ControlApplication”中创建一些影响“对话框”的条件,然后当每个活动时,调用类似:((Application)getApplicationContext()).getDialog().show()。希望对您有所帮助:) @LeoLink 那行不通。您不能使用应用程序上下文创建对话框。 啊,我忘记了,但是为什么要在调用活动应用程序的 onCreate 时显示一个对话框?。如果不想多次写sn-p代码,可以做一个函数,传参数给它。 【参考方案1】:

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

** 请记住,您需要考虑其行为的后果。

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

为 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;

编辑:

您不能通过不是 Activity 或 Service 的上下文来**显示应用程序窗口/对话框。尝试传递有效的活动参考

** 你可以使用应用程序上下文来创建对话框,方法是在调用 Dialog.show() 之前添加

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

- but this requires permission:  

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

参考:

Dialogs AlertDialog WindowType

【讨论】:

这需要特殊权限。这对我来说不是解决方案。 您刚刚在代码中添加了注释,当您想在活动之外显示对话框时仍然需要该权限。 @rekire - 见编辑 - 当你告诉你想在哪里显示对话框时,给你解决方案会很简单 TYPE_SYSTEM_ALERT 已弃用!!【参考方案2】:

您不能使用应用程序 [或服务] 上下文。如果您真的想从应用程序中显示拨号日志,则必须将 Activity 上下文传递给它。您还可以存储 Activity 上下文,但我 建议这样做。活动上下文在完成时无效,因此您将破坏您的程序。正如@LeoLink 所说,只需直接从您的活动中调用它。

例如编辑

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

【讨论】:

我有很多活动,在特定条件后我想显示该对话框,如何获取活动上下文并将其传递给 ControlApplication 类? 如果你一心想要这样做,我再次推荐这个,然后在你的应用程序中放置一个 Activity 变量。然后调用Context.getApplicationContext() 并将其转换为您的特定应用程序并调用一个方法以通过该方法传递您的活动上下文。就像一个普通的二传手一样。但是,如果您这样做,请不要依赖它,也不要忘记每次活动更改时都必须更改它,否则它将不起作用。【参考方案3】:

Application 类用于保存您的活动可以使用的数据,而不是与 UI 交互。显示您希望在其中显示的活动的对话框。

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

【讨论】:

但是同一个班级我可以显示 Toast ,那为什么我不能显示 Dialog ? 我有很多活动,在特定条件之后我想显示该对话框,因此在每个活动中编写相同的代码是没有意义的。 Toast 更多的是设备功能而不是应用程序功能。 @shankey 您不必编写相同的代码。参考我的更新 如果您真的想在您的应用程序中包含该代码(我仍然认为这是不好的做法),那么您应该将活动传递给方法。然后将活动用作对话的上下文,它将起作用。但是我会拥有一个包含特定代码(包括您的对话代码)的所有活动的超类

以上是关于如何从在android中扩展应用程序的类中显示对话框?的主要内容,如果未能解决你的问题,请参考以下文章

静态方法与扩展 android.app.Application 的类?

在android应用程序中扩展底部工作表对话框

扩展片段的类中的选项卡

如何在已经扩展 Thread 的类中扩展 JFrame

android中AsyncTask中的ProgressDialog

如何从扩展 JobService 的类中调用将视图作为参数的 MainActivity 方法?