在接到需求後對如何實現進行了預研,發現有極光官網維護的 jpush-react-native 和 React Native 中文網維護的 react-native-jpush 供我們使用,我選擇的是 jpush-react-native。
一,相關版本信息
{
"name": "app",
"version": "0.0.1",
"private": true,
"scripts": {
"configureJPush": "node node_modules/jpush-react-native/JPushConfiguration.js",
"start": "node node_modules/react-native/local-cli/cli.js start",
"test": "jest"
},
"dependencies": {
"react": "16.3.1",
"react-native": "0.54.4",
"react-navigation": "^1.0.0-beta.19",
"jpush-react-native": "^2.1.7",
……
},
"devDependencies": {
……
},
"jest": {
……
}
}
二、添加極光組件
運行命令:yarn add jpush-react-native 或 npm install jpush-react-native --save
並鏈接原生庫:react-native link jpush-react-native
三、iOS端手動配置
3.1 打開 iOS 工程,會發現RCTJPushModule.xcodeproj 工程會自動添加到 Libraries 目錄裏面
在 iOS 工程 target 的 Build Phases->Link Binary with Libraries 中加入如下庫
libz.tbd
CoreTelephony.framework
Security.framework
CFNetwork.framework
CoreFoundation.framework
SystemConfiguration.framework
Foundation.framework
UIKit.framework
UserNotifications.framework
libresolv.tbd
3.2 在 iOS 工程中設置 TARGETS-> BUILD Phases -> LinkBinary with Libraries 找到 UserNotifications.framework 把 status 設爲 optional
3.3 在 iOS 工程中如果找不到頭文件可能要在 TARGETS-> BUILD SETTINGS -> Search Paths -> Header Search Paths 添加如下路徑 $(SRCROOT)/../node_modules/jpush-react-native/ios/RCTJPushModule
3.4 在 xcode8 之後需要點開推送選項: TARGETS -> Capabilities -> Push Notification 設爲 on 狀態
3.5 在 AppDelegate.h 文件中 填寫如下代碼,這裏的的 appkey、channel、和 isProduction 填寫自己的
static NSString *appKey = @""; //填寫appkey
static NSString *channel = @""; //填寫channel 一般爲nil
static BOOL isProduction = false; //填寫isProdurion 平時測試時爲false ,生產時填寫true
3.6 在AppDelegate.m 的didFinishLaunchingWithOptions 方法裏面添加如下代碼
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {
//可以添加自定義categories
[JPUSHService registerForRemoteNotificationTypes: (UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert) categories:nil];
} else {
//iOS 8以前 categories 必須爲nil
[JPUSHService registerForRemoteNotificationTypes: (UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeSound|UIRemoteNotificationTypeAlert) categories:nil];
}
[JPUSHService setupWithOption:launchOptions appKey:appKey channel:channel apsForProduction:isProduction];
}
在AppDelegate.m 的didRegisterForRemoteNotificationsWithDeviceToken 方法中添加 [JPUSHService registerDeviceToken:deviceToken];
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
[JPUSHService registerDeviceToken:deviceToken];
}
爲了在收到推送點擊進入應用能夠獲取該條推送內容需要在 AppDelegate.m 的didReceiveRemoteNotification 方法裏面添加
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
[[NSNotificationCenter defaultCenter] postNotificationName:kJPFDidReceiveRemoteNotification object:userInfo];
}
注意:這裏需要在兩個方法裏面添加方法,一個是iOS7以前的、一個是iOS7即以後的,如果AppDelegate.m 沒有這個兩個方法則直接複製這兩個方法;
在 iOS10 的設備則可以使用JPush 提供的兩個方法;如下所示
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
// 取得 APNs 標準信息內容
[[NSNotificationCenter defaultCenter] postNotificationName:kJPFDidReceiveRemoteNotification object:userInfo];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification: (NSDictionary *)userInfo fetchCompletionHandler:(void (^) (UIBackgroundFetchResult))completionHandler {
[[NSNotificationCenter defaultCenter] postNotificationName:kJPFDidReceiveRemoteNotification object:userInfo];
}
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger))completionHandler {
// Required
NSDictionary * userInfo = notification.request.content.userInfo;
if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
[JPUSHService handleRemoteNotification:userInfo];
[[NSNotificationCenter defaultCenter] postNotificationName:kJPFDidReceiveRemoteNotification object:userInfo];
}
completionHandler(UNNotificationPresentationOptionAlert); // 需要執行這個方法,選擇是否提醒用戶,有Badge、Sound、Alert三種類型可以選擇設置
}
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
NSDictionary * userInfo = response.notification.request.content.userInfo;
if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
[JPUSHService handleRemoteNotification:userInfo];
[[NSNotificationCenter defaultCenter] postNotificationName:kJPFDidReceiveRemoteNotification object:userInfo];
}
completionHandler(); // 系統要求執行這個方法
}
3.7 貼兩張圖
四、Android端手動配置
4.1 使用 Android Studio 打開 React Native 項目下的 Android 應用,修改 settings.gradle 配置。
include ':app', ':jpush-react-native'
project(':jpush-react-native').projectDir = new File(rootProject.projectDir, '../node_modules/jpush-react-native/android')
4.2 修改app 下的 AndroidManifest 配置,將 jpush 相關的配置添加到這個文件中。
<application
android:name="com.pateo.ma.windlink.MainApplication"
android:allowBackup="true"
android:label="@string/app_name"
android:icon="@mipmap/logo"
android:theme="@style/AppTheme">
<activity
android:name="com.pateo.ma.windlink.MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:screenOrientation="portrait"
android:theme="@android:style/Theme.Black.NoTitleBar"
android:windowSoftInputMode="adjustPan|stateHidden">
……
</application>
4.3 修改 app 下的 build.gradle 配置
your react native project/android/app/build.gradle
android {
defaultConfig {
applicationId "yourApplicationId"
...
manifestPlaceholders = [
JPUSH_APPKEY: "yourAppKey", //在此替換你的APPKey
APP_CHANNEL: "developer-default" //應用渠道號,默認就好
]
}
}
……
dependencies {
compile fileTree(dir: "libs", include: ["*.jar"])
compile project(':jpush-react-native')
compile "com.facebook.react:react-native:+" // From node_modules
}
// 將此處的 yourApplicationId 替換爲你的項目的包名;yourAppKey 替換成你在官網上申請的應用的 AppKey。到此爲止,配置完成
4.4 現在重新 同步 一下項目,應該能看到 jpush-react-native 作爲一個 android Library 項目導進來了
4.5 打開 app 下的 MainActivity,路徑:android/app/src/main/java/……/MainActivity.java,在 ReactInstanceManager 的 build 方法中加入 JPushPackage:
// 導入命名空間
import cn.jpush.android.api.JPushInterface;
// 添加方法
@Override
protected void onResume() {
super.onResume();
JPushInterface.onResume(this);
}
@Override
protected void onPause() {
super.onPause();
JPushInterface.onPause(this);
}
4.6 打開 app 下的 MainApplication,路徑:android/app/src/main/java/……/MainApplication.java,加入 JPushPackage:
private boolean SHUTDOWN_TOAST = false;
private boolean SHUTDOWN_LOG = false;
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
protected boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List getPackages() {
return Arrays.asList(
MainReactPackage(),
new JPushPackage(SHUTDOWN_TOAST, SHUTDOWN_LOG)
);
}
};
五、在RN上進行的操作
5.1 普通推送
componentDidMount() {
// ---------------------------------android start---------------------------------
JPushModule.addReceiveCustomMsgListener((message) => {
// 這是默認的通知消息
// this.setState({pushMsg:message});
});
JPushModule.addReceiveNotificationListener((map) => {
// 自定義推送的消息
// console.log("alertContent: " + map.alertContent);
// extra是可選配置上的附件字段
// console.log("extras: " + map.extras);
var message = JSON.parse(map.extras);
this.storeDB(message); // 我這裏是把內容存在了數據庫裏面,你可以把這裏的message放到state裏面顯示出來
// 這裏面解析json數據,並存在數據庫中,同時顯示在通知欄上
})
// 點擊通知進入應用的主頁,相當於跳轉到制定的頁面
JPushModule.addReceiveOpenNotificationListener((map) => {
// console.log("Opening notification!");
this.props.navigator.replace({name: "HomePage",component:HomePage});
})
// ---------------------------------android end---------------------------------
// ---------------------------------ios start---------------------------------
NativeAppEventEmitter.addListener(
'ReceiveNotification',
(message) => {
// 下面就是發送過來的內容,可以用stringfy打印發來的消息
console.log("content: " + JSON.stringify(message));
// 下面的json就是我在極光推送上的附件字段內容就是上面的log打印出來的東西
// {
// "_j_msgid": 4572771355,
// "content": "日誌第一天",
// "time": "2016-11-18/13:11:09",
// "aps": {
// "sound": "default",
// "badge": 1,
// "alert": "測試ios1"
// },
// "name": "劉成",
// "age": "28",
// "性別": "男",
// "qq":"674668211",
// "手機號":"674668211",
// }
// console.log("_j_msgid:" + message._j_msgid); // 這個是極光的消息id
// console.log("content:" + message.content); // 這是標題
// console.log("aps:" + message.aps.sound); // 這是聲音
// console.log("aps:" + message.aps.badge); // 這是上標
// console.log("aps:" + message.aps.alert); // 這是發送通知的主內容 this.storeDB(message);
// }
// );
// ---------------------------------ios end---------------------------------
}
// 最後在組件卸載的時間取消監聽
componentWillUnmount() {
JPushModule.removeReceiveCustomMsgListener();
JPushModule.removeReceiveNotificationListener();
BackAndroid.removeEventListener('hardwareBackPress');
NativeAppEventEmitter.removeAllListeners();
DeviceEventEmitter.removeAllListeners();
}
(1)android的推送內容都在message.content裏面,附加的數據在message.extras,message就是發送過來的消息內容:addReceiveNotificationListener;
如果你沒有附加的消息,只是顯示消息內容,用這個方法就行了:addReceiveCustomMsgListener;
如果你要點擊通知打開某個應用,用:addReceiveOpenNotificationListener
(2)ios的要用到註冊監聽事件:NativeAppEventEmitter.addListener,消息內容都在message裏面,可以把這裏的message
放到state裏面顯示出來。
5.2 別名推送
setAlias有三個參數,第一個是你要推送的別名,要註冊到極光的,第二和第三個分別是設置成功的回調、設置失敗的回調。
import JPushModule from 'jpush-react-native';
'您的別名' !== '' ? (JPushModule.setAlias('您的別名',this.success,this.fail)):null
success=()=>{
NativeAppEventEmitter.addListener( 'ReceiveNotification', (message) =>{JPushModule.setBadge(0,function(){
// console.log(message)
})} );
// ---------------------------------android start---------------------------------
JPushModule.addReceiveCustomMsgListener((message) => {
// 這是默認的通知消息
// console.log(message)
});
JPushModule.addReceiveNotificationListener((map) => {
// var message = JSON.parse(map.extras);
});
// 點擊通知進入應用的主頁
JPushModule.addReceiveOpenNotificationListener((map) => {
// ……
})
// ---------------------------------android end---------------------------------
}
fail=()=>{
}