最近在寫(xiě)信鴿推送中間遇到一些坑,不過(guò)好在都逐步解決了,目前寫(xiě)一下做個(gè)說(shuō)明。由于極光推送官方做了相關(guān)RN代碼,有需要的同學(xué)也可以參考他們的步驟來(lái)一步步完成自己推送的RN模塊.下面來(lái)說(shuō)說(shuō)我的開(kāi)發(fā)過(guò)程吧:
首先我們都得先用RN創(chuàng)建個(gè)工程
iOS信鴿推送 RN模塊開(kāi)發(fā)
1. iOS先新建一個(gè)靜態(tài)庫(kù)
導(dǎo)入信鴿推送需要的libXG-SDK.a和XGPush.h文件,信鴿推送iOS配置和方法說(shuō)明參考官方.
然后新建iOS類(lèi)文件,用于iOS和RN交互,將靜態(tài)庫(kù)工程導(dǎo)入RN功能下編寫(xiě)相關(guān)功能。
我XGPush靜態(tài)庫(kù)的結(jié)構(gòu)如下:

強(qiáng)調(diào)一點(diǎn):就是類(lèi)名命名規(guī)范,如果是帶你新建的類(lèi)帶有前綴RCT和RK的話,RN引用導(dǎo)入的時(shí)候默認(rèn)忽略的,比如我這個(gè)RCTXGPushModule,RN里面引用的時(shí)候默認(rèn)就是NativeModules.XGPushModule。
這一點(diǎn)可以在RN源碼里面RCTBridge的RCTBridgeModuleNameForClass方法找到說(shuō)明

2. 下面就是iOS原生模塊和RN交互了
具體交互說(shuō)可參考RN中國(guó)社區(qū)網(wǎng)站原生模塊
- 按照說(shuō)明配置導(dǎo)入相關(guān)RN頭文件,繼承類(lèi)RCTEventEmitter,遵循相關(guān)協(xié)議
我的.h文件內(nèi)容如下RCTXGPushModule.h - .m文件就是和RN交互相關(guān)
有幾點(diǎn)說(shuō)明:
/**
為了實(shí)現(xiàn)RCTBridgeModule協(xié)議,需要包含RCT_EXPORT_MODULE()宏。
這個(gè)宏也可以添加一個(gè)參數(shù)用來(lái)指定在Javascript中訪問(wèn)這個(gè)模塊的名字。
如果你不指定,默認(rèn)就會(huì)使用這個(gè)Objective-C類(lèi)的名字
*/
RCT_EXPORT_MODULE();
加上單例方法保持對(duì)象唯一,要不然有可能會(huì)產(chǎn)生崩潰和其他問(wèn)題
//保持對(duì)象唯一 使用單例
+ (id)allocWithZone:(NSZone *)zone {
static RCTXGPushModule *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [super allocWithZone:zone];
});
return sharedInstance;
}
直接用對(duì)象發(fā)送事件就會(huì)崩潰,類(lèi)似的采用通知發(fā)送事件 原因的RN先生成XGPushModlue對(duì)象方可發(fā)送事件
否則當(dāng)用戶操作觸發(fā)時(shí)調(diào)用sendEventWithName報(bào)錯(cuò)bridge is not set,
所以參考極光推送全部采用通知發(fā)送事件,類(lèi)似

導(dǎo)入方法提供給js調(diào)用用RN的RCT_EXPORT_METHOD,可以回調(diào)參數(shù)過(guò)去。使用方法類(lèi)似如下:

最后就是調(diào)用RN發(fā)送事件方法了
- (void)sendEventWithName:(NSString *)eventName body:(id)body
andriod 信鴿推送 RN模塊開(kāi)發(fā)
由于我沒(méi)做過(guò)安卓開(kāi)發(fā),所以安卓遇到了很多坑,逐步才一一解決。
- 首先使用Android Studio打開(kāi)RN創(chuàng)建的安卓工程,新建module
- 現(xiàn)在我們需要建立安卓XGPush的RN的module模塊

我創(chuàng)建的module模塊名稱(chēng)是
xgpush,創(chuàng)建完成結(jié)構(gòu)如下
-
導(dǎo)入信鴿推送安卓模塊需要的文件
信鴿推送安卓SDK下載地址
在新建的module的libs文件下導(dǎo)入信鴿推送jar文件
tmp4bc73aa1.png
在新建的module的src/main下新建文件夾jiniLIbs,導(dǎo)入信鴿so文件tmp69793686.png 在module的build.gradle里面配置依賴
dependencies {
//implementation fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.facebook.react:react-native:+'
compile files('libs/Xg_sdk_v3.2.3_20180403_1839.jar')
compile files('libs/wup-1.0.0.E-SNAPSHOT.jar')
compile files('libs/jg_filter_sdk_1.1.jar')
compile files('libs/mid-core-sdk-4.0.6.jar')
}
- 工程依賴xgpush
屏幕快照 2018-07-11 下午3.21.32.png
在主工程目錄下的settings.gradle導(dǎo)入xgpush,就是新建的module名
include ':app', ':xgpush'
- 信鴿推送安卓SDK與RN交互
我這里java模塊如下:
tmp45367cc4.png
LocalInnerMessageReceiver本地通知,接受者用于接受信鴿發(fā)送本地通知的.沒(méi)什么好說(shuō)的
LocalInnerMessageReceiver
XGMessageReceiver用于監(jiān)聽(tīng)信鴿推送相關(guān)事件,
官方參考地址

XGPushModule用于安卓和RN交互很重要
RN與安卓原生交互可 參考
強(qiáng)調(diào)幾點(diǎn):
- 一個(gè)原生模塊是一個(gè)繼承了
ReactContextBaseJavaModule的Java類(lèi) - 一個(gè)原生模塊需要監(jiān)聽(tīng)聲明RN周期的,可實(shí)現(xiàn)接口
LifecycleEventListener,然后需要在構(gòu)造函數(shù)中注冊(cè)一個(gè)監(jiān)聽(tīng)函數(shù):
reactContext.addLifecycleEventListener(this);
-
可在構(gòu)造函數(shù)里面實(shí)現(xiàn)監(jiān)聽(tīng)和進(jìn)行初始化等操作
tmp3089154e.png ReactContextBaseJavaModule要求派生類(lèi)實(shí)現(xiàn)getName方法。這個(gè)函數(shù)用于返回一個(gè)字符串名字,這個(gè)名字在JavaScript端標(biāo)記這個(gè)模塊。這里我們把這個(gè)模塊叫做
RNGFXGPush,這樣就可以在JavaScript中通過(guò)React.NativeModules.RNGFXGPush訪問(wèn)到這個(gè)模塊
@Override
public String getName() {
return "RNGFXGPush";
}
注意:模塊名前的RCT前綴會(huì)被自動(dòng)移除。所以如果返回的字符串為RCTRNGFXGPush,在JavaScript端依然可以通過(guò)React.NativeModules.RNGFXGPush訪問(wèn)到這個(gè)模塊。
- 要導(dǎo)出一個(gè)方法給JavaScript使用,Java方法需要使用注解
@ReactMethod
類(lèi)似代碼:
/*
* 設(shè)置是否開(kāi)啟信鴿Debug日志
* */
@ReactMethod
public void enableDebug(Boolean enable) {
XGPushConfig.enableDebug(this.context,enable);
}
/*
* 注冊(cè)信鴿推送
* */
@ReactMethod
public void registerPush() {
XGPushManager.registerPush(this.context, new XGIOperateCallback() {
@Override
public void onSuccess(Object data, int flag) {
Log.d("XGPush", "注冊(cè)成功:" + data);
sendEvent(RNGFXGPushRegisterEvent,data);
}
@Override
public void onFail(Object data, int errCode, String msg) {
Log.d("XGPush", "注冊(cè)失敗,錯(cuò)誤碼:" + errCode + ",錯(cuò)誤信息:" + msg);
WritableMap params = Arguments.createMap();
params.putInt("errCode", (int) errCode);
params.putString("msg",msg);
sendEvent(RNGFXGPushRegisterEvent,params);
}
});
}
- 發(fā)送事件 最簡(jiǎn)單的辦法就是通過(guò)
RCTDeviceEventEmitter,這可以通過(guò)ReactContext來(lái)獲得對(duì)應(yīng)的引用,像這樣:
tmp65d85024.png
-
在Java這邊要做的最后一件事就是注冊(cè)這個(gè)模塊。我們需要在應(yīng)用的Package類(lèi)的createNativeModules方法中添加這個(gè)模塊。如果模塊沒(méi)有被注冊(cè),它也無(wú)法在JavaScript中被訪問(wèn)到。
XGPushPackage
這個(gè)package需要在MainApplication.java文件的getPackages方法中提供。這個(gè)文件位于你的react-native
應(yīng)用文件夾的android目錄中。具體路徑是: android/app/src/main/java/com/your-app-name/MainApplication.java.

- 打開(kāi)主工程 Androidmanifest.xml,添加信鴿安卓配置
配置詳情參考官方
我的配置部分截圖
如果配置沒(méi)有問(wèn)題,運(yùn)行RN代碼交互成功,就會(huì)出現(xiàn)和我類(lèi)似的安卓信鴿推送效果
tmp2785e192.png
代碼可參考我的Demo










