前几天无意中发现自己的程序不能响应系统的屏保,呵呵,一种不祥的预感袭上心头,以前一个朋友也向我问过这样的情况,只是当时没有碰到,并不在意,但是现在遇到了。呵呵,只好面对。
这属于与系统交互时出的错,归根结底还是程序有点问题,但调试起来很困难,因为模拟器上是无法模拟出系统的屏保的。
我兀自在想,程序究竟在什么地方出错?是结构的问题吗(我使用了multiview),还是代码的错误?我的程序是直接写屏的(direct screen access),因此在接收系统消息时有自己特有的办法(当然我如果用传统结构,就不会出现这样的问题),那就是AbortNow()和Restart()的调用,经过调试,发现当菜单出现或对话框出现以及到后台时(当然系统的屏保事件的接收也是如此,此为后话),是先执行AbortNow再执行Restart的。我一步步的调式,发现程序在屏保事件应该出现时(有时间定制)根本就不执行AbortNow(),也就是无法响应这个系统事件。而菜单出现遮蔽屏幕时会响应该事件,但立刻就报告kern-exec3错误,程序崩溃。(后一个问题的原因后来也查明,是HandleForegroundEventL调度不当)
呵呵,现在说的容易,当时为弄清这个也折腾了不少时间。好了,不多说了,经过种种排查,发现原来是引擎中有点问题,缺少了一段防止ViewSrv 11 problems的代码,呵呵,总的来说就是刷新的太快,而不能响应到系统事件了,到这里我本以为万事Ok了,但却出现了另一个棘手的问题,那就是偶然性kern-exec3错误,呵呵,程序最怕这个了,时好时坏,简直让你无从下手:)看来上面说的HandleForegroundEventL并没有完全解决这个问题,后来得到启发,使用User::Panic来了场彻底的硬件调试(好辛苦好烦琐),才发现了偶然性错误中的必然性,就在于iDirectScreenAccess->StartL(),这个会产生偶然性的错误,而一旦错误发生后就会产生崩溃(因为下面的代码还不知道,继续使用着iDirectScreenAccess对象),这样的话我通过错误捕捉: TRAPD(dsaErr, iDirectScreenAccess->StartL()); if(dsaErr == KErrNone) { //构建正确下处理 } else { //构建失败下处理 } 彻底的避免了这个偶然错误:)
呵呵,事到如此,原以为功德圆满,不料在测试时又发生了意外,在接受和拒绝电话时,暂停对话框会出现重叠,导致程序无法玩下去,当然后来经过派查和安插标志位也避免了这个问题,不过之中的种种确实搞得很辛苦:)
万事总有第一次,这次我学到很多东西,呵呵,包括技术和经验上的,以及对待问题的方法,呵呵,有问题不要急,慢慢静下心来做,总会成功的,另外不要怕烦,有的时候对自己程序必要的彻底检查还是要做,把错误范围一步步缩小,这就是你第一步胜利!
另外,多学习经典示例代码也很重要:) (不过有必要指出,这里涉及到两个经典代码,Retroblaster和DirScrAcc都各自有先天的错误,贻误了我不少时间呵:)学习它,但别迷信它,你能做得更好! |