显示来自 Retrofit 拦截器的对话框

Showing Dialog from Retrofit's Interceptor

当几个参数不满足时,我试图显示来自 Retrofit 拦截器的对话框。 但是我在尝试显示对话框时出现 android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running? 异常。

这是我的代码。

final AlertDialog.Builder alertDialog = new AlertDialog.Builder(ShieldSquare.applicationContext)
            .setIcon(android.R.drawable.ic_dialog_alert)
            .setTitle("Are you sure to Exit")
            .setMessage("Exiting will call finish() method")
            .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    dialogInterface.dismiss();
                }
            })
            //set negative button
            .setNegativeButton("No", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    //set what should happen when negative button is clicked
                    Toast.makeText(ShieldSquare.applicationContext,
                            "Nothing Happened", Toast.LENGTH_LONG).show();
                }
            });

    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            alertDialog.create().show();
        }
    };

    new Handler(Looper.getMainLooper()).post(runnable);

上面的代码 运行 在 Retrofit 链开始之前的拦截器上。

ssResponse = chain.proceed(originalRequest);

一般情况下,我们只显示来自活动的对话框,因此上下文 ShieldSquare.applicationContext 无法显示 AlertDialog

有两种方法可以满足您的需求:

第一个,使用特殊权限android.permission.SYSTEM_ALERT_WINDOW。 在 alertDialog.show(); 之前添加:

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

并将下面的权限添加到 AndroidManifest.xml

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

然后您可以使用 ShieldSquare.applicationContext 作为对话生成器。

第二个,你可以将你的ShieldSquare.applicationContext更新为最新的activity,那么ShieldSquare.applicationContext将永远是一个activity的上下文:

public abstract class BaseActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ShieldSquare.applicationContext = this;
    }
}

而且我找到了一些使用BroadcastReceiver显示对话框的方法,你也可以看看,见SO answer and this blog post.