最近終于有時(shí)間來整理一下代碼 修修bug
然后發(fā)現(xiàn)有一樣這樣的問題,占據(jù)了差不多10%的安卓用戶毡庆,以vivo坑赡、OPPO 、榮耀么抗、華為入門機(jī)居多毅否。我手上4臺機(jī)器怎么都復(fù)現(xiàn)不出來,真不知道國產(chǎn)廠商做了啥
我們知道 Android 8.0之后規(guī)定服務(wù)一定要前臺顯示蝇刀,不允許直接使用startService螟加,需要用前臺方式啟動(dòng),然后在服務(wù)里面在通知欄里搞個(gè)通知顯示出來熊泵,說明服務(wù)正在運(yùn)行仰迁。
然后我們看異常信息就這么一句話
Context.startForegroundService() did not then call Service.startForeground()
啥也沒了!啥也沒了顽分!啥也沒了徐许!
就是說調(diào)用startForegroundService啟動(dòng)服務(wù),但是沒有在服務(wù)里面調(diào)用startForeground()前臺顯示(我明明就調(diào)用了卒蘸!竟然說我每調(diào)用)
那就搜源碼看看雌隅,然后發(fā)現(xiàn)有兩個(gè)類似的地方,出現(xiàn)了這句話缸沃。但是我這樣異常沒有冒號也沒有ServiceRecord恰起。(知道為什么的小伙伴請務(wù)必告訴一下我唄)
不過有冒號的這兩種異常日志系統(tǒng)確實(shí)也有收集,有很多趾牧,估計(jì)這日志收集把ServiceRecord這個(gè)里面的東西也歸類了吧
既然有那就一起看检盼、出現(xiàn)Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord的原因有下面兩個(gè)
一個(gè)是Context.startForegroundService服務(wù)啟動(dòng)后沒有調(diào)用Service.startForeground(),5秒內(nèi) 服務(wù)執(zhí)行完畢 服務(wù)結(jié)束翘单、就產(chǎn)生Crash這個(gè)異常
另外一個(gè)是Context.startForegroundService啟動(dòng)服務(wù)后吨枉、5秒后都沒有調(diào)用Service.startForeground()就爆ANR
看完這兩個(gè)原因我就很懵逼了蹦渣。
因?yàn)槲襑elcomeActivity 十分簡單?onCreate沒啥東西 然后獲取了一下權(quán)限 ?就openHome了
判斷了一下是否在運(yùn)行、就直接啟動(dòng)了
然后服務(wù)里面就Service.startForeground()貌亭,通道我也是每個(gè)服務(wù)new一個(gè)的啊柬唯,ID我是一個(gè)服務(wù)一個(gè)ID,啟動(dòng)之前我也通過EventBus把萬一有的其他這個(gè)AppUpdateService個(gè)停止了圃庭,理論上不會重復(fù)了
然后我們再看詳細(xì)的崩潰日志
結(jié)果還真超過了5秒锄奢,有些還10幾秒 20幾秒 ,然后看回代碼發(fā)現(xiàn)context.startForegroundService(intent);之后就是隔了5秒以上 服務(wù)才執(zhí)行onCreate 然后再startForeground已經(jīng)為時(shí)已晚
這就有點(diǎn)尷尬了正常測試發(fā)現(xiàn)每次都是幾十毫秒就執(zhí)行的剧腻,但是日志顯示這些手機(jī)確實(shí)是超過5秒以上才啟動(dòng)的 坑拘央!
所以到此android.app.RemoteServiceException?Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord 的原因我已經(jīng)找到了
至于為什么會這樣我還要好好研究一下ams了,因?yàn)槲曳?wù)并沒有做什么東西只發(fā)了一個(gè)請求恕酸,歡迎頁也是很簡單堪滨。不過我發(fā)現(xiàn)就是這些國產(chǎn)手機(jī)胯陋,安裝更新的時(shí)候蕊温,原來的服務(wù)、activity好像是沒有殺死的遏乔。然后這里會導(dǎo)致Notification ID重復(fù)
總結(jié)
1.調(diào)用startForeground();的時(shí)候ID不要重復(fù)
2.調(diào)用startForeground();的時(shí)候ID不能為零义矛!
3.服務(wù)啟動(dòng)后優(yōu)先調(diào)用startForeground();
4.onStartCommand這個(gè)東西保活的時(shí)候盟萨,有寫的不好就會產(chǎn)生第一點(diǎn)的重復(fù)
5.NotificationChannel這個(gè)東西每次要new出來getNotificationChannel可能會不太好