关于java.lang.IllegalArgumentException: View not attached to

今天遇到一个很奇特的问题,当用户设置了PIN码,在锁屏界面正常解锁PIN码后,进入Launcher时显示com.android.phone 已停止运行。一开始猜想会不会是解锁PIN码的时候处理导致了Phone进程报错,通过log分析找到了问题的大概原因:

AndroidRuntime: FATAL EXCEPTION: mainAndroidRuntime: java.lang.IllegalArgumentException: View not attached to window managerAndroidRuntime: at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:385)AndroidRuntime: at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:287)AndroidRuntime: at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:79)AndroidRuntime: at android.app.Dialog.dismissDialog(Dialog.java:323)AndroidRuntime: at android.app.Dialog.dismiss(Dialog.java:306)AndroidRuntime: at com.android.stk.StkDialogActivity$4.onClick(StkDialogActivity.java:188)AndroidRuntime: at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:169)AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:99)AndroidRuntime: at android.os.Looper.loop(Looper.java:153)AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:5299)AndroidRuntime: at java.lang.reflect.Method.invokeNative(Native Method)AndroidRuntime: at java.lang.reflect.Method.invoke(Method.java:511)AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)AndroidRuntime: at dalvik.system.NativeStart.main(Native Method)

转载请务必注明出处:

通过分析PIN码的解锁流程知道,并不是PIN码解释时的dialog导致的问题。PIN码解锁流程另用文档说明。

仔细查看log后发现有:

AndroidRuntime: at com.android.stk.StkDialogActivity$4.onClick(StkDialogActivity.java:188) 这是开机识别到SIM卡之后弹出的STK对话框。那为什么会报com.android.phone已停止运行呢?

经过以上分析,我们可以大致猜测是因为STK引起的问题,既然是STK的问题那为什么会报phone的错误呢?如果是phone的错误那么从log中应该可以检索到phone相关的问题,为什么没有呢?那么我们接下来一一解答这些问题。

(1). 为什么报错com.android.phone已停止运行?

通过查看STK的源码(单卡MTK的代码在/mediatec/packages/app/stk1),在其AndroidManifest.xml可以发现:

android:sharedUserId="android.uid.phone"

也就是STK和Phon在一个进程中,因此在报错的表现上来讲就会是com.andorid.phone。

(2). 为什么会报View not attached to window manager错误?

这个错误的意思是说我们所操作的View没有被纳入window manager的管理。

我们知道所有的窗口创建和管理都是依附于window manager的,因此Dialog的创建也不例外。Dialog的创建流程通过查看源码可以知道,在Dialog的构造函数中,创建了一个Window对象,但我们知道Window对象并不是用于显示的,真正用于显示的是View对象。因此通过Dialog的show方法构造了一个mDecor的View对象,并最终通过WindowManager的addView()方法显示Dialog。

通过查看log信息我们可以看到com.android.stk.StkDialogActivity$4.onClick(StkDialogActivity.java:188)

查看对应的StkDialogActivity代码后发现,在188行处代码为dialog.dismiss();

在网络上搜索后发现,多数情况下出现这种错误,都是在dismiss Dialog时,发现创建该Dialog的Activity存在而导致的。

比如在界面上显示一个Dialog,当任务处理结束后再Dismiss Dialog。如果在Dialog显示期间,该Activity因为某种原因被杀掉且又重新启动了,那么当任务结束时,Dismiss Dialog的时候WindowManager检查,就会发现该Dialog所属的Activity已经不存在了(重新启动了一次,是一个新的Activity),所以会报IllegalArgumentException: View not attached to window manager.

通过以上分析我们可以知道在STK Dialog在执行dismiss方法时,发现启动它的Activity已经不见了,被杀掉了(现在这个是重新启动的),所以才报错出现异常。

(3). 为什么STKDialogActivity会被"杀掉"?

通过跟踪查看异常log我们可以看到StkDialogActivity的生命周期打印log如下:

onCreateonResume – mbSendResp[false], sim id: 0… …省略部分onSaveInstanceStateonPause, sim id: 0… …省略部分onDestroy-onCreate… …省略部分onRestoreInstanceState – [com.android.internal.telephony.cat.TextMessage@41fe7d80]onResume – mbSendResp[false], sim id: 0

到这里后就出现了异常错误……

通过log我们可以很清楚的看到该Activity启动了两次。在log中我们也看到了onSaveInstanceState方法。

对于onSaveInstanceState方法,在Android SDK里面有这样的描述:

Android calls onSaveInstanceState() before the activity becomes vulnerable to being destroyed by the system, but does not bother calling it when the instance is actually being destroyed by a user action (such as pressing the BACK key)

也就说当某个activity变得“容易”被系统销毁时,该activity的onSaveInstanceState就会被执行,除非该activity是被用户主动销毁的,例如当用户按BACK键的时候。

为你的难过而快乐的是敌人,

关于java.lang.IllegalArgumentException: View not attached to

相关文章:

你感兴趣的文章:

标签云: