一、直播原理及流程
1.一個完整直播app原理
直播原理:把主播錄制的視頻,推送到服務器,在由服務器分發給觀眾觀看。
直播環節:推流端(采集、美顏處理、編碼、推流)、服務端處理(轉碼、錄制、截圖、鑒黃)、播放器(拉流、解碼、渲染)、互動系統(聊天室、禮物系統、贊)
2.直播app實現流程
1.采集、2.濾鏡處理、3.編碼、4.推流、5.CDN分發、6.拉流、7.解碼、8.播放、9.聊天互動
3.直播app架構
4.直播app技術點
二、直播基礎知識介紹:
1.采集視頻、音頻
* 1.1 采集視頻、音頻編碼框架 *
AVFoundation:AVFoundation是用來播放和創建實時的視聽媒體數據的框架,同時提供Objective-C接口來操作這些視聽數據,比如編輯,旋轉,重編碼
* 1.2 視頻、音頻硬件設備 *
CCD:圖像傳感器: 用於圖像采集和處理的過程,把圖像轉換成電信號。拾音器:聲音傳感器: 用於聲音采集和處理的過程,把聲音轉換成電信號。音頻采樣數據:一般都是PCM格式視頻采樣數據: 一般都是YUV,或RGB格式,采集到的原始音視頻的體積是非常大的,需要經過壓縮技術處理來提高傳輸效率
2.視頻處理(美顏,水印)
視頻處理原理:因為視頻最終也是通過GPU,一幀一幀渲染到屏幕上的,所以我們可以利用OpenGL ES,對視頻幀進行各種加工,從而視頻各種不同的效果,就好像一個水龍頭流出的水,經過若干節管道,然后流向不同的目標- 現在的各種美顏和視頻添加特效的app都是利用
GPUImage這個框架實現的,.
- 現在的各種美顏和視頻添加特效的app都是利用
* 視頻處理框架 *
GPUImage: GPUImage是一個基於OpenGL ES的一個強大的圖像/視頻處理框架,封裝好了各種濾鏡同時也可以編寫自定義的濾鏡,其本身內置了多達120多種常見的濾鏡效果。OpenGL:OpenGL(全寫Open Graphics Library)是個定義了一個跨編程語言、跨平台的編程接口的規格,它用於三維圖象(二維的亦可)。OpenGL是個專業的圖形程序接口,是一個功能強大,調用方便的底層圖形庫。OpenGL ES:OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL三維圖形 API 的子集,針對手機、PDA和游戲主機等嵌入式設備而設計。
3.視頻編碼解碼
* 3.1 視頻編碼框架 *
FFmpeg:是一個跨平台的開源視頻框架,能實現如視頻編碼,解碼,轉碼,串流,播放等豐富的功能。其支持的視頻格式以及播放協議非常豐富,幾乎包含了所有音視頻編解碼、封裝格式以及播放協議。- -Libswresample:可以對音頻進行重采樣,rematrixing 以及轉換采樣格式等操 作。
- -Libavcodec:提供了一個通用的編解碼框架,包含了許多視頻,音頻,字幕流 等編碼/解碼器。
- -Libavformat:用於對視頻進行封裝/解封裝。
- -Libavutil:包含一些共用的函數,如隨機數生成,數據結構,數學運算等。
- -Libpostproc:用於進行視頻的一些后期處理。
- -Libswscale:用於視頻圖像縮放,顏色空間轉換等。
- -Libavfilter:提供濾鏡功能。
X264:把視頻原數據YUV編碼壓縮成H.264格式VideoToolbox:蘋果自帶的視頻硬解碼和硬編碼API,但是在iOS8之后才開放。AudioToolbox:蘋果自帶的音頻硬解碼和硬編碼API
* 3.2 視頻編碼技術 *
視頻壓縮編碼標准:對視頻進行壓縮(視頻編碼)或者解壓縮(視頻解碼)的編碼技術,比如MPEG,H.264,這些視頻編碼技術是壓縮編碼視頻的主要作用:是將視頻像素數據壓縮成為視頻碼流,從而降低視頻的數據量。如果視頻不經過壓縮編碼的話,體積通常是非常大的,一部電影可能就要上百G的空間。注意:最影響視頻質量的是其視頻編碼數據和音頻編碼數據,跟封裝格式沒有多大關系
MPEG:一種視頻壓縮方式,它采用了幀間壓縮,僅存儲連續幀之間有差別的地方 ,從而達到較大的壓縮比H.264/AVC:一種視頻壓縮方式,采用事先預測和與MPEG中的P-B幀一樣的幀預測方法壓縮,它可以根據需要產生適合網絡情況傳輸的視頻流,還有更高的壓縮比,有更好的圖象質量注意1:如果是從單個畫面清晰度比較,MPEG4有優勢;從動作連貫性上的清晰度,H.264有優勢注意2:由於264的算法更加復雜,程序實現煩瑣,運行它需要更多的處理器和內存資源。因此,運行264對系統要求是比較高的。注意3:由於264的實現更加靈活,它把一些實現留給了廠商自己去實現,雖然這樣給實現帶來了很多好處,但是不同產品之間互通成了很大的問題,造成了通過A公司的編碼器編出的數據,必須通過A公司的解碼器去解這樣尷尬的事情
H.265/HEVC:一種視頻壓縮方式,基於H.264,保留原來的某些技術,同時對一些相關的技術加以改進,以改善碼流、編碼質量、延時和算法復雜度之間的關系,達到最優化設置。- H.265 是一種更為高效的編碼標准,能夠在同等畫質效果下將內容的體積壓縮得更小,傳輸時更快更省帶寬
I幀:(關鍵幀)保留一副完整的畫面,解碼時只需要本幀數據就可以完成(因為包含完整畫面)
P幀:(差別幀)保留這一幀跟之前幀的差別,解碼時需要用之前緩存的畫面疊加上本幀定義的差別,生成最終畫面。(P幀沒有完整畫面數據,只有與前一幀的畫面差別的數據)B幀:(雙向差別幀)保留的是本幀與前后幀的差別,解碼B幀,不僅要取得之前的緩存畫面,還要解碼之后的畫面,通過前后畫面的與本幀數據的疊加取得最終的畫面。B幀壓縮率高,但是解碼時CPU會比較累幀內(Intraframe)壓縮:當壓縮一幀圖像時,僅考慮本幀的數據而不考慮相鄰幀之間的冗余信息,幀內一般采用有損壓縮算法幀間(Interframe)壓縮:時間壓縮(Temporal compression),它通過比較時間軸上不同幀之間的數據進行壓縮。幀間壓縮一般是無損的muxing(合成):將視頻流、音頻流甚至是字幕流封裝到一個文件中(容器格式(FLV,TS)),作為一個信號進行傳輸。
* 3.3 音頻編碼技術 *
AAC,mp3:這些屬於音頻編碼技術,壓縮音頻用
* 3.4碼率控制 *
多碼率:觀眾所處的網絡情況是非常復雜的,有可能是WiFi,有可能4G、3G、甚至2G,那么怎么滿足多方需求呢?多搞幾條線路,根據當前網絡環境自定義碼率。- 列如:常常看見視頻播放軟件中的1024,720,高清,標清,流暢等,指的就是各種碼率。
* 3.5 視頻封裝格式 *
-
TS: 一種流媒體封裝格式,流媒體封裝有一個好處,就是不需要加載索引再播放,大大減少了首次載入的延遲,如果片子比較長,mp4文件的索引相當大,影響用戶體驗為什么要用TS:這是因為兩個TS片段可以無縫拼接,播放器能連續播放
-
FLV: 一種流媒體封裝格式,由於它形成的文件極小、加載速度極快,使得網絡觀看視頻文件成為可能,因此FLV格式成為了當今主流視頻格式
4.推流
推流:就是將采集到的音頻,視頻數據通過流媒體協議發送到流媒體服務器
* 4.1 數據傳輸框架 *
librtmp:用來傳輸RTMP協議格式的數據
* 4.2 流媒體數據傳輸協議 *
-
RTMP:實時消息傳輸協議,Adobe Systems公司為Flash播放器和服務器之間音頻、視頻和數據傳輸開發的開放協議,因為是開放協議所以都可以使用了。- RTMP協議用於對象、視頻、音頻的傳輸。
- 這個協議建立在TCP協議或者輪詢HTTP協議之上。
- RTMP協議就像一個用來裝數據包的容器,這些數據可以是FLV中的視音頻數據。一個單一的連接可以通過不同的通道傳輸多路網絡流,這些通道中的包都是按照固定大小的包傳輸的
chunk:消息包
5.流媒體服務器
* 5.1常用服務器 *
SRS:一款國人開發的優秀開源流媒體服務器系統BMS:也是一款流媒體服務器系統,但不開源,是SRS的商業版,比SRS功能更多nginx:免費開源web服務器,常用來配置流媒體服務器。
* 5.2數據分發 *
CDN:(Content Delivery Network),即內容分發網絡,將網站的內容發布到最接近用戶的網絡”邊緣”,使用戶可以就近取得所需的內容,解決 Internet網絡擁擠的狀況,提高用戶訪問網站的響應速度.CDN:代理服務器,相當於一個中介。CDN工作原理:比如請求流媒體數據- 1.上傳流媒體數據到服務器(源站)
- 2.源站存儲流媒體數據
- 3.客戶端播放流媒體,向CDN請求編碼后的流媒體數據
- 4.CDN的服務器響應請求,若節點上沒有該流媒體數據存在,則向源站繼續請求流媒體數據;若節點上已經緩存了該視頻文件,則跳到第6步。
- 5.源站響應CDN的請求,將流媒體分發到相應的CDN節點上
- 6.CDN將流媒體數據發送到客戶端
回源:當有用戶訪問某一個URL的時候,如果被解析到的那個CDN節點沒有緩存響應的內容,或者是緩存已經到期,就會回源站去獲取搜索。如果沒有人訪問,那么CDN節點不會主動去源站拿.帶寬:在固定的時間可傳輸的數據總量,- 比如64位、800MHz的前端總線,它的數據傳輸率就等於64bit×800MHz÷8(Byte)=6.4GB/s
負載均衡: 由多台服務器以對稱的方式組成一個服務器集合,每台服務器都具有等價的地位,都可以單獨對外提供服務而無須其他服務器的輔助.- 通過某種負載分擔技術,將外部發送來的請求均勻分配到對稱結構中的某一台服務器上,而接收到請求的服務器獨立地回應客戶的請求。
- 均衡負載能夠平均分配客戶請求到服務器列陣,籍此提供快速獲取重要數據,解決大量並發訪問服務問題。
- 這種群集技術可以用最少的投資獲得接近於大型主機的性能。
QoS(帶寬管理):限制每一個組群的帶寬,讓有限的帶寬發揮最大的效用
6.拉流
拉流,就是從流媒體服務器獲取音頻,視頻數據
直播協議選擇:- 即時性要求較高或有互動需求的可以采用
RTMP,RTSP - 對於有回放或跨平台需求的,推薦使用
HLS
- 即時性要求較高或有互動需求的可以采用
直播協議對比:
-
HLS:由Apple公司定義的用於實時流傳輸的協議,HLS基於HTTP協議實現,傳輸內容包括兩部分,一是M3U8描述文件,二是TS媒體文件。可實現流媒體的直播和點播,主要應用在iOS系統- HLS是
以點播的技術方式來實現直播 - HLS是
自適應碼率流播,客戶端會根據網絡狀況自動選擇不同碼率的視頻流,條件允許的情況下使用高碼率,網絡繁忙的時候使用低碼率,並且自動在二者間隨意切
換。這對移動設備網絡狀況不穩定的情況下保障流暢播放非常有幫助。 - 實現方法是服務器端提供多碼率視頻流,並且在列表文件中注明,播放器根據播放進度和下載速度自動調整。
- HLS是
-
HLS與RTMP對比:HLS主要是延時比較大,RTMP主要優勢在於延時低- HLS協議的小切片方式會生成大量的文件,存儲或處理這些文件會造成大量資源浪費
- 相比使用RTSP協議的好處在於,一旦切分完成,之后的分發過程完全不需要額外使用任何專門軟件,普通的網絡服務器即可,大大降低了CDN邊緣服務器的配置要求,可以使用任何現成的CDN,而一般服務器很少支持RTSP。
-
HTTP-FLV:基於HTTP協議流式的傳輸媒體內容。- 相對於RTMP,HTTP更簡單和廣為人知,內容延遲同樣可以做到1~3秒,打開速度更快,因為HTTP本身沒有復雜的狀態交互。所以從延遲角度來看,HTTP-FLV要優於RTMP。
-
RTSP:實時流傳輸協議,定義了一對多應用程序如何有效地通過IP網絡傳送多媒體數據. -
RTP:實時傳輸協議,RTP是建立在UDP協議上的,常與RTCP一起使用,其本身並沒有提供按時發送機制或其它服務質量(QoS)保證,它依賴於低層服務去實現這一過程。 -
RTCP:RTP的配套協議,主要功能是為RTP所提供的服務質量(QoS)提供反饋,收集相關媒體連接的統計信息,例如傳輸字節數,傳輸分組數,丟失分組數,單向和雙向網絡延遲等等。
- ijkplayer:一個基於FFmpeg的開源Android/iOS視頻播放器
- API易於集成;
- 編譯配置可裁剪,方便控制安裝包大小;
- 支持硬件加速解碼,更加省電
- 簡單易用,指定拉流URL,自動解碼播放.
7.解碼
* 7.1 解封裝 *
-
demuxing(分離):從視頻流、音頻流,字幕流合成的文件(容器格式(FLV,TS))中, 分解出視頻、音頻或字幕,各自進行解碼。
* 7.2 音頻編碼框架 *
-
fdk_aac:音頻編碼解碼框架,PCM音頻數據和AAC音頻數據互轉
* 7.3 解碼介紹 *
-
硬解碼:用GPU來解碼,減少CPU運算- 優點:播放流暢、低功耗,解碼速度快,
* 缺點:兼容不好
- 優點:播放流暢、低功耗,解碼速度快,
-
軟解碼:用CPU來解碼- 優點:兼容好
* 缺點:加大CPU負擔,耗電增加、沒有硬解碼流暢,解碼速度相對慢
- 優點:兼容好
8.播放
- ijkplayer:一個基於FFmpeg的開源Android/iOS視頻播放器
- API易於集成;
- 編譯配置可裁剪,方便控制安裝包大小;
- 支持硬件加速解碼,更加省電
- 簡單易用,指定拉流URL,自動解碼播放.
9.聊天互動
三、了解流媒體
流媒體開發:網絡層(socket或st)負責傳輸,協議層(rtmp或hls)負責網絡打包,封裝層(flv、ts)負責編解碼數據的封裝,編碼層(h.264和aac)負責圖像,音頻壓縮。
幀:每幀代表一幅靜止的圖像GOP:(Group of Pictures)畫面組,一個GOP就是一組連續的畫面,每個畫面都是一幀,一個GOP就是很多幀的集合- 直播的數據,其實是一組圖片,包括I幀、P幀、B幀,當用戶第一次觀看的時候,會尋找I幀,而播放器會到服務器尋找到最近的I幀反饋給用戶。因此,GOP Cache增加了端到端延遲,因為它必須要拿到最近的I幀
- GOP Cache的長度越長,畫面質量越好
碼率:圖片進行壓縮后每秒顯示的數據量。幀率:每秒顯示的圖片數。影響畫面流暢度,與畫面流暢度成正比:幀率越大,畫面越流暢;幀率越小,畫面越有跳動感。- 由於人類眼睛的特殊生理結構,如果所看畫面之幀率高於16的時候,就會認為是連貫的,此現象稱之為視覺暫留。並且當幀速達到一定數值后,再增長的話,人眼也不容易察覺到有明顯的流暢度提升了。
分辨率:(矩形)圖片的長度和寬度,即圖片的尺寸壓縮前的每秒數據量:幀率X分辨率(單位應該是若干個字節)壓縮比:壓縮前的每秒數據量/碼率 (對於同一個視頻源並采用同一種視頻編碼算法,則:壓縮比越高,畫面質量越差。)-
視頻文件格式:文件的后綴,比如.wmv,.mov,.mp4,.mp3,.avi,主要用處,根據文件格式,系統會自動判斷用什么軟件打開,
注意: 隨意修改文件格式,對文件的本身不會造成太大的影響,比如把avi改成mp4,文件還是avi.
-
視頻封裝格式:一種儲存視頻信息的容器,流式封裝可以有TS、FLV等,索引式的封裝有MP4,MOV,AVI等,主要作用:一個視頻文件往往會包含圖像和音頻,還有一些配置信息(如圖像和音頻的關聯,如何解碼它們等):這些內容需要按照一定的規則組織、封裝起來.注意:會發現封裝格式跟文件格式一樣,因為一般視頻文件格式的后綴名即采用相應的視頻封裝格式的名稱,所以視頻文件格式就是視頻封裝格式。
視頻封裝格式和視頻壓縮編碼標准:就好像項目工程和編程語言,封裝格式就是一個項目的工程,視頻編碼方式就是編程語言,一個項目工程可以用不同語言開發。
四、直播開發總結(仿照可以自己寫一個Demo)
用戶端(拉流)
框架 :IJKPlayer
直播中最最重要的元素,那就是視頻播放器了。視頻播放器的選擇,其實是非常多的,最著名的,非b站的IJKPlayer莫屬了。其實現在很多三方的播放器,開發者在編寫的時候,都是按照系統的MPMoviePlayer的接口設計的,所以,你只要學會使用一個播放器,其他播放器的使用都會很輕松的上手。
附上兩個比較有參考價值的demo,一個是自定義IJKPlayer,進度條、音量、亮度,可以參考這個demo,對IJKPlayer進行深度的個性化定制(其他播放器也適用),比如大部分播放器支持的屏幕手勢(滑動調整音量、亮度、進度等),另一個是ZFPlayer,這個播放器基於AVPlayer,主要可以參考里面的橫豎平切換的處理,也可以直接拿來做普通的視頻播放器繼承在應用中,很多功能都已經做好,用起來很方便。
服務器
首先你要找到一個測試服務器或者創建本地Nginx服務器,搭建本地服務器請看Mac搭建nginx+rtmp服務器
主播端 (推流)
框架:LFLiveKit
關於直播的推流,目前來說最火的應該是這個了LFLiveKit。
個人仿寫項目
但有一些個人仿寫項目都是IJKPlayer配合LFLiveKit完成的。
下面推薦幾個個人仿寫的項目,可以參考下大部分直播中會出現的場景的處理策略。
這個是仿映客的520Linkee,這個是仿喵播的MiaowShow,(可以看它們相關的博客講解)
這兩個都是市面上比較常見的個人手機端直播的典型實現方案。
自己實現:模擬實現視頻聊天功能
推流端用的是LFLiveKit框架,拉流用IJKPlayer,服務端找到一個測試服務器或者創建本地Nginx服務器
相關圖:

五、一個完整直播app功能
-
1、
聊天- 私聊、聊天室、點亮、推送、黑名單等;
-
2、
禮物- 普通禮物、豪華禮物、紅包、排行榜、第三方充值、內購、禮物動態更新、提現等;
-
3、
直播列表- 關注、熱門、最新、分類直播用戶列表等;
-
4、
自己直播- 錄制、推流、解碼、播放、美顏、心跳、后台切換、主播對管理員操作、管理員對用戶等;
-
5、
房間邏輯- 創建房間、進入房間、退出房間、關閉房間、切換房間、房間管理員設置、房間用戶列表等;
-
6、
用戶邏輯- 普通登陸、第三方登陸、注冊、搜索、修改個人信息、關注列表、粉絲列表、忘記密碼、查看個人信息、收入榜、關注和取關、檢索等;
-
7、
觀看直播- 聊天信息、滾屏彈幕、禮物顯示、加載界面等;
-
8、
統計- APP業務統計、第三方統計等;
-
9、
超管- 禁播、隱藏、審核等;
六、第三方提供的SDK(快速的開發完整的iOS直播app)
直播
SDK:金山雲、七牛雲、阿里雲、網易雲、騰訊雲
金山雲的SDK:他們的SDK更新頻率挺快的,而且最新版已經支持https了。但他們的SDK也存在一些bug,不過好在他們的每一版更新都會及時的進行修復。
經過對比了好多家的SDK demo(阿里、網易、騰訊、七牛等)后,你會發現金山的SDK demo是寫的最完善的,推流端你直接拿過來給個推流地址就可以推了,包括美顏、碼率、編碼等等,都在demo上有選項可供設置,你只要在開發的時候,對這些功能重新設計下UI就好了。播放器demo、推流demo,建議在使用的過程中,多跟進他們的更新release,你會發現他們每次更新都會優化很多功能、修復很多bug
聊天
SDK:融雲、環信和野狗
既然大家都在看直播,互動肯定也少不了,直播聊天室就必須要有。我們用的是融雲,因為融雲的宣傳和口碑都不錯,所以就選擇了融雲,而且也是好多直播服務商的合作伙伴,所以可以放心使用。其他的還有環信和野狗,環信的控制台和文檔,不如融雲友好,野狗的沒有試過,個人建議使用融雲。而且融雲官網有集成了播放器、聊天的直播間demo可以參考,里面帶了一個香港某電視台的直播流,可以用來測試用來 rtmp://live.hkstv.hk.lxdns.com/live/hks 。
然后聊天中的聊天列表的處理,可以參考我的這篇簡書來處理,以優化性能 http://www.jianshu.com/p/518e9c169274 。
這里有一點需要注意,在一個controller中,將當前controller設置為融雲的消息接收代理,就可以接收融雲消息了。
[[RCIMClient sharedRCIMClient] setReceiveMessageDelegate:self object:nil];
在頁面dealloc中不要只調用 [RCIMClient sharedRCIMClient] quitChatRoom 退出直播間就覺得沒事了,因為退出直播間是異步的,可能在當前controller dealloc后才會退出,如果在這段時間收到新的消息,[RCIMClient sharedRCIMClient]就會因為delegate釋放了而導致崩潰,所以要在當前controller的dealloc中設置消息接收代理為nil。
[[RCIMClient sharedRCIMClient] setReceiveMessageDelegate:nil object:nil];
點贊動畫
點贊動畫可以參考這個 https://github.com/singer1026/DMHeartFlyAnimation ,主要通過CAKeyFrameAnimation和UIBezierPath完成,也可以自行修改代碼修改動畫軌跡、替換點贊圖片等。
彈幕
彈幕建議使用BarrageRenderer,性能不錯,git主頁的介紹,就能讓你很簡單的上手使用,但如果你要做歷史消息的彈幕和即時消息結合的彈幕,建議歷史彈幕的遍歷以及時間軸綁定,還是自己寫比較好,因為這個庫的redisplay以及綁定時間軸方法,在與即時消息結合的時候,彈幕的展示可能會有重復出現多次的現象。
網絡切換
直播中我們要考慮用戶的當前網絡狀態,移動網絡幫他停止播放,或者切換到wifi的時候,幫他重連,以減少流量的耗費。網絡的變化主要通過兩種方式判斷,一種是Reachability,另一種是獲取狀態欄上的網絡狀態。
Reachability寫在AppDelegate中,在網絡狀態變化的時候,block中的代碼就會被調用,你想把網絡變化的消息發送給直播頁面,直接用通知中心就可以,然后Reachability建議使用AFNetworking的,因為之前有文章說Reachability庫可能會引起不支持ipv6導致審核被拒,我們項目中用的AFNetworking中的Reachability,沒有問題:
- (void)monitorNetworking { AFNetworkReachabilityManager *mgr = [AFNetworkReachabilityManager sharedManager]; [mgr setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { switch (status) { wifi網絡 break; 移動網絡 break; case AFNetworkReachabilityStatusNotReachable: 無網絡 break; case AFNetworkReachabilityStatusUnknown: 未知網絡 break; default: break; } }]; //開始監控 [mgr startMonitoring]; }
獲取狀態欄網絡狀態,有人說在狀態欄隱藏的頁面,沒法獲取網絡狀態,實測是可以獲取的,方法里面有我寫的枚舉,替換下就好了:
- (NSString *)getCurrentNetWork { NSArray *subviews = [[[[UIApplication sharedApplication] valueForKeyPath:@"statusBar"] valueForKeyPath:@"foregroundView"] subviews]; for (id child in subviews) { if ([child isKindOfClass:NSClassFromString(@"UIStatusBarDataNetworkItemView")]) { //獲取到狀態欄碼 int networkType = [[child valueForKeyPath:@"dataNetworkType"] intValue]; switch (networkType) { case 0: { // states = NetworkStatesNone; return CurrentNetWorkNone; } break; case 1: { // states = NetworkStates2G; return CurrentNetWorkMobile; } break; case 2: { // states = NetworkStates3G; return CurrentNetWorkMobile; } break; case 3: { // states = NetworkStates4G; return CurrentNetWorkMobile; } break; case 5: { // states = NetworkStatesWIFI; return CurrentNetWorkWifi; } break; default: { return CurrentNetWorkNone; } break; } } } return CurrentNetWorkNone; }
七、性能問題
