非Activity的context 或者 全局监听中
常规new dialog的方式调不起弹窗
exitDialog = new Dialog(context, R.style.loading_dialog);
exitDialog.setCancelable(false);
View view = LayoutInflater.from(context).inflate(R.layout.dialog, null);
TextView tv = (TextView) view.findViewById(R.id.popubwindow_ok_content_tv);
if (!StringUtil.isEmpty(tips)) {
tv.setText(tips);
} else {
tv.setText(context.getResources().getString(R.string.str_exit_content));
}
exitDialog.setContentView(view);
view.findViewById(R.id.popubwindow_ok_ok_tv).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
XwgUtils.exist2login(context);
dismissExitDialog();
}
});
exitDialog.setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
dismissExitDialog();
}
});
增加以下部分
exitDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
部分手机(小米)仍弹不出来,需要给予显示悬浮窗的权限
解决思路:使用 Dialog样式的Activity
通过跳转+SingleTask 实现被踢下线提示退出至登录界面
public class ExistDialogActivity extends Activity {
public static final String KEY_EXIST_APP = "exist";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_exist_activity);
((TextView) findViewById(R.id.title)).setText(R.string.str_exit_title);
((TextView) findViewById(R.id.content)).setText(R.string.str_exit_content);
((TextView) findViewById(R.id.confirm)).setText("确 定");
findViewById(R.id.confirm).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
exist();
}
});
}
private void exist() {
Intent intent = new Intent(ExistDialogActivity.this, MainActivity.class);
intent.putExtra(KEY_EXIST_APP, true);
startActivity(intent);
finish();
}
@Override
public void onBackPressed() {
}
}
AndroidManifest中
<activity
android:name=".ui.other.ExistDialogActivity"
android:configChanges="orientation|keyboardHidden"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:theme="@style/existDialogStyle"
android:windowSoftInputMode="stateHidden" />
styles文件中
<style name="existDialogStyle">
<item name="android:windowBackground">@android:color/transparent</item>
<!--设置Dialog的windowFrame框为无-->
<item name="android:windowFrame">@null</item>
<!--设置无标题-->
<item name="android:windowNoTitle">true</item>
<!--是否浮现在activity之上-->
<item name="android:windowIsFloating">true</item>
<!--是否半透明-->
<item name="android:windowIsTranslucent">true</item>
<!--设置窗口内容不覆盖-->
<item name="android:windowContentOverlay">@null</item>
<!--设置动画,在这里使用让它继承系统的Animation.Dialog-->
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
<!--背景是否模糊显示-->
<item name="android:backgroundDimEnabled">true</item>
<!--点击对话框外部不消失-->
<item name="android:windowCloseOnTouchOutside">false</item>
<item name="android:textSize">14sp</item>
<item name="android:textStyle">normal</item>
<item name="android:textColor">@android:color/black</item>
</style>
最后三行item增加的原因。是我遇到了奇怪的现象
我的小米note3死活不显示layout中textview的文字内容,就是白白一片。增加后上述三行配置才显示出内容来
xml布局文件的设置才起效果,不知什么原因。
我的xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_cicle_white"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="48dp"
android:gravity="center_vertical|left"
android:paddingLeft="12dp"
android:text="@string/str_exit_title"
android:textColor="@color/code_green"
android:textSize="16sp"
android:textStyle="normal" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@drawable/separator_line" />
<TextView
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="52dp"
android:gravity="center_vertical|left"
android:paddingLeft="12dp"
android:text="@string/str_exit_content"
android:textSize="16sp" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@drawable/separator_line" />
<TextView
android:id="@+id/confirm"
android:layout_width="match_parent"
android:layout_height="48dp"
android:clickable="true"
android:gravity="center"
android:text="@string/str_ok"
android:textSize="16sp" />
</LinearLayout>
另外注意 style如果是这样的
<style name="existDialogStyle" parent="Theme.AppCompat.Dialog">
那么对应的Activity extends 的
public class ExistDialogActivity extends AppCompatActivity
如果style 非 AppCompat 则extends Activity
否则会报类似错
java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
还有要注意的是 调用起 该Dialog Acitivity 的方式
startActivity(new Intent(context, ExistDialogActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
addFlags FLAG_ACTIVITY_NEW_TASK
因为非Acitivity的context调用时如果栈中无该类,会报错
Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
点击打开链接
FLAG_ACTIVITY_NEW_TASK:例如现在栈1的情况是:A B C。C通过intent跳转到D,并且这个intent添加了FLAG_ACTIVITY_NEW_TASK标记,如果D这个Activity在Manifest.xml中的声明中添加了Task affinity,系统首先会查找有没有和D的Task affinity相同的task栈存在,如果有存在,将D压入那个栈,如果不存在则会新建一个D的affinity的栈将其压入。如果D的Task affinity默认没有设置,则会把其压入栈1,变成:A B C D,这样就和不加FLAG_ACTIVITY_NEW_TASK标记效果是一样的了。注意如果试图从非activity的非正常途径启动一个activity(例见下文“intent.setFlags()方法中参数的用例”),比如从一个service中启动一个activity,则intent比如要添加FLAG_ACTIVITY_NEW_TASK标记(编者按:activity要存在于activity的栈中,而非activity的途径启动activity时必然不存在一个activity的栈,所以要新起一个栈装入启动的activity)。简而言之,跳转到的activity根据情况,可能压在一个新建的栈中。
直到此时,我们的dialog样式的acitivity应该能正常显示出来了
然后我们运用SingleTask 和 onNewIntent 方法实现清除所有非相关activity
onNewIntent 的使用场景
launchMode为singleTask的时候,通过Intent跳到一个Activity,如果系统已经存在一个实例,系统就会将请求发送到这个实例上,但这个时候----------系统就不会再调用onCreate方法,而是调用onNewIntent方法。
我们在MainActivity 的 onNewIntent 方法中做处理,当然MainActivity 的LaunchMode 是 SingleTask
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (intent != null) {
boolean isExistApp = intent.getBooleanExtra(ExistDialogActivity.KEY_EXIST_APP, false);
if (isExistApp) {
startActivity(new Intent(this, LoginActivity.class));
finish();
return;
}
.............
}
}
至此,我们完成了从非activity 或全局监听下 弹出下线弹窗 并 完成清退所有activity 并跳转回登录界面的功能。