Android實(shí)戰(zhàn)——系統(tǒng)懸浮窗踩坑記

1.背景介紹

開啟懸浮窗后,小窗懸浮在app內(nèi)及桌面上,并保持懸浮窗頁面所有狀態(tài)

預(yù)覽


video

路由介紹


image

功能概覽(??:【】標(biāo)記處有坑,后面有解釋和解決辦法)

  1. splash->首頁->詳情頁->懸浮窗頁->回到桌面->點(diǎn)擊桌面App圖標(biāo)->【懸浮窗頁】
  2. splash->首頁->詳情頁->懸浮窗頁->開啟懸浮窗->點(diǎn)擊懸浮窗->懸浮窗頁
  3. splash->首頁->詳情頁->懸浮窗頁->開啟懸浮窗->回到桌面->點(diǎn)擊懸浮窗->懸浮窗頁->【返回詳情頁】

2.功能實(shí)現(xiàn)

  • 在AndroidManifest.xml將懸浮窗頁面android:launchMode="singleInstance"
  • 添加權(quán)限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
  • 檢查懸浮窗權(quán)限
  • 點(diǎn)擊開啟,將懸浮窗頁置于后臺(tái),同時(shí)添加小窗
moveTaskToBack(true)

var windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
windowManager.addView(...)
  • 點(diǎn)擊小窗將浮窗頁置于前臺(tái)
var intent = Intent(it, FloatWindowActivity::class.java).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
it.startActivity(intent)
  • 進(jìn)入懸浮窗頁面關(guān)閉小窗,保留懸浮窗頁面
override fun onRestart() {
    super.onRestart()
    closeFloatWindow(this, exitFloatActivity = false)
}
  • 點(diǎn)擊關(guān)閉小窗, 同時(shí)將后臺(tái)的懸浮窗頁面finish
closeFloatWindow(this, exitFloatActivity = true)

3.踩坑級(jí)解決方案

  1. 功能預(yù)覽中第一條,點(diǎn)擊桌面App圖標(biāo)會(huì)顯示詳情頁面,期望顯示懸浮窗頁

解釋:

由于設(shè)置了懸浮窗頁為singleInstance,所以默認(rèn)打開的是路由棧A的最上面路由,而不是路由棧B的懸浮窗頁面。

解決:

在懸浮窗頁面監(jiān)聽app回到前臺(tái),如果不在小窗中,將該路由棧拉回前臺(tái)

if (FloatWindowHelper.instance.dragFloatWrapper == null) {
    var intent = Intent(this, FloatWindowActivity::class.java)
        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        .addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
    startActivity(intent)
}

2.功能預(yù)覽中第三條,懸浮窗頁面點(diǎn)擊返回會(huì)回到桌面,期望回到詳情頁

解釋:

上一步點(diǎn)擊懸浮窗,路由跳轉(zhuǎn)到懸浮窗頁面,此時(shí)啟動(dòng)的只有路由棧B,所以返回就直接回到桌面了

解決:

如果在桌面點(diǎn)擊懸浮窗時(shí),先啟動(dòng)app(默認(rèn)路由棧A),這里有個(gè)小細(xì)節(jié),會(huì)啟動(dòng)我們清單文件里設(shè)置了LAUNCHER的頁面,即Splash頁面,這里只需要finish掉不需要再自動(dòng)跳到主頁

// 先啟動(dòng)app,默認(rèn)standard路由棧
if (isAppInBg) {
    context.let {
        val intent = it.packageManager.getLaunchIntentForPackage(it.packageName)
        it.startActivity(intent)
        // 告訴splash不需要跳轉(zhuǎn)到主頁,然后再恢復(fù)需要跳轉(zhuǎn)
        needJumpToMain = false
        timer.schedule(object : TimerTask() {
            override fun run() {[link](https://note.youdao.com/)
                needJumpToMain = true
            }
        }, 1200)

    }
    isAppInBg = false
}

源碼已上傳至github

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容