从android中的非活动类显示对话框警报

时间:2013-06-12 07:06:31

标签: android android-alertdialog

我希望通过AlertDialogManager课程向non-activity课程DeviceAdminReceiverSample的方法onDisabled展示提醒对话,但每当我通过alertDialog致电06-12 12:01:19.923: E/AndroidRuntime(468): FATAL EXCEPTION: main 06-12 12:01:19.923: E/AndroidRuntime(468): java.lang.RuntimeException: Unable to start receiver com.android.remotewipedata.DeviceAdminReceiverSample: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application 时它使用以下文本

生成错误的方法

错误

context

我知道问题出在this这个问题上,但我不知道该放在那里以便工作,我尝试了getApplicationContext()public class AlertDialogManager { public void showAlertDialog(Context context, String title, String message, Boolean status) { final AlertDialog alertDialog = new AlertDialog.Builder(context).create(); alertDialog.setTitle(title); alertDialog.setMessage(message); if (status != null) alertDialog.setButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { alertDialog.dismiss(); } }); alertDialog.show(); } 但都是徒劳的。我的两个类的代码都在

之下

AlertDialogManager

public class DeviceAdminReceiverSample extends DeviceAdminReceiver {
static final String TAG = "DeviceAdminReceiver";
AlertDialogManager alert = new AlertDialogManager();

/** Called when this application is no longer the device administrator. */
@Override
public void onDisabled(Context context, Intent intent) {
    super.onDisabled(context, intent);
    Toast.makeText(context, R.string.device_admin_disabled,
            Toast.LENGTH_LONG).show();
    // intent.putExtra("dialogMessage", "Device admin has been disabled");
    // intent.setClass(context, DialogActivity.class);
    // intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    // context.startActivity(intent);
    alert.showAlertDialog(context, "Alert",
            "Device admin has been disabled", true);
}

}

DeviceAdminReceiverSample

{{1}}

8 个答案:

答案 0 :(得分:37)

只需在alertDialog.show();

之前添加此内容即可
alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

or try following is above doesn't works:
alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_PANEL); 

并使用此权限:

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

答案 1 :(得分:13)

问题是“You can show AlertDialogs from Activity only”。这不是背景问题。

虽然从接收器 显示对话框不是一个好主意(更好的是使用通知),但是如果你想这样做,你可以创建一个{{ 3}}

答案 2 :(得分:6)

如果您总是希望从应用程序中的任何位置获取当前活动,则可以在Application实例上注册ActivityLifecycleCallback。

这是一个未经测试的实现,可能会让您更接近。

public class TestApp extends Application {

    private WeakReference<Activity> mActivity = null;

    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                mActivity = new WeakReference<Activity>(activity);
            }

            @Override
            public void onActivityDestroyed(Activity activity) {
                mActivity.clear();
            }

            /** Unused implementation **/
            @Override
            public void onActivityStarted(Activity activity) {}

            @Override
            public void onActivityResumed(Activity activity) {}
            @Override
            public void onActivityPaused(Activity activity) {}

            @Override
            public void onActivityStopped(Activity activity) {}

            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
        });
    }

    public Activity getCurrentActivity() {
        return mActivity.get();
    }

}

然后在整个应用程序中使用它,您可以像这样打电话......

Activity activity = ((TestApp)getApplicationContext()).getCurrentActivity(); 

优点是你可以随时跟踪你当前的活动,但是对于仅从活动中处理对话来说它有点过分。

答案 3 :(得分:1)

在活动类

中调用此方法
public static void showAlert(Activity activity, String message) {

        TextView title = new TextView(activity);
        title.setText("Title");
        title.setPadding(10, 10, 10, 10);
        title.setGravity(Gravity.CENTER);
        title.setTextColor(Color.WHITE);
        title.setTextSize(20);

        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
        // builder.setTitle("Title");
        builder.setCustomTitle(title);
        // builder.setIcon(R.drawable.alert_36);

        builder.setMessage(message);

        builder.setCancelable(false);
        builder.setNegativeButton("OK", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                dialog.cancel();

            }

        });

        AlertDialog alert = builder.create();
        alert.show();
    }

答案 4 :(得分:0)

正如AJAY建议的那样,最好的方法是使用&#39;活动&#39;在参数中而不是使用&#39;上下文&#39;。

在您的个人班级中,只需在其构造函数中请求活动作为必填参数=&gt; public void constructorOfTheClass(Activity activity){...}。

当您在Activity中调用构造函数时,只需指出此参数,您就可以直接在类中使用它。

然后你可以使用这个&#39;活动&#39;您的类中的AlertDialog方法中的信息,因为SUNIL注意到在所需的活动中正确提示。

希望它有所帮助......并确保它能够正常工作! ; O)

答案 5 :(得分:0)

这是我制作和使用的内容:

myDialog.java:

import android.app.Activity;
import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

public class myDialog {
    private Activity mActivity;

    myDialog(Activity a) {
        this.mActivity = a;
    }

    @SuppressWarnings("InflateParams")
    public void build(String title, String msg) {
        LayoutInflater inflater = LayoutInflater.from(mActivity);
        View subView = inflater.inflate(R.layout.dialog_box_text, null);
        final TextView message = subView.findViewById(R.id.message);
        message.setText(msg);
        AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
        builder.setTitle(title);
        builder.setView(subView);
        builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        AlertDialog alert = builder.create();
        alert.show();
    }
}

dialog_box_text.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:weightSum="1"
    android:orientation="horizontal">
    <TextView
        android:id="@+id/message"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="  "
        android:maxLines="1"
        android:textColor="@color/colorBlack" />
</LinearLayout>

示例代码:

public class MainActivity extends AppCompatActivity {
    private myDialog md;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        md = new myDialog(this);

...

        md.build("Title", "Message");

答案 6 :(得分:-1)

这是一个正确执行此任务的快速方法,它完成了我的工作。基本上,你要做的只是创建一个新的线程。


  1. 声明一个公共和静态变量,其类型与原始活动类匹配。

    public static Activity1 activity;

  2. Activity1是变量所在的类。

    1. 调用方法onCreate();后,将变量设置为等于活动的上下文,也称为 this
    2. 示例:

      @Override 
          protected void onCreate( Bundle savedInstanceState ) {
          super.onCreate( savedInstanceState );
          activity = this;
      }
      

      <小时/> 3.由于我们现在拥有活动的上下文,我们可以使用它来创建一个带有警告对话框的函数,方法是使用调用警告对话框的函数内部的runOnUiThread();方法。我们将new Runnable()用于runOnUiThread();所需的可运行操作,并且实际打开警报对话框,我们将覆盖可运行项目的运行功能,并将警报对话框的代码放在那里。

      示例功能:

      public static void exampleDialog(){
      Activity1.activity.runOnUiThread(new Runnable){
      @Override
          public void run(){
          //alert dialog code goes here.  For the context, use the activity variable from Activity1.
              }
          }
      }
      

      希望这会有所帮助:)

答案 7 :(得分:-2)

您可以在MainActivity中使用初始值(this)定义一个公共Context变量;如此处所示:

public class MainActivity< alertdail > extends AppCompatActivity {

    ////////////////////////////////////////////////////////////
    //Public var refers to Main Activity:
    Context mainActivity = this;
    ////////////////////////////////////////////////////////////

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate ( savedInstanceState );
        setContentView ( R.layout.activity_main );
        AlertDialogManager alert  =new AlertDialogManager ();
alert.showAlertDialog ( this,"Title","Message",true );


     }


    public class AlertDialogManager {

        public void showAlertDialog(Context context, String title, String message,
                                    Boolean status) {
            final AlertDialog alertDialog = new AlertDialog.Builder ( mainActivity ).create ( );
            alertDialog.setTitle ( title );
            alertDialog.setMessage ( message );

            if (status != null)
                alertDialog.setButton ( "OK", new DialogInterface.OnClickListener ( ) {
                    public void onClick(DialogInterface dialog, int which) {
                        alertDialog.dismiss ( );
                    }
                } );
            alertDialog.show ( );
        }

        public void showAlertDialog(Context c) {
        }
    }


    public class DeviceAdminReceiverSample extends DeviceAdminReceiver {
        static final String TAG = "DeviceAdminReceiver";
        AlertDialogManager alert = new AlertDialogManager ( );

        /**
         * Called when this application is no longer the device administrator.
         */
        @Override
        public void onDisabled(Context context, Intent intent) {
            super.onDisabled ( context, intent );
            Toast.makeText ( context, R.string.device_admin_disabled,
                    Toast.LENGTH_LONG ).show ( );
            // intent.putExtra("dialogMessage", "Device admin has been disabled");
            // intent.setClass(context, DialogActivity.class);
            // intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            // context.startActivity(intent);
            alert.showAlertDialog ( context, "Alert",
                    "Device admin has been disabled", true );
        }
    }
}