接ReactNative跨平臺(tái)開發(fā)實(shí)踐-簡易直播demo1
三:實(shí)現(xiàn)細(xì)節(jié)
1.集成ReactNative
官網(wǎng)上已經(jīng)對(duì)安卓與iOS平臺(tái)集成ReactNative描述的很詳細(xì)了,在此就僅附上官網(wǎng)地址,按照官網(wǎng)步驟就可以集成到現(xiàn)有的原生APP中了。
官網(wǎng)地址:http://facebook.github.io/react-native/docs/integration-with-existing-apps.html
2.第三方庫使用方法
簡要介紹下對(duì)于本demo中使用到的百度推流端SDK,播放端SDK與融云IM SDK的使用方式。
以iOS端為例:
整個(gè)工程是基于cocoapods來開發(fā)的,因?yàn)橐昧说谌綆?,使用cocoapods方便管理。
pod 'BaiduBCECapture', "~> 2.0"
pod 'BaiduBCEPlayerLSS', "2.0.0"
pod 'RongCloudIM', "~> 2.8.14"
推流SDK:BaiduBCECapture與播放SDK:BaiduBCEPlayerLSS的使用比較簡單,根據(jù)官網(wǎng)提供的demo中的調(diào)用方法,將自己的View(在安卓中則是surfaceView)交給SDK來持有就能實(shí)現(xiàn)視頻渲染了。
下圖則是具體的與第三方SDK的交互流程:

根據(jù)上圖再看代碼就很清晰了。
再簡要介紹下融云IM SDK:RongCloudIM的使用方法,基本原理為實(shí)現(xiàn)協(xié)議RCIMClientReceiveMessageDelegate,接收到消息進(jìn)入?yún)f(xié)議方法onReceived,其余例如發(fā)送消息的操作都是由單例來完成。
3.(重點(diǎn))將native組件包裝成component暴露給JS的實(shí)現(xiàn)過程
首先附上官網(wǎng)中將Native UI Component封裝給RN的地址:
iOS:http://facebook.github.io/react-native/docs/native-components-ios.html
Android:http://facebook.github.io/react-native/docs/native-components-android.html
根據(jù)前面的設(shè)計(jì)思路,可以總結(jié)出需要封裝的類即為持有了Model的原生類,RN層需要在這個(gè)原生組件之上放置按鈕等控件。
iOS的封裝的步驟按照官網(wǎng)步驟即可,但安卓的就要復(fù)雜一些,首先明確在安卓中是由ViewGroup來管理一系列的View的,但由于我們是想跟iOS的設(shè)計(jì)思路保持一致,即在RN中直接使用原生類的component,在其上加控件,那么需要封裝的就不能是官網(wǎng)示例中的 SimpleViewManager了,必須是可以管理View的ViewGroup,由于我不會(huì)安卓開發(fā),關(guān)于這點(diǎn)走了不少的彎路,還是萬分感謝安卓的同事的指點(diǎn)。
public class ZYLiveBackGroundViewManager extends ViewGroupManager<FrameLayout>
暴露給RN的方法:
1.無需回調(diào)的方法:RCT_EXPORT_METHOD(),如界面上的返回按鈕就無需回調(diào),這個(gè)按鈕直接返回設(shè)置頁,無論結(jié)束推流或播放停止時(shí)是成功還是失敗都會(huì)返回,所以無需將其設(shè)置為回調(diào)方法。
2.需要回調(diào)的方法:RCT_REMAP_METHOD(),如推流界面的控制攝像頭方向,設(shè)置美顏,設(shè)置閃光燈以及開啟推流等按鈕都需要知道是否操作成功,若操作成功更改界面,來提示用戶操作成功,這類需要更新UI的方法就需要回調(diào)。
具體實(shí)現(xiàn)方法附上官網(wǎng)地址:
iOS:http://facebook.github.io/react-native/docs/native-modules-ios.html
Android:http://facebook.github.io/react-native/docs/native-modules-android.html
這里值得注意的是RN在設(shè)計(jì)的時(shí)候,無論是iOS還是安卓,只要是原生封裝暴露給RN的component,都已經(jīng)實(shí)現(xiàn)了橋接協(xié)議:
iOS:
@interface RCTViewManager : NSObject <RCTBridgeModule>
android:
...
public abstract class ViewGroupManager <T extends ViewGroup>
extends BaseViewManager<T, LayoutShadowNode>
...
...
public abstract class BaseViewManager<T extends View, C extends LayoutShadowNode> extends ViewManager<T, C>
...
...
public abstract class ViewManager<T extends View, C extends ReactShadowNode> extends BaseJavaModule
...
這樣做的原因應(yīng)該去看下源碼才能理解了,但對(duì)我們來說,本身已經(jīng)暴露成功的Native UI Component就已經(jīng)可以當(dāng)成Native Module來使用了。所以,關(guān)于module的方法都可直接寫在這個(gè)component中。
使用方法如下,以iOS中的推流層為例:
nativeStreamView.js
module.exports = requireNativeComponent('ZYLiveBackGroundView', null);//將原生封裝的Component暴露出來
streamView.js
import ZYLiveBackGroundView from './nativeStreamView';//獲取原生暴露的Component
var myModule = NativeModules.ZYLiveBackGroundViewManager;//獲取原生暴露的module,其實(shí)都是從iOS的ZYLiveBackGroundViewManager這個(gè)類中獲取的
...//component的使用:
<ZYLiveBackGroundView style={styles.background}>
...
...//module的使用
myModule.onBack();
...
介紹完JS調(diào)用原生類后再介紹下原生調(diào)用RN的實(shí)現(xiàn),上訴基本是JS來調(diào)用原生的控件或方法的,但由于加入了聊天室的功能,融云IM SDK是用原生來實(shí)現(xiàn)的,當(dāng)收到新的消息是,SDK的回調(diào)也僅限于原生類,而我們需要在界面上顯示收到的這個(gè)消息,所以需要在原生收到消息時(shí)告知JS來更新界面,這也叫作消息分發(fā)。
附上官網(wǎng)實(shí)現(xiàn)方法:
iOS:http://facebook.github.io/react-native/docs/native-modules-ios.html#sending-events-to-javascript
Android:http://facebook.github.io/react-native/docs/native-modules-android.html#sending-events-to-javascript
首先我去查找了RCTEventEmitter這個(gè)消息分發(fā)類,發(fā)現(xiàn)這個(gè)類與RCTViewManager無關(guān),所以沒法再在同一個(gè)原生類中實(shí)現(xiàn)消息回傳RN了,只能新建一個(gè)專門用于實(shí)現(xiàn)調(diào)用JS的類。
iOS ,Android:
IMCloud
具體的使用方法官方文檔里已經(jīng)描述的很清楚了,這里就不重復(fù)了,直接看代碼就明白了。
四.打包
無論是iOS打包或安卓打包都需要將JS文件與圖片文件打包至bundle中,引入工程,但官網(wǎng)中并未提及這點(diǎn)(略坑),所以簡要說一下打包的步驟。
iOS打包步驟:
1.打包命令:到項(xiàng)目根目錄下執(zhí)行
react-native bundle --entry-file ./index.ios.js --bundle-output ./ios/index.ios.jsbundle --platform ios --assets-dest ./ios --dev false
輸出文件也可不放到iOS工程下,然后回到Xcode中,添加剛剛生成的
idex.ios.jsbundle與assets文件,其中assets的添加方式要選為Create Folder Reference,然后將Scheme修改為release,獲取jsbundle的方式改為:
//打包后獲取離線bundle
jsCodeLocation = [NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"index.ios.jsbundle" ofType:nil]];
就可以打包上傳iOS應(yīng)用了。