阅读 5902

完美实现账户踢出时的全局弹窗

如果我们的app支持单点登录、账户踢出功能,那么在接到后端push的“需要踢出当前用户”的消息后就需要弹出一个dialog。这种dialog出现的时机并不确定,一种方式就是做一个系统层面的dialog,就像ANR时出现的系统dialog,让其永远保持在屏幕的上方。

Dialog dialog = new Dialog(this);
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
dialog.show();
复制代码

但这种写法有两个问题,一个是TYPE_SYSTEM_ALERT已经被废弃,其二是需要增加权限。

/** @deprecated */
@Deprecated
public static final int TYPE_SYSTEM_ALERT = 2003;
复制代码
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
复制代码

我们可以换个思路来考虑这个需求,要知道dialog的构建和activity是强相关的,解决方案是永远保存当前的activity对象,当锁屏和app退出到后台时,清空保存的当前activity。

首先,在application中持有当前的activity对象:

public class App extends Application {

    private AppCompatActivity curActivity;

    @Override
    public void onCreate() {
        super.onCreate();
        
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityResumed(Activity activity) {
                curActivity = (AppCompatActivity) activity;
            }

            @Override
            public void onActivityPaused(Activity activity) {
                curActivity = null;
            }
        });
    }
}
复制代码

然后,定义弹出dialog的方法:

public class App extends Application {

    private AppCompatActivity curActivity;

    public void showDialog(String title, String message) {
        if (curActivity == null) {
            return; // 不要忘了判空操作
        }
        
        EasyDialog.builder(curActivity)
                .setTitle(title)
                .setMessage(message)
                .setPositiveButton("ok", null)
                .build()
                .show(curActivity.getSupportFragmentManager());
    }
}
复制代码

最后,在需要的时候调用application中的showDialog()来完成弹窗:

((App) getApplication()).showDialog("全局弹窗", "可在任意时机弹出一个dialog")
复制代码

这里的代码在onResume()onPause()做了activity对象的获取,可以保证获取的是当前最上层的activity,当app退出到后台后这个curActivity会变为null,不允许弹出对话框了。最后记得要在弹出时做个activity的判空或isDestroyed()之类的判断,防止使用了即将销毁的activity。

题外话:

当你的应用支持了分屏功能,也就是多窗口后,那么则需要在onStop()中清空activity,在onStart()中得到activity,更多详细内容请参考《多窗口支持  |  Android Developers》

@Override
public void onActivityStarted(Activity activity) {
    curActivity = (AppCompatActivity) activity;
}

@Override
public void onActivityStopped(Activity activity) {
    curActivity = null;
}
复制代码

联系作者