今天在配合客户实现安装第三方app时,遇到一个问题,安装过程中,会长时间黑屏(30s~60s),最初怀疑是否是安装时,android系统资源(内存和CPU)剩余不多,导致安装时间较长,但是这样的话,解释不通,为什么会黑屏的问题,这时只能辛苦导出系统anr日志和logcat日志,一点一点去跟踪分析了,具体错误信息如下:
11-17 16:40:07.336 4415 4415 E pzz : 安装APK文件
11-17 16:40:07.336 1330 1615 W ContextImpl: Calling a method in the system process without a qualified user: android.app.ContextImpl.sendBroadcast:966 com.android.server.policy.PhoneWindowManager.interceptKeyBeforeQueueing:6214 com.android.server.wm.InputMonitor.interceptKeyBeforeQueueing:448 com.android.server.input.InputManagerService.interceptKeyBeforeQueueing:1971 <bottom of call stack>
11-17 16:40:07.338 1330 20989 I ActivityManager: START u0 {act=android.intent.action.VIEW dat=content://com.feid.feidterminal.FileProvider/download/DownLoadFeiD/mt.apk typ=application/vnd.android.package-archive flg=0x10000001 cmp=com.android.packageinstaller/.InstallStart} from uid 10041
11-17 16:40:07.338 1330 1614 D WindowManager: mHIKKeyPolicy.interceptKeyBeforeDispatching
11-17 16:40:07.339 1330 1614 W KeyPolicyImpl: interceptKeyBeforeQueueing keyCode :140
11-17 16:40:07.341 400 400 W /system/bin/hwservicemanager: getTransport: Cannot find entry vendor.qti.hardware.iop@1.0::IIop/default in either framework or device manifest.
11-17 16:40:07.341 1330 20989 E ANDR-PERF-JNI: Iop tryGetService failed
11-17 16:40:07.345 1330 20989 D ActivityTrigger: activityStartTrigger: Activity is Triggerred in full screen ApplicationInfo{8d91d53 com.android.packageinstaller}
11-17 16:40:07.345 1330 20989 E ActivityTrigger: activityStartTrigger: not whiteListedcom.android.packageinstaller/com.android.packageinstaller.InstallStart/27
11-17 16:40:07.345 1330 20989 D CompatibilityInfo: mCompatibilityFlags - 4
11-17 16:40:07.345 1330 20989 D CompatibilityInfo: applicationDensity - 160
11-17 16:40:07.345 1330 20989 D CompatibilityInfo: applicationScale - 1.0
11-17 16:40:07.346 1330 20989 D ActivityTrigger: activityResumeTrigger: The activity in ApplicationInfo{8d91d53 com.android.packageinstaller} is now in focus and seems to be in full-screen mode
11-17 16:40:07.346 1330 20989 E ActivityTrigger: activityResumeTrigger: not whiteListedcom.android.packageinstaller/com.android.packageinstaller.InstallStart/27
11-17 16:40:07.350 1330 20989 D ActivityTrigger: activityResumeTrigger: The activity in ApplicationInfo{8d91d53 com.android.packageinstaller} is now in focus and seems to be in full-screen mode
11-17 16:40:07.350 1330 20989 E ActivityTrigger: activityResumeTrigger: not whiteListedcom.android.packageinstaller/com.android.packageinstaller.InstallStart/27
11-17 16:40:07.354 1330 20989 D CompatibilityInfo: mCompatibilityFlags - 4
11-17 16:40:07.354 1330 20989 D CompatibilityInfo: applicationDensity - 160
11-17 16:40:07.354 1330 20989 D CompatibilityInfo: applicationScale - 1.0
11-17 16:40:07.355 1330 20989 D CompatibilityInfo: mCompatibilityFlags - 4
11-17 16:40:07.355 1330 20989 D CompatibilityInfo: applicationDensity - 160
11-17 16:40:07.355 1330 20989 D CompatibilityInfo: applicationScale - 1.0
11-17 16:40:07.366 540 3460 D msm8916_platform: platform_set_channel_map mixer_ctl_name:Playback Channel Map12
11-17 16:40:07.367 540 3460 D msm8916_platform: platform_set_channel_map: set mapping(1 2 0 0 0 0 0 0) for channel:2
11-17 16:40:07.367 540 3460 D audio_hw_primary: start_output_stream: exit
11-17 16:40:07.369 1330 1343 I ActivityManager: START u0 {act=android.intent.action.VIEW dat=content://com.feid.feidterminal.FileProvider/download/DownLoadFeiD/mt.apk typ=application/vnd.android.package-archive flg=0x2000000 cmp=com.android.packageinstaller/.InstallStaging (has extras)} from uid 10015
11-17 16:40:07.372 1330 1343 D ActivityTrigger: activityStartTrigger: Activity is Triggerred in full screen ApplicationInfo{8d91d53 com.android.packageinstaller}
11-17 16:40:07.372 1330 1343 E ActivityTrigger: activityStartTrigger: not whiteListedcom.android.packageinstaller/com.android.packageinstaller.InstallStaging/27
11-17 16:40:07.373 1330 1343 D CompatibilityInfo: mCompatibilityFlags - 4
11-17 16:40:07.373 1330 1343 D CompatibilityInfo: applicationDensity - 160
11-17 16:40:07.373 1330 1343 D CompatibilityInfo: applicationScale - 1.0
11-17 16:40:07.373 1330 1343 D ActivityTrigger: activityResumeTrigger: The activity in ApplicationInfo{8d91d53 com.android.packageinstaller} is now in focus and seems to be in full-screen mode
11-17 16:40:07.373 1330 1343 E ActivityTrigger: activityResumeTrigger: not whiteListedcom.android.packageinstaller/com.android.packageinstaller.InstallStaging/27
11-17 16:40:07.373 1330 1343 D ActivityTrigger: ActivityTrigger activityPauseTrigger
11-17 16:40:07.374 1330 1343 D zww : acquireWakeLock ~~~
11-17 16:40:07.374 1330 1343 D zww : acquireWakeLockInternal: lock=240036497, flags=0x1, tag="*launch*", ws=WorkSource{10015}, uid=1000, pid=1330
11-17 16:40:07.374 1330 1343 E PowerManagerService: Read the path /sys/class/power_supply/usb/usb_otg successfully, the value is 1
11-17 16:40:07.384 1330 4261 D ActivityTrigger: activityResumeTrigger: The activity in ApplicationInfo{8d91d53 com.android.packageinstaller} is now in focus and seems to be in full-screen mode
11-17 16:40:07.384 1330 4261 E ActivityTrigger: activityResumeTrigger: not whiteListedcom.android.packageinstaller/com.android.packageinstaller.InstallStaging/27
11-17 16:40:07.386 1330 4261 D CompatibilityInfo: mCompatibilityFlags - 4
11-17 16:40:07.386 1330 4261 D CompatibilityInfo: applicationDensity - 160
11-17 16:40:07.386 1330 4261 D CompatibilityInfo: applicationScale - 1.0
11-17 16:40:07.440 21292 21292 W Activity: An activity without a UI must call finish() before onResume() completes
查问题的老方法,我们需要先看一下,系统为什么会报出这个异常,通过搜索源码发现,android 6.0之后,在/frameworks/base/core/java/android/app/Activity.java 中的**performResume()**方法添加了如下判断:
final void performResume() {
performRestart();
// 此处省略一万code ......
// invisible activities must be finished before onResume() completes
// 原因在这里,对比android5.x与6.0之后的此处源码,可知,新增了这个判断
// 判断当然视图是否可见,如果不可见,需要在onResume()中调用finish操作
if (!mVisibleFromClient && !mFinished) {
Log.w(TAG, "An activity without a UI must call finish() before onResume() completes");
if (getApplicationInfo().targetSdkVersion
> android.os.Build.VERSION_CODES.LOLLIPOP_MR1) {
throw new IllegalStateException(
"Activity " + mComponent.toShortString() +
" did not call finish() prior to onResume() completing");
}
}
// Now really resume, and install the current status bar and menu.
mCalled = false;
mFragments.dispatchResume();
mFragments.execPendingActions();
onPostResume();
if (!mCalled) {
throw new SuperNotCalledException(
"Activity " + mComponent.toShortString() +
" did not call through to super.onPostResume()");
}
}
由此可知,App代码中,应该是调用了什么属性或者进行了什么操作,导致视图不可见,进而导致视图运行时进入了这个判断,系统抛出了这个异常。
一层一层的抽丝剥茧去看,这时我们再从Activity: An activity without a UI must call finish() before onResume() completes
错误往回看日志,找到开头,可以发现,是app内部调用了packageinstaller之后爆发了这一系列问题,与客户进行沟通,发现,客户想要通过自己的app实现后台安装其他app,从上面分析可知,是在安装app过程中,系统报出的这个错误,所以我们找客户确认了一下,的确app代码中,进行了如下设置:
//xml中调用
<activity android:name=".xxxActivity"
android:theme="@android:style/Theme.Translucent.NoTitleBar"/>
//代码中在onCreate之前调用
setTheme(android.R.style.Theme_NoDisplay);
小结
问题原因找到了,我们现在想需要想解决方法,有上面的源码分析,可知,应用更新时,必然会调用到系统的packageInstall,而android6.0之后的系统,抛出这个异常的前提是,会去判断getApplicationInfo().targetSdkVersion android.os.Build.VERSION_CODES.LOLLIPOP_MR1
,所以解决方法有以下三个:
1) APP中,对于android系统做兼容处理,在android6.0之后的系统中,需要将android.R.style.Theme_No_Dispaly
属性改为android.R.style.Theme_Translucent_NoTitleBar
。
2) APP中,将targetSdkVersion
修改为小于等于android.os.Build.VERSION_CODES.LOLLIPOP_MR1(即SDK API 21
)。
3) 系统源码中,适配客户需求,当然了不能简单的只是把6.0之后performResume中新增的判断去掉这样修改,因为系统源码环环相扣,还是要了解设计者的意图,才可以去删除代码。