jsBridge接入流程

import deviceInfo from './deviceInfo'
import { setRefreshToken } from './token'

// === 設備判斷 ===
const u = navigator.userAgent
export const isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1
export const isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
export const isNativeMobile = (isAndroid || isIOS) && new URLSearchParams(window.location.search).get('native')

// === 調試信息 ===
console.log('=== 設備檢測 ===', {
userAgent: u,
isAndroid,
isIOS,
isNativeMobile,
urlParams: window.location.search
})

// === nativeTokenReady: 外部可 await 等待 token 注入 ===
let nativeTokenReadyResolve: (_token: string) => void
export const nativeTokenReady: Promise<string> = new Promise((resolve) => {
nativeTokenReadyResolve = resolve
})

// === 橋接狀態管理 ===
let bridgeInitialized = false
let tokenReceived = false

/**
* 安卓橋函數:需要 bridge.init()
*/
const androidFunction = (callback: any) => {
console.log('=== 安卓橋函數調用 ===', new Date().toISOString())

if (window.WebViewJavascriptBridge) {
console.log('=== 安卓橋已存在,直接回調 ===')
callback(window.WebViewJavascriptBridge)
} else {
console.log('=== 安卓橋不存在,等待WebViewJavascriptBridgeReady事件 ===')
document.addEventListener('WebViewJavascriptBridgeReady', () => {
console.log('=== 收到WebViewJavascriptBridgeReady事件 ===')
callback(window.WebViewJavascriptBridge)
}, false)
}
}

/**
* iOS 橋函數:用 iframe 觸發注入
*/
const iosFunction = (callback: any) => {
console.log('=== iOS橋函數調用 ===', new Date().toISOString())

if (window.WebViewJavascriptBridge) {
console.log('=== iOS橋已存在,直接回調 ===')
return callback(window.WebViewJavascriptBridge)
}

if (window.WVJBCallbacks) {
console.log('=== iOS橋回調已存在,添加到隊列 ===')
return window.WVJBCallbacks.push(callback)
}

? console.log('=== 創建iOS橋回調隊列和iframe ===')
window.WVJBCallbacks = [callback]
const WVJBIframe = document.createElement('iframe')
WVJBIframe.style.display = 'none'
WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__'
document.documentElement.appendChild(WVJBIframe)

setTimeout(() => {
document.documentElement.removeChild(WVJBIframe)
console.log('=== 移除iOS橋iframe ===')
}, 0)
}

/**
* 處理token注入
*/
const handleTokenInjection = (data: any) => {
console.log('=== 處理token注入 ===', new Date().toISOString())
console.log('原始數據:', data)
console.log('數據類型:', typeof data)

try {
let res = data
if (isAndroid && typeof data === 'string') {
try {
res = JSON.parse(data)
console.log('安卓JSON解析成功:', res)
} catch (e) {
console.error('安卓JSON解析失敗:', e, data)
return
}
}

console.log('處理后的數據:', res)
console.log('數據字段:', Object.keys(res || {}))

// 嘗試多種可能的token字段
const validToken = res['token']


if (validToken) {
console.log('=== 設置token成功 ===', validToken)
setRefreshToken(validToken)
tokenReceived = true
nativeTokenReadyResolve(validToken)
} else {
console.warn('=== 沒有找到有效的token ===')

// 即使沒有token也要resolve,避免無限等待
if (!tokenReceived) {
tokenReceived = true
nativeTokenReadyResolve('')
}
}

// 設置設備版本(如果有的話)
if (res?.['Device-Version']) {
console.log('=== 設置設備版本 ===', res['Device-Version'])
deviceInfo.setdeviceVersion(res['Device-Version'])
}

} catch (error) {
console.error('=== 處理token注入失敗 ===', error, data)
if (!tokenReceived) {
tokenReceived = true
nativeTokenReadyResolve('')
}
}
}

// === 導出的統一橋接初始化函數 ===
export function setupBridge(): any {
if (bridgeInitialized) {
console.log('=== 橋接已初始化,跳過重復初始化 ===')
return
}

console.log('=== 開始初始化橋接 ===', new Date().toISOString())
bridgeInitialized = true

window.setupWebViewJavascriptBridge = isAndroid ? androidFunction : iosFunction

? window.setupWebViewJavascriptBridge((bridge) => {
console.log('=== 橋接回調執行 ===', new Date().toISOString())
console.log('橋接對象:', bridge)

// 注冊原生注入 refreshToken 的方法
bridge.registerHandler('injectRefreshToken', handleTokenInjection)
console.log('=== 已注冊injectRefreshToken處理器 ===')

? ? // 安卓需要調用 bridge.init()
if (isAndroid) {
console.log('=== 調用安卓bridge.init ===')
bridge.init((_msg: any, responseCallback: any) => {
console.log('=== 安卓bridge.init回調 ===', _msg)
responseCallback('H5 已收到')
})
}
})
}

// === 封裝 callHandler 調用 ===
export const bridge = {
callHandler: (methodName: string, params?: any, callback?: any): any => {
console.log('=== 調用橋接方法 ===', methodName, params)

if (window?.setupWebViewJavascriptBridge) {
window.setupWebViewJavascriptBridge((bridge) => {
bridge.callHandler(methodName, params || null, (data: any, fn: any) => {
console.log('=== 橋接方法回調 ===', methodName, data)
callback?.(data, fn)
})
})
} else {
console.warn('=== 橋接未初始化,無法調用方法 ===', methodName)
}
}
}

// === 初始化橋接 ===
if (isNativeMobile) {
console.log('=== 檢測到原生環境,開始初始化 ===', new Date().toISOString())

// 立即初始化
setupBridge()

// 監聽全局事件(兜底方案)
const messageHandler = (event: any) => {
console.log('=== 收到message事件 ===', new Date().toISOString(), event.data)

// 檢查是否是token相關的事件
if (event.data && (event.data.token || event.data.refreshToken || event.data.type === 'injectRefreshToken')) {
console.log('=== 通過message事件收到token ===', event.data)
handleTokenInjection(event.data)
}
}

window.addEventListener('message', messageHandler)

// 延遲初始化(兜底)
setTimeout(() => {
if (!tokenReceived) {
console.log('=== 延遲初始化橋接 ===', new Date().toISOString())
setupBridge()
}
}, 1000)

// 超時處理
setTimeout(() => {
if (!tokenReceived) {
console.warn('=== 10秒內未收到token,可能存在問題 ===')
nativeTokenReadyResolve('')
}
}, 10000)
}

/**
* app攜帶地址欄參數?
* ? native=true
* ? theme=light | dark
*?
* bridge方法名
*/

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/921783.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/921783.shtml
英文地址,請注明出處:http://en.pswp.cn/news/921783.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【C++】19. 封裝紅?樹實現set和map

文章目錄一、源碼及框架分析二、模擬實現map和set1、insert的實現2、iterator的實現3、map?持[ ]4、模擬實現的完整源代碼1&#xff09;RBTree.h2&#xff09;Myset.h3&#xff09;Mymap.h4&#xff09;Test.cpp一、源碼及框架分析 SGI-STL30版本源代碼&#xff0c;map和set的…

面試不會問題

1. 什么是表鎖&#xff1f;什么是行鎖&#xff1f;什么情況下會使用表鎖&#xff1f;InnoDB引擎通過“索引”實現行鎖&#xff08;鎖定滿足條件的行&#xff09;&#xff0c;但如果操作無法通過索引定位行&#xff0c;會導致行鎖失效&#xff0c;進而升級為表鎖。常見的表現為&…

達夢數據庫-用戶,權限,角色

達夢數據庫-用戶,權限,角色 在達夢數據庫(DM8)中,用戶(User)、權限(Privilege)和角色(Role) 是數據庫安全體系的核心組成部分,用于控制誰可以訪問數據庫、能訪問哪些對象以及能執行哪些操作。 下面為你提供一份全面、詳細、結構化的說明,幫助你深入理解達夢數據…

uniapp原生插件 TCP Socket 使用文檔

uniapp原生插件 TCP Socket 使用文檔 試了插件市場幾個TCP Socket插件都不能實現監聽服務器主動斷開&#xff0c;于是閑來無事就開發了一款&#xff0c;本插件是一個基于 Netty 實現的 TCP 通信模塊&#xff0c;用于在 UniApp 插件中提供 TCP 連接、數據發送和連接管理功能。以…

VM中CentOS 7密碼重置

重啟虛擬機點擊e進入內核處理向下劃找到UTF-8在后面輸入rd.breakctrl X進入單用戶模式mount -o remount,rw/sysroot進行掛盤 chroot /sysroot訪問系統&#xff0c;并使用passwd修改root密碼 出現亂碼 輸入LANGen touch /.autorelabel 保存配置 exit exit退出等待系統重新打開&…

車規級MOS管AEC-Q101認證的關鍵參數解讀與失效模式-深圳阿賽姆

摘要本文拆解AEC-Q101認證的7大關鍵測試項&#xff08;UIS/溫度循環/THB等&#xff09;&#xff0c;結合M120N06JC等型號實測數據&#xff0c;解析雪崩失效/柵氧擊穿/綁定線脫落等故障機理&#xff0c;附選型核查表一、AEC-Q101認證核心測試項與參數解讀1.1 非鉗位電感開關測試…

嵌入式鐵頭山羊stm32-ADC實現軟件觸發的常規序列的單通道轉換-Day25

目錄 一、實驗目的 二、電路連接 三、實驗執行&#xff08;五步&#xff09; 1.初始化ADC的IO引腳 2.配置ADC的時鐘&#xff0c;注意要小于14MHz 3.根據ADC的編程接口 實現初始化ADC的基本參數 4.配置常規序列并閉合觸發輸入開關 5.閉合總開關、啟動并讀取轉換結果 四…

多模態模型出現“幻覺”,描述了表格中不存在的內容,如何修正?

在日常工作中&#xff0c;多模態模型的 “幻覺” 問題已成為影響效率的關鍵痛點 —— 當我們需要模型基于文檔生成建議性內容&#xff08;如行業報告分析、論文數據解讀等&#xff09;時&#xff0c;模型常因無法準確理解文檔信息&#xff0c;輸出包含 “虛構內容” 的結果&…

Java AI 智能問數:Function調用版如何重塑企業數據決策

Java AI 智能問數&#xff1a;Function調用版如何重塑企業數據決策 在數字化轉型浪潮中&#xff0c;企業一把手常面臨數據查詢的痛點&#xff1a;分析師需編寫復雜SQL&#xff0c;業務人員依賴IT支持&#xff0c;決策鏈條冗長。傳統方法效率低下&#xff0c;而自然語言處理&…

AI-調查研究-74-具身智能 機器人學習新突破:元學習與仿真到現實遷移的挑戰與機遇

點一下關注吧&#xff01;&#xff01;&#xff01;非常感謝&#xff01;&#xff01;持續更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持續更新中&#xff01;&#xff08;長期更新&#xff09; AI煉丹日志-31- 千呼萬喚始出來 GPT-5 發布&#xff01;“快的…

勞務員的就業前景如何?

勞務員的就業前景整體較為樂觀&#xff0c;受到行業需求、政策支持等因素的積極影響&#xff0c;同時也面臨著一些挑戰。以下是具體分析&#xff1a;1.就業優勢行業需求穩定&#xff1a;建筑行業作為國民經濟的支柱產業&#xff0c;持續發展使得對勞務員的需求較為穩定。無論是…

libvirt 新手指南:從零開始掌握虛擬化管理

引言 在云計算、大數據和邊緣計算的時代&#xff0c;虛擬化技術已成為 IT 基礎設施的核心支柱。它允許我們在單一物理服務器上運行多個虛擬機&#xff08;Virtual Machine&#xff0c;簡稱 VM&#xff09;&#xff0c;從而實現資源的高效利用、快速部署和靈活擴展。對于新手來說…

OpenLayers數據源集成 -- 章節三:矢量要素圖層詳解

前言在前面的文章中&#xff0c;我們學習了OpenLayers的瓦片圖層&#xff08;TileLayer&#xff09;技術。本文將深入探討OpenLayers中的矢量要素圖層&#xff08;VectorFeatureLayer&#xff09;功能&#xff0c;這是WebGIS開發中處理矢量數據、實現交互式地圖的核心技術。矢量…

從“能說話”到“會做事”:AI Agent如何重構日常工作流?

從“能說話”到“會做事”&#xff1a;AI Agent如何重構日常工作流&#xff1f;在人工智能飛速發展的當下&#xff0c;AI已從最初簡單的語音交互、信息檢索進化到了具備自主決策與行動能力的新階段&#xff0c;其中AI Agent的出現堪稱關鍵轉折點。從只能機械“說話”回答問題&a…

隨身wifi到底有沒有用?

不用繞彎子&#xff0c;直接說清隨身WiFi怎么回事&#xff0c;對比完家用WiFi和手機熱點&#xff0c;再避坑&#xff5e;一、先明白&#xff1a;隨身WiFi到底是啥&#xff1f; 1、簡單講就是「能揣兜里的WiFi發射器」——要么插張物聯卡&#xff0c;要么內置流量&#xff0c;能…

MySQL問題8

MySQL深度分頁優化思路 常見的3種優化思路如下&#xff1a; 1. 子查詢優化方式 示例改寫前&#xff1a; SELECT * FROM words WHERE name oee ORDER BY id LIMIT 99999990, 10;這個寫法會導致 MySQL 掃描并丟棄前面 99999990 行&#xff0c;效率極低。 示例改寫后&#xff…

洛谷 P1249 最大乘積-普及/提高-

P1249 最大乘積 題目描述 一個正整數一般可以分為幾個互不相同的自然數的和&#xff0c;如 312312312&#xff0c;413413413&#xff0c;514235142351423&#xff0c;615246152461524。 現在你的任務是將指定的正整數 nnn 分解成若干個互不相同的自然數&#xff08;也可以不分解…

大學地理信息科學該如何學習才能好就業

一、明確專業特點與就業方向地理信息科學是一門交叉性強、實踐性強的學科&#xff0c;融合了地理學、計算機科學、測繪、遙感等多個領域&#xff0c;廣泛應用于自然資源管理、城市規劃、交通、環境、農業、水利、智慧城市等行業。主要就業方向包括&#xff1a;政府部門/事業單位…

【git】Git 大文件推送失敗問題及解決方案

Git 大文件推送失敗問題及解決方案 在日常開發中&#xff0c;我們經常會遇到這樣的問題&#xff1a; Remote: File [xxx.exe] size 188.156MB, exceeds quota 100MB Remote: Please remove the file[s] from history and try again這是因為 Gitee/GitHub 等平臺對單個文件大小有…

國產銀河麒麟三維數字沙盤大數據可視化研訓推演模擬仿真地理信息系統

國產銀河麒麟三維數字沙盤大數據可視化研訓推演模擬仿真地理信息系統獨立自主知識產權和原創源代碼級地理信息系統平臺&#xff0c;核心引擎與算法實現全棧國產化&#xff0c;提供從數據采集、處理到可視化分析的全鏈條自主可控解決方案&#xff0c; 1.2支持國產操作系統&…