Android使用BackgroundMail发邮件触发IllegalArgumentException崩溃求助
解决BackgroundMail发送邮件后崩溃的问题
问题根源分析
从你提供的崩溃日志和SendEmailTask代码来看,崩溃的直接原因是:当BackgroundMail内部的AsyncTask执行完后台任务进入onPostExecute时,它尝试关闭一个内部创建的ProgressDialog,但此时你的Activity已经被销毁(比如用户切走页面、Activity被finish),导致Dialog对应的View已经脱离了WindowManager,从而抛出IllegalArgumentException: View not attached to window manager。
由于你无法修改BackgroundMail的源码,我们可以从自己的调用代码入手解决问题。
解决方案(无需修改BackgroundMail源码)
1. 关闭BackgroundMail的进度对话框显示(推荐)
既然你明确提到自己未使用任何对话框,那直接让BackgroundMail不要创建和显示内部的ProgressDialog即可,从根源上避免dismiss时的崩溃。
只需要在构建BackgroundMail实例时,添加关闭进度可见性的配置(如果Builder提供对应方法):
BackgroundMail.newBuilder(mContext) .withUsername("gmail id") .withPassword("pass") .withMailto("gmail id") .withType(BackgroundMail.TYPE_PLAIN) .withSubject("New Meter Installation") .withBody("Meter #" + msn + " is "+ com+ " and "+ status) .withProcessVisibility(false) // 关键:关闭内部进度对话框 .send();
如果Builder没有暴露withProcessVisibility方法,也可以用反射临时修改该字段:
BackgroundMail mail = BackgroundMail.newBuilder(mContext) .withUsername("gmail id") .withPassword("pass") .withMailto("gmail id") .withType(BackgroundMail.TYPE_PLAIN) .withSubject("New Meter Installation") .withBody("Meter #" + msn + " is "+ com+ " and "+ status) .build(); // 先构建实例,不直接send // 反射修改processVisibility为false try { Field field = BackgroundMail.class.getDeclaredField("processVisibility"); field.setAccessible(true); field.set(mail, false); } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); } mail.send(); // 最后执行发送
2. 确保调用send时Activity处于存活状态
如果之后需要保留进度提示,那要保证调用BackgroundMail.send()时,当前的Activity还没有被销毁。可以在Activity中维护一个存活标记:
// 在你的Activity类中 private boolean isActivityAlive = true; @Override protected void onDestroy() { super.onDestroy(); isActivityAlive = false; } // 调用邮件发送的代码块中 if (response.body().getStatus().equals("OK")) { // 你的其他业务代码... if (isActivityAlive) { BackgroundMail.newBuilder(this) // 传递Activity作为Context,而非ApplicationContext // 配置信息... .send(); } }
额外优化提示
- 不要用
ApplicationContext初始化BackgroundMail,因为ProgressDialog依赖Activity的Window环境,用Application Context会引发其他异常。 - 可以自定义发送结果的提示逻辑,替换
BackgroundMail自带的Toast,进一步规避其内部潜在问题:BackgroundMail.newBuilder(mContext) // 配置信息... .onSuccess(() -> { // 自定义成功提示,确保在Activity存活时执行 if (mContext instanceof Activity && !((Activity) mContext).isFinishing()) { ((Activity) mContext).runOnUiThread(() -> Toast.makeText(mContext, "邮件发送成功", Toast.LENGTH_SHORT).show() ); } }) .onFail(() -> { // 自定义失败提示 if (mContext instanceof Activity && !((Activity) mContext).isFinishing()) { ((Activity) mContext).runOnUiThread(() -> Toast.makeText(mContext, "邮件发送失败", Toast.LENGTH_SHORT).show() ); } }) .send();
内容的提问来源于stack exchange,提问作者Moeez
相关产品推荐
相关产品推荐

