Android 8.0 上一个奇怪的IllegalStateException

Android 8.0 上一个奇怪的IllegalStateException

前言

API 26之后,给Activity应用Dialog主题,大部分第三方ROM都存在巨坑。

起因

公司项目在适配Android 8.0之后,爆发了一个触发率极高,而在Google Play Console上又找不到任何有效错误信息的IllegalStateException。Google Play Console统计信息如下:

java.lang.RuntimeException:
  at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3184)
  at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3279)
  at android.app.ActivityThread.-wrap12 (Unknown Source)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1881)
  at android.os.Handler.dispatchMessage (Handler.java:108)
  at android.os.Looper.loop (Looper.java:166)
  at android.app.ActivityThread.main (ActivityThread.java:7406)
  at java.lang.reflect.Method.invoke (Method.java)
  at com.android.internal.os.Zygote$MethodAndArgsCaller.run (Zygote.java:245)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:926)
Caused by: java.lang.IllegalStateException:
  at android.app.Activity.onCreate (Activity.java:1076)
  at android.support.v4.app.SupportActivity.onCreate (SupportActivity.java)
  at android.support.v4.app.FragmentActivity.onCreate (FragmentActivity.java:15)
  at android.support.v7.app.AppCompatActivity.onCreate (AppCompatActivity.java:36)
  at android.app.Activity.performCreate (Activity.java:7365)
  at android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1218)
  at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3137)
  at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3279)
  at android.app.ActivityThread.-wrap12 (Unknown Source)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1881)
  at android.os.Handler.dispatchMessage (Handler.java:108)
  at android.os.Looper.loop (Looper.java:166)
  at android.app.ActivityThread.main (ActivityThread.java:7406)
  at java.lang.reflect.Method.invoke (Method.java)
  at com.android.internal.os.Zygote$MethodAndArgsCaller.run (Zygote.java:245)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:926)

以及统计到的另一个错误信息:

java.lang.RuntimeException:
  at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2946)
  at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3046)
  at android.app.ActivityThread.-wrap11 (Unknown Source)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1688)
  at android.os.Handler.dispatchMessage (Handler.java:105)
  at android.os.Looper.loop (Looper.java:164)
  at android.app.ActivityThread.main (ActivityThread.java:6809)
  at java.lang.reflect.Method.invoke (Method.java)
  at com.android.internal.os.Zygote$MethodAndArgsCaller.run (Zygote.java:240)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:767)
Caused by: java.lang.IllegalStateException:
  at android.app.Activity.onCreate (Activity.java:995)
  at android.support.v4.app.SupportActivity.onCreate (SupportActivity.java)
  at android.support.v4.app.FragmentActivity.onCreate (FragmentActivity.java:15)
  at android.support.v7.app.AppCompatActivity.onCreate (AppCompatActivity.java:36)
  at android.app.Activity.performCreate (Activity.java:6998)
  at android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1230)
  at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2899)
  at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3046)
  at android.app.ActivityThread.-wrap11 (Unknown Source)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1688)
  at android.os.Handler.dispatchMessage (Handler.java:105)
  at android.os.Looper.loop (Looper.java:164)
  at android.app.ActivityThread.main (ActivityThread.java:6809)
  at java.lang.reflect.Method.invoke (Method.java)
  at com.android.internal.os.Zygote$MethodAndArgsCaller.run (Zygote.java:240)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:767)

两份错误信息并无太大区别,但就从错误信息来看,触发该Bug的必然是项目中的Activity,而该Activity在执行其父类的代码时就已经崩溃,而自身的代码并没有执行。这找起来就棘手了,都不清楚是哪个页面引发的。于是再结合错误信息截图来看看:

2018-03-16-1.PNG
2018-03-16-2.PNG

错误仅仅发生在适配API 26的版本上,错误仅仅发生在API 26的ROM,而手头的两台设备,Nexus 5X 跟Pixel 2 XL都未触发,而Google Play Console上也没有统计到亲儿子存在该问题,出问题的基本上都是国内的ROM,尤其华为的居多。

现在所知的关键点是,targetSdkVersion在26及以上且系统API在26及以上的设备才会触发,而触发的Activity连自身的代码都没有执行。那么就只剩Activity的声明处了,先去8.0行为变更里面看了一遍,并没有对Activity声明增加新的要求。翻开AndroidManifest.xml文件,所有的Activity都检查一遍,也并没有不和谐之处,无非是设置一下label以及配置一下theme。这些信息都不足以查出触发点来时,就只能找一台可以触发的机器了,于是通过测试的同事找来一台在触发机器列表里的手机,然而系统与应用及设备均符合触发条件,可这台机器就是不触发,实在无解。

眼见着就要无从下手了,但忽然想到公司项目还接入了友盟统计,抱着侥幸的心理上去看看是否有什么蛛丝马迹。不常使用友盟查看崩溃统计主要是其C++层的报错完全统计不到(项目涉及NDK开发)而数据又不够直观。幸运的是友盟果然统计到了重要信息,除开上面的报错信息以外,其补上了Google Play Console漏掉的一部分,而这一部分非常关键:

java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation
  at android.app.Activity.onCreate (Activity.java:1076)
  at android.support.v4.app.SupportActivity.onCreate (SupportActivity.java)
  at android.support.v4.app.FragmentActivity.onCreate (FragmentActivity.java:15)
  at android.support.v7.app.AppCompatActivity.onCreate (AppCompatActivity.java:36)
  at android.app.Activity.performCreate (Activity.java:7365)
  at android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1218)
  at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3137)
  at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3279)
  at android.app.ActivityThread.-wrap12 (Unknown Source)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1881)
  at android.os.Handler.dispatchMessage (Handler.java:108)
  at android.os.Looper.loop (Looper.java:166)
  at android.app.ActivityThread.main (ActivityThread.java:7406)
  at java.lang.reflect.Method.invoke (Method.java)
  at com.android.internal.os.Zygote$MethodAndArgsCaller.run (Zygote.java:245)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:926)

问题

其实仅仅这一句话最关键:

Only fullscreen opaque activities can request orientation

只有全屏不透明的Activity可以请求方向

没错,项目里的部分Activity应用了Dialog的主题,也就是说它是非全屏且透明的Activity。然而奇怪的是,这些Dialog样式的Activity并没有设定screenOrientation属性,也就是该属性用的是默认值,于该Activity来说并没有request orientation,因此,此处个人判定,应该是第三方ROM的问题。对于Dialog样式的Activity,即便是设置了screenOrientation属性,也不应该Activity崩溃,而应该是设置的screenOrientation属性无效,更何况并没有设置screenOrientation属性,仅仅是对Activity应用了Dialog的主题。

解决

定义一个透明的Activity主题:增加android:windowIsTranslucent属性为true,并设置透明的背景。而对于非要使用对话框样式的Activity,那么就对照对话框的Theme进行设置了,此处不展开说了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 176,268评论 25 709
  • 对好看的脸,会很认真的看一看,所以记得比较牢。对不好看的脸,都不会仔细去看,所以看了一眼之后就记不清长相了。 记不...
    Emma_L阅读 2,905评论 0 3
  • 从小到大,我从来不知道什么是爱,我以为爱情就是爱,亲亲我我就是爱,被人欣赏就是爱,被人认可就是爱,被人夸奖就...
    金晶花阅读 1,886评论 0 0
  • 520,多么有仪式感的日子。节日不是用来证明什么,只是让对方知道,你对我的重要性,我对你的重要性。仪式感是推进情感...
    senny1978阅读 1,805评论 0 2
  • 用相机定格时间,记录花儿最美好的时光。图片拍摄于乌鲁木齐。 ------------------ The end ...
    荷语微光阅读 1,454评论 2 1

友情链接更多精彩内容