谈谈Android中的消息提示那些坑

Stars-one 2021年05月28日 37次浏览 本篇字数为2,091字

本文为作者原创,转载请注明出处,谢谢配合
作者:Stars-one
链接:https://stars-one.site/2021/05/28/android-dialog-bug


Android中的消息提示无非就那几种,弹个窗(Toast或SnackBar),或者是弹出个对话框(Dialog),最近在使用的时候也是遇到了问题,有时候导致APP闪退

稍微研究会,总结了一下使用过程中需要注意的几个坑

需要切换到UI主线程

无论是使用弹窗或是弹个对话框,都需要在UI主线程中进行,否则就会导致APP闪退,由于自己经常是直接开个子线程进行网络请求的操作,偶尔会忘记切换回UI线程,就会导致闪退,提醒自己注意一下

自己封装了个弹窗方法作为BaseActivity一个方法中,这样之后新写的Activity页面都是继承这个BaseActivity,需要弹窗,调用方法很方便,连context也可以不用传,十分舒服

需要注意的是,封装记得在外层套个切换主线程的方法,如:

private void showToast(final String msg) {
	runOnUiThread(new Runnable() {
		@Override
		public void run() {
			Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
		}
	});
}

切换UI主线程的方法详情进参考Android开发——实现子线程更新UI - Stars-one - 博客园

后台Service弹窗

首先,得声明一个悬浮窗权限

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

使用了后台服务,但需要弹个窗,可以使用下面的代码

Handler handler = new Handler(Looper.getMainLooper());
	handler.post(new Runnable() {
		@Override
		public void run() {
			AlertDialog dialog = new AlertDialog.Builder(BaseMsgService.this)
					.setTitle("提示").setMessage(str).setPositiveButton("确定", new DialogInterface.OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int which) {
					
				}
			}).create();
			dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
			dialog.show();
		}
	});

悬浮窗权限

悬浮窗权限这单主要是针对的对话框,由于Android6.0引入了动态权限,如果从开启了一个Service,弹出对话框也会导致APP闪退,错误提示为:

permission denied for window type 2003

如下图所示

错误提示

可能你的报错提示不是上面这个,但是有permission denied这两个字样,估计就是权限的问题

处理的方式很简单,只需要授权即可

//6.0以上需要获取弹窗权限,跳转到设置页面
if (Build.VERSION.SDK_INT >= 23) {
	if (!Settings.canDrawOverlays(Login.this)) {
		Toast.makeText(Login.this, "软件需要悬浮窗权限,跳转到设置页面请手动勾选允许", Toast.LENGTH_SHORT).show();
		new Thread(new Runnable() {
			@Override
			public void run() {
				runOnUiThread(new Runnable() {
					@Override
					public void run() {
						Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
								Uri.parse("package:" + getPackageName()));
						startActivityForResult(intent, 111);
					}
				});
			}
		}).start();
	}
}