用 jpush-react-native 插件快速集成推送功能(Android 篇)




  • 概述

    jpush-react-native 是极光推送官方开发的 React Native 版本插件,可以快速集成推送功能。现在最新版本的 JPush SDK 分离了 JPush 及 JCore,让开发者可以分开集成 JMessage 及 JPush(以前 JMessage 包含了 JPush)。下面就来具体说一下如何快速集成以及使用 jpush-react-native 插件。


    安装

    打开终端,进入项目文件夹,执行以下命令:

    npm install jpush-react-native --save
    npm install jcore-react-native --save
    react-native link
    

    执行完 link 项目后可能会出现报错,这没关系,需要手动配置一下 build.gradle 文件。在 Android Studio 中打开你的项目,然后找到 app 或者你自己定义的需要集成 jpush-react-native 的模块,打开此模块下的 build.gradle 文件,做以下改动:

    app/build.gradle

    android {
        ...
        defaultConfig {
            applicationId "com.pushdemo" // 此处改成你在极光官网上申请应用时填写的包名
            ...
            manifestPlaceholders = [
                    JPUSH_APPKEY: "d4ee2375846bc30fa51334f5",   //在此替换你的APPKey
                    APP_CHANNEL: "developer-default"        //应用渠道号
            ]
        }
    }
    

    检查一下在 dependencies 中有没有加入 jpush-react-native 以及 jcore-react-native 这两个依赖,如果没有,则需要加上:

    dependencies {
        ...
        compile project(':jpush-react-native')
        compile project(':jcore-react-native')
        ...
    }
    

    接下来打开项目的 settings.gradle,看看有没有包含 jpush-react-native 以及 jcore-react-native,如果没有,则需要加上:

    include ':app', ':jpush-react-native', ':jcore-react-native'
    project(':jpush-react-native').projectDir = new File(rootProject.projectDir, '../node_modules/jpush-react-native/android')
    project(':jcore-react-native').projectDir = new File(rootProject.projectDir, '../node_modules/jcore-react-native/android')
    

    做完以上步骤,这时可以同步(sync)一下项目,然后应该可以看到 jpush-react-native 以及 jcore-react-native 作为 Library 项目导进来了。

    接下来打开模块的 MainApplication.java 文件,加入 JPushPackage:

    app/src.../MainApplication.java

        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<ReactPackage> getPackages() {
                return Arrays.<ReactPackage>asList(
                        new MainReactPackage(),
                        //加入 JPushPackage
                        new JPushPackage(SHUTDOWN_TOAST, SHUTDOWN_LOG)
                );
            }
        };
    

    然后在 MainActivity 中加入一些初始化代码即可:

    app/src.../MainActivity.java

    public class MainActivity extends ReactActivity {    
        ...
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            JPushInterface.init(this);
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            JPushInterface.onPause(this);
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            JPushInterface.onResume(this);
        }
    }
    

    这样就完成了所有的配置。接下来就可以在 JS 中调用插件提供的 API 了。

    使用

    收到推送

    添加了此事件后,在收到推送时将会触发此事件。

    example/react-native-android/push_activity.js

    ...
    import JPushModule from 'jpush-react-native';
    ...
    export default class PushActivity extends React.Component {
        componentDidMount() {
            JPushModule.addReceiveNotificationListener((map) => {
                console.log("alertContent: " + map.alertContent);
                console.log("extras: " + map.extras);
                // var extra = JSON.parse(map.extras);
                // console.log(extra.key + ": " + extra.value);
            });
    }
    
    点击推送

    在用户点击通知后,将会触发此事件。

    ...
    componentDidMount() {
        JPushModule.addReceiveOpenNotificationListener((map) => {
                console.log("Opening notification!");
                console.log("map.extra: " + map.key);
            });
    }
    

    高级应用

    修改 JPushModule 中收到点击通知的事件,可以自定义用户点击通知后跳转的界面(现在默认是直接启动应用),只需要修改一点点原生的代码:

    jpush-react-native/src.../JPushModule.java

    public static class JPushReceiver extends BroadcastReceiver {    
        public JPushReceiver() {        
            HeadlessJsTaskService.acquireWakeLockNow(mRAC);    
        }    
        
        @Override    
        public void onReceive(Context context, Intent data) {
        ...
        } else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(data.getAction())) {    
            Logger.d(TAG, "用户点击打开了通知");
            Intent intent = new Intent();
            intent.setClassName(context.getPackageName(), context.getPackageName() + ".MainActivity");
            intent.putExtras(bundle);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            // 如果需要跳转到指定的界面,那么需要同时启动 MainActivity 及指定界面(SecondActivity):
            // If you need to open appointed Activity, you need to start MainActivity and
            // appointed Activity at the same time.
            Intent detailIntent = new Intent();
            detailIntent.setClassName(context.getPackageName(), context.getPackageName() + ".SecondActivity");
            detailIntent.putExtras(bundle);
            Intent[] intents = {intent, detailIntent};
            // 同时启动 MainActivity 以及 SecondActivity
            context.startActivities(intents);
            // 或者回调 JS 的某个方法
        }
    }
    
    ...
    
     @ReactMethod
     public void finishActivity() {
         Activity activity = getCurrentActivity();
         if (activity != null) {
             activity.finish();
         }
     }
    

    如果修改了此处跳转的界面,需要在 Native 中声明一个 Activity,如 demo 中的 SecondActivity,而 SecondActivity 的界面仍然用 JS 来渲染。只需要改动一下 SecondActivity,让它继承自 ReactActivity 即可:

    example/android/app/src.../SecondActivity.java

    public class SecondActivity extends ReactActivity {
    
        @Override
        protected String getMainComponentName() {
            return "SecondActivity";
        }
    
    }
    

    然后使用上面返回的字符串注册一个 Component 即可:

    example/react-native-android/second.js

    'use strict';
    
    import React from 'react';
    import ReactNative from 'react-native';
    
    const {
      AppRegistry,
      View,
      Text,
      TouchableHighlight,
      StyleSheet,
      NativeModules,
    } = ReactNative;
    
    var JPushModule = NativeModules.JPushModule;
    
    
    export default class second extends React.Component {
      constructor(props) {
        super(props);
      }
    
      onBackPress = () => {
        let navigator = this.props.navigator;
        if (navigator != undefined) {
          this.props.navigator.pop();
        } else {
          console.log("finishing second activity");
          JPushModule.finishActivity();
        }
      }
    
      onButtonPress = () => {
        console.log("will jump to setting page");
        let navigator = this.props.navigator;
        if (navigator != undefined) {
          this.props.navigator.push({
            name: "setActivity"
          });
        } else {
    
        }
    
      }
    
      render() {
        return (
          <View>
            <TouchableHighlight
              style={styles.backBtn}
              underlayColor = '#e4083f'
              activeOpacity = {0.5}
              onPress = {this.onBackPress}>
              <Text>
                Back
              </Text>
            </TouchableHighlight>
            <Text
              style={styles.welcome}> 
              Welcome ! 
            </Text> 
            <TouchableHighlight underlayColor = '#e4083f'
              activeOpacity = {0.5}
              style = {styles.btnStyle}
              onPress = {this.onButtonPress}>
              <Text style={styles.btnTextStyle}>
                Jump To Setting page!
              </Text> 
            </TouchableHighlight>
            </View>
        );
      }
    }
    
    var styles = StyleSheet.create({
      backBtn: {
        padding: 10,
        marginTop: 10,
        marginLeft: 10,
        borderWidth: 1,
        borderColor: '#3e83d7',
        backgroundColor: '#3e83d7',
        borderRadius: 8,
        alignSelf: 'flex-start'
      },
      welcome: {
        textAlign: 'center',
        margin: 10,
      },
      btnStyle: {
        marginTop: 10,
        borderWidth: 1,
        borderColor: '#3e83d7',
        borderRadius: 8,
        backgroundColor: '#3e83d7',
        alignSelf: 'center',
        justifyContent: 'center'
      },
      btnTextStyle: {
        textAlign: 'center',
        fontSize: 25,
        color: '#ffffff'
      },
    });
    
    AppRegistry.registerComponent('SecondActivity', () => second);
    

    这样就完成了用户点击通知后的自定义跳转界面。

    接收自定义消息

    在用户收到自定义消息后触发。

    example/react-native-android/push_activity.js

     ...
        componentDidMount() {
            JPushModule.addReceiveCustomMsgListener((map) => {
                this.setState({
                    pushMsg: map.message
                });
                console.log("extras: " + map.extras);
        });
    ...
    
    
    得到 RegistrationId

    用户注册成功后(一般在用户启动应用后),如果订阅了这个事件,将会收到这个 registrationId。

    ...
        componentDidMount() {
            JPushModule.addGetRegistrationIdListener((registrationId) => {
                console.log("Device register succeed, registrationId " + registrationId);
            });
        }
    
    清除所有通知

    建议在用户退出前台后调用。

        ...
        componentWillUnmount() {
            console.log("Will clear all notifications");
            JPushModule.clearAllNotifications();
        }
    
    设置标签

    example/react-native-android/set_activity.js

        ...
        setTag() {
            if (this.state.tag !== undefined) {
                /*
                * 请注意这个接口要传一个数组过去,这里只是个简单的示范
                */      
                JPushModule.setTags(["VIP", "NOTVIP"], () => {
                    console.log("Set tag succeed");
                }, () => {
                    console.log("Set tag failed");
                });
            }
        }
    
    设置别名
        ...
        setAlias() {
            if (this.state.alias !== undefined) {
                JPushModule.setAlias(this.state.alias, () => {
                    console.log("Set alias succeed");
                }, () => {
                    console.log("Set alias failed");
                });
            }
        }
    

    以上就是插件提供的主要接口的示例。总的来说,配置和使用都比较简单,适合开发者快速集成推送功能。



  • 请求楼主知道如何实现App杀掉之后依然能接收到推送消息吗,目前好像只要将App杀掉,就无法接收了推送消息了,这样就失去了推送的意义了。



  • @第十三只眼睛 你好,如果你安装了其他集成了 JPush SDK 的应用,那么可以收到通知的。



  • @KenChoi ,您好:
    请问接收到推送的消息后,如何设置app图标上的数字角标?提醒有新消息收到。另外,若app进程被杀掉或重新启动手机,还能收到信息吗?角标还能更新吗?上一条您的回复没明白,难道让用户还要安个jpush的应用吗?用户怎么知道安装啊?
    我现在就是被接收消息的问题困扰很久了,麻烦您帮忙指点,谢谢!



  • @cnbeautifultime Android 没有设置角标的接口,iOS 有。


登录后回复