• 摘要 2015年是React Native发展的一年,2016年必定是React Native蓬勃的一年!2016年React Native很可能成为最为成功的开源技术之一。为什么React Native这么火呢?那么React Native相比H5、Native又有哪些优势呢?...

    @王利华,vczero

    “存在即合理”。凡是存在的,都是合乎规律的。任何新事物的产生总要的它的道理;任何新事物的发展总是有着取代旧事物的能力。React Native来的正是时候,一则是因为H5发展到一定程度的受限;二则是移动市场的迅速崛起强调团队快速响应和迭代;三则是用户的体验被放大,用户要求极致的快感,除非你牛x(例如:12306最近修改手机号需要用户自己发短信接收验证码)。
    以下简单的介绍下H5、React Native、Native的含义:

    最近三四年间,国内外的前端与全栈开发者社区都在坚持不懈地追寻使用JavaScript与HTML、CSS技术体系开发App内场景的核心工程技术。这种技术,在国内很多公司与团队中,被通称为H5。——童遥

    这段是取自童老师给小二我新书作的序,没有断章取义的意思。很清楚,H5并不是狭义的HTML5新标签和API,而是工程化的“In App” technology。

    iOS/Android ——原生应用(都懂得,不解释)。

    React Native —— React & Native ,应运而生!

    一、React Native的出现

    React Native的出现,似乎是扛起的反H5的旗子。就像当年Facebook放弃H5,全部转向Native一样。这一点,我们需要认同和保持高度的清醒。那么,React Native是否又是在吞食Native的领地呢?技术的发展,是用户风向标的导向起的作用。任何一门技术的出现,都是当时用户需求的体现。

    我们应该从以下几点看待React Native的出现。

    "鉴往知来"——从过去的教训中总结经验,从用户的角度开拓未来
    “HTML5差强人意,但是与原生应用相比还是有些差距”——为了更高的追求! 用户体验!
    “人才宝贵,快速迭代”——Web开发者相对较多,寻找平衡点
    “跨平台!跨平台!跨平台!”——单一技术栈
    “xx是世界上最好的语言” ——工程学的范畴,没有最好,只有最适合

    HTML5 vs React Native ? HTML5 : React Native
    结论(React Native):
    1、原生应用的用户体验
    2、跨平台特性
    3、开发人员单一技术栈
    4、上手快,入门容易
    5、社区繁荣

    二、3款应用效果

    注:以下所有对比均在iOS平台下



    上面3张图片,如果去掉第一张图的“HybirdApp”的字样,是否分得清哪个是React Native开发?哪个是Native应用。
    你的第一感觉是什么?

    三、工程方案

    为了评估3种方案的技术优势和弱势。我们需要开发功能大致相似的App。这里,我们使用了“豆瓣”的API来开发“豆搜”应用。该应用能够搜索“图书”、“音乐”、“电影”。想当年,豆瓣以“图书评论”走红,尤其是12年当红!豆瓣是一个清新文艺的社区,一个“慢公司”。最近有一则网传消息,注意是网传——“传京东投1.5亿美元控股豆瓣”。今天,不聊豆瓣,我们要聊一个工程化的问题。

    我们需要将3款App的功能做到一致,同时需要保持技术要点一致。比如React Native这里使用了TabBar,那么Native我们也必须使用TabBar。简单而言就是:功能一致,组件 & API一致。我们功能如下图所示:

    1、H5方案
    在H5/Hybird应用中,我们使用AngularJS开发单页webApp,然后将该WebApp内嵌入到iOS WebView中,在iOS代码中,我们使用Navigation稍微控制下跳转。
    WebApp地址:http://vczero.github.io/search/html/index.html
    WebApp项目地址:https://github.com/vczero/search (很简单的一个项目)
    H5/Hybird项目地址:https://github.com/vczero/search_Hybird

    2、React Native
    在React Native中,封装必要的功能组件。
    项目地址:https://github.com/vczero/React-Dou。
    项目结构如下图:

    3、Native(iOS)
    使用React Native大致相同的组件开发App,不使用任何第三方库,代码布局。
    项目地址:https://github.com/vczero/iOS-Dou

    四、对比分析

    很多时候,新技术的采用最希望看到的是数据,而不是简单说“用户体验棒,开发效率高,维护成本低”。不过,生活中也有这样的同学,知一二而能窥全貌。当然,本人生性胆小,也没有那么多的表哥和隔壁的老王,所以不敢早下定论,不敢太放肆。赵本山在《大笑江湖》中有句名言“May the force be with you”(别太放肆,没什么用)。因此,从以下几个方面做一个简单的对比。

    ----------提纲------------

    1、开发方式

    (1)代码结构
    (2)UI布局
    (3)UI截面图
    (4)路由/Navigation
    (5)第三方生态链

    2、性能 & 体验

    (1)内存
    (2)CPU
    (3)动画
    (4)安装包体积
    (5)Big ListView
    (6)真机体验

    3、更新 & 维护

    (1)更新能力
    (2)维护成本
    ----------提纲------------

    1、开发方式

    很多人说React Native的代码不好看,不好理解。那是因为前端工程师都熟悉了Web的开发方式。怎么解决这个问题呢,可以先看看iOS代码,断定不熟悉iOS的同学心里会默念“一万匹**马奔腾”。那时候,你再看React Native,你会觉得使用React Native开发App是件多么美好的事!OK,我们先来看下三者在开始“一款简单App”的代码结构。
    (1)代码结构
    H5/Hybird的开发模式,我们需要维护3套代码,两套是Native(iOS/Android)代码,一套是WebApp版本。这里,我们使用AngularJS作为WebApp单页开发框架。如下图所示。

    在React Native中,同样需要关注部分的Native代码,但是大部分还是前端熟悉的JavaScript。在“豆搜”应用中,代码结构如下:

    在Native开发中,更加强调Native开发者的能力。平台是:iOS/Android。

    结论:从前端角度而言,React Native跨平台特性,不要开发者深入的了解各平台就能开发一款高效App。同时,语言层面而言,JavaScript运用很广泛,入门门槛相对较低。React Native虽然抛弃了MVC分离实践,但是从业务角度而言,更为合理。一切而言:对前端,对移动领域是利好的消息。

    (2)UI布局
    “面容姣好”,合理的UI却总是跟着时间在变。那么UI布局就不是小事。
    Web开发布局目前大多是 DIV + CSS。
    React Native的布局方式是Flexbox。

       //JSX
      <ScrollView style={styles.flex_1}>
        <View style={[styles.search, styles.row]}>
          <View style={styles.flex_1}>
            <Search placeholder="请输入图书的名称" onChangeText={this._changeText}/>
          </View>
          <TouchableOpacity style={styles.btn} onPress={this._search}>
            <Text style={styles.fontFFF}>搜索</Text>
          </TouchableOpacity>
        </View>
        {
          this.state.show ?
          <ListView
            dataSource={this.state.dataSource}
            renderRow={this._renderRow}
            />
          : Util.loading
        }
      </ScrollView>
      //样式
      var styles = StyleSheet.create({
          flex_1:{
            flex:1,
            marginTop:5
          },
          search:{
            paddingLeft:5,
            paddingRight:5,
            height:45
          },
          btn:{
            width:50,
            backgroundColor:'#0091FF',
            justifyContent:'center',
            alignItems:'center'
          },
          fontFFF:{
            color:'#fff'
          },
          row:{
            flexDirection:'row'
          }
        });        

    而Native布局就有种让你想吐的感觉,尤其是iOS的布局。这里不是指采用xib或者Storyboard,而是单纯的代码,例如添加一个文本:

    UILabel *publisher = [[UILabel alloc]init];
    publisher.frame = CGRectMake(bookImgWidth + 10, 50, 200, 30);
    publisher.textColor = [UIColor colorWithRed:0.400 green:0.400 blue:0.435 alpha:1];
    publisher.font = [UIFont fontWithName:@"Heiti TC" size:13];
    publisher.text = obj[@"publisher"];
    [item addSubview:publisher];           

    总结:React Native既综合了Web布局的优势,采用了FlexBox和JSX,又使用了Native原生组件。比如我们使用一个文本组件。
    <Text style={{width:100;height:30;backgroundColor:'red'}}>测试</Text>

    (3)UI截面图
    Hybrid方式截面图

    可以看到第一层列表页是完整的布局,实际上这就是Web页面;而第二层灰色的是Native的WebView组件。
    iOS UI截面图


    可以看到Native页面的组件特别多,即使是列表页,其中某一项都是一个组件(控件)。

    当然,我们就会想,能够完全调用原生组件呢?那样性能是否更好?
    React Native UI截面图


    可以清楚的看到React Native调用的全部是Native组件。并且层次更深,因为React Native做了组件的封装。如上图,蓝色边框的就是RCTScrollView组件。

    (4)路由/Navigation
    在Web单页面应用中,路由由History API实现。
    而React Native采用的路由是原生的UINavigationController导航控制器实现。
    React Native NavigatorIOS组件封装程度高;Navigator可定制化程度高。
    Navigator方法如下:

    getCurrentRoutes() - returns the current list of routes
    jumpBack() - Jump backward without unmounting the current scene
    jumpForward() - Jump forward to the next scene in the route stack
    jumpTo(route) - Transition to an existing scene without unmounting
    push(route) - Navigate forward to a new scene, squashing any scenes that you could jumpForward to
    pop() - Transition back and unmount the current scene
    replace(route) - Replace the current scene with a new route
    replaceAtIndex(route, index) - Replace a scene as specified by an index
    replacePrevious(route) - Replace the previous scene
    immediatelyResetRouteStack(routeStack) - Reset every scene with an array of routes
    popToRoute(route) - Pop to a particular scene, as specified by its route. All scenes after it will be unmounted
    popToTop() - Pop to the first scene in the stack, unmounting every other scene         

    相对Native而言,这些接口更Native还是很相似的。

    //iOS UINavigationController  
    //相对Web而言,不用自己去实现路由,并且路由更加清晰         
    [self.navigationController pushViewController:detail animated:YES];

    "豆搜" WebApp路由(基于AngularJS)如下:

    "豆搜" React Native版本导航如下:

    "豆搜" iOS版本导航代码如下:

    总结:React Native封装的导航控制更容易理解。

    (5)第三方生态链
    “我的是我的,你的也是我的。 ”——我不是“疯狂女友”,我是React Native!
    我们缺少“城市列表”组件,OK,使用JSX封装一个;觉得性能太低,OK,基于React Native方案封装一个原生组件。
    这个iOS图表库不错,拿来用呗! => 完美!
    这一切都是基于React Native提供的模块扩展方案。
    所以说:iOS第三方库 + 部分JavaScript库 = React Native 生态库

    2、性能 & 体验

    我们都很关注一款App性能。因此测试和体验App的性能很重要。以下测试,都是基于相同的case。
    测试平台:模拟器,iphone6,iOS8.4
    (1)内存
    首先,我们来看下Native应用占用的内存情况。一开始,原生应用启动后,占用内存是20~25M;针对相同的case,跑了2min,结果如下图:

    可以看出,峰值是87.9M,均值是72M;内存释放比较及时。

    我们再来看下Hybird App的情况。App已启动,占用内存35~55M;同样,跑了2min以上,结果如下图:

    可以看出,峰值在137.9M,因为整个应用在WebView中,内存释放不明显,存在缓存。

    最后,看下React Native的情况。App启动占用内存35~60M,同样跑2min以上,结果如下图:

    可以看出,峰值在142M,内存相对释放明显。

    总结:React Native和Web View在简单App上相差不大。二者主要:内存消耗主要是在网页数据上。

    (2)CPU
    我们可以看一下Native应用程序CPU的情况,最高值在41%。

    Hybird App的最高值在30%。

    React Native的最高值在34%。

    总结:CPU使用率大体相近,React Native的占用率低于Native。

    (3)动画
    React Native提供了Animated API实现动画。简单效果,基本OK。个人觉得React Native不适合做游戏,尤其布局能力。
    Native Animation提供UIView动画
    H5/Hybird:采用js动画能力
    总结:React Native Animated API / 封装Native动画库 可以满足基本需求

    (4)安装包体积
    Hybird App:
    34(App壳) + 5(HTML) + 125(Angular) + 29(An-route) + 6(min.js) + 4(min.css) = 203 KB。

    React Native:
    不含bundle: 843KB
    含bundle: 995KB

    Native
    83KB

    React Native框架包大小
    843(不含bundle) – 32(Hybird_app空壳,初识项目) = 811KB

    相比快速迭代和热更新,比Native多了811KB一点都不重要,我们将图片素材、静态资源线上更新缓存起来即可减少很多体积。
    总结:牺牲一点体积,换更大的灵活性!(世界上哪有那么美的事,除非丑,就会想得美,:) )。

    (5)Big ListView & Scroll 性能
    循环列表项500次: H5页面惨不忍睹
    React Native还可以接受
    Native 采用UITabView更高效,因为不渲染视图外部分。

    (6)真机体验
    机型:iphone4s,iOS7
    Native > React Native > Hybird
    如果非要给个数字的话,那我个人主观感受是:
    Native: 95%+ 流畅度
    React Native: 85~90% 流畅度
    H5/Hybird: 70% 流畅度

    总结:Native/React Native的体验相对而言更流畅。

    3、更新 & 维护

    (1)更新能力
    H5/Hybird: 随时更新,适合做营销页面,目前携程一些BU全部都是H5页面;但是重要的部分还是Native。
    React Native:React Native部分可以热更新,bug及时修复。
    Native:随版本更新,尤其iOS审核严格,需要测试过关,否则影响用户。

    (2)维护成本
    H5/Hybird: Web代码 + iOS/Android平台支持
    React Native:可以一个开发团队 + iOS/Android工程师;业务组件颗粒度小,不用把握全局即可修改业务代码。
    Native:iOS/Android开发周期长,两个开发团队。

    总结:React Native 统一了开发人员技术栈,代码维护相对容易。

    五、综合

    1、开发方式

    (1)代码结构: React Native更为合理,组件化程度高
    (2)UI布局:Web布局灵活度 > React Native > Native
    (3)UI截面图:React Native使用的是原生组件,
    (4)路由/Navigation:React Native & Native更胜一筹
    (5)第三方生态链:Native modules + js modules = React Native modules

    2、性能 & 体验

    (1)内存:Native最少;因为React Native含有框架,所以相对较高,但是后期平稳后会优于Native。
    (2)CPU:React Native居中。
    (3)动画:React Native动画需求基本满足。
    (4)安装包体积:React Native框架打包后,811KB。相比热更新,可以忽略和考虑资源规划。
    (5)Big ListView
    (6)真机体验:Native >= React Native > H5/Hybrid

    3、更新 & 维护

    (1)更新能力: H5/Hybird > React Native > Native
    (2)维护成本: H5/Hybird <= React Native < Native

    React Native定制难度相比Native有些大;但是具备跨平台能力和热更新能力。
    最后硬广一下我的书:


    展开全文
  • react-native-firebase 通知

    2018-07-02 17:19:13
    通知简介React Native Firebase的通知模块支持远程(FCM)和本地通知。远程通知Firebase云消息传递(FCM)允许您的应用程序远程显示通知。为了使事情变得简单易懂,我们将React Native Firebase功能明确划分为仅限...

    通知简介

    React Native Firebase的通知模块支持远程(FCM)和本地通知。

    远程通知

    Firebase云消息传递(FCM)允许您的应用程序远程显示通知。为了使事情变得简单易懂,我们将React Native Firebase功能明确划分为仅限数据和通知消息。

    远程通知:

    • 用于在设备上显示可见通知。
    • 包含可选的数据有效负载(键/值对的映射),供应用程序使用(如果它位于前台),或者随后打开通知。 如果未打开通知,则此数据永远不会对应用程序可用。
    • 被移动设备的操作系统拦截。
    • 当应用程序处于后台或关闭时,将传送到通知托盘。

    React Native Firebase通知模块处理仅通知和通知+数据FCM远程消息。
    有关仅限数据的FCM消息,请参阅消息传递模块

    远程通知的行为如下:

     应用程序在前台应用程序在后台应用关闭
    Android的onNotification 触发onNotificationOpened 如果点击通知则触发getInitialNotification 如果点击通知并打开应用程序,则会填充
    iOS版onNotification 触发onNotificationDisplayed如果content_available设置为true 

    onNotificationOpened触发通知,则触发
    getInitialNotification 如果点击通知并打开应用程序,则会填充
    笔记没有向用户显示可见通知,您可以手动显示通知该通知由移动设备的OS呈现给用户该通知由移动设备的OS呈现给用户

    本地通知

    Android和IOS都支持在本地触发应用程序通知的功能。这些可以立即显示,也可以安排在以后显示。

    通知模块处理所有本地通知。

    计划的通知行为如下:


    应用程序在前台应用程序在后台应用关闭
    Android的onNotification 触发onNotificationOpened 如果点击通知则触发getInitialNotification 如果点击通知并打开应用程序,则会填充
    iOS版onNotification 触发onNotificationOpened 如果点击通知则触发getInitialNotification 如果点击通知并打开应用程序,则会填充
    笔记没有向用户显示可见通知,您可以手动显示通知该通知由移动设备的OS呈现给用户该通知由移动设备的OS呈现给用户

    Android安装

    首先确保您已遵循初始设置指南消息设置指南

    安装RNFirebase Notifications包

    添加RNFirebaseNotificationsPackage到您的android/app/src/main/java/com/[app name]/MainApplication.java

    // ...
    import io.invertase.firebase.RNFirebasePackage;
    import io.invertase.firebase.notifications.RNFirebaseNotificationsPackage; // <-- Add this line
    
    public class MainApplication extends Application implements ReactApplication {
        // ...
    
        @Override
        protected List<ReactPackage> getPackages() {
          return Arrays.<ReactPackage>asList(
              new MainReactPackage(),
              new RNFirebasePackage(),
              new RNFirebaseNotificationsPackage() // <-- Add this line
          );
        }
      };
      // ...
    }

    更新Android清单

    将以下内容添加到android/app/src/main/AndroidManifest.xml

    添加权限:

    <manifest ...>
      <uses-permission android:name="android.permission.INTERNET" />
      <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
      <uses-permission android:name="android.permission.VIBRATE" />

    在活动道具中设置应用启动模式

    <activity
      ...
      android:launchMode="singleTop"
    >

    默认图标和颜色(可选)

    在应用程序组件中,添加元数据元素以设置默认通知图标和颜色。只要传入的消息没有明确设置图标或颜色,Android就会使用这些值。

    <application ...>
      <!-- Set custom default icon. This is used when no icon is set for incoming notification messages.
           See README(https://goo.gl/l4GJaQ) for more. -->
      <meta-data
        android:name="com.google.firebase.messaging.default_notification_icon"
        android:resource="@drawable/ic_stat_ic_notification" />
      <!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
           notification message. See README(https://goo.gl/6BKBk7) for more. -->
      <meta-data
        android:name="com.google.firebase.messaging.default_notification_color"
        android:resource="@color/colorAccent" />
    </application>

    通知渠道(可选)

    从Android 8.0(API级别26)及更高版本,支持并建议使用通知渠道。FCM提供具有基本设置的默认通知通道。如果您更喜欢创建和使用自己的默认频道,请将default_notification_channel_id设置为通知频道对象的ID,如图所示; 只要传入消息未明确设置通知通道,FCM就会使用此值。

    <application ...>
      <meta-data
        android:name="com.google.firebase.messaging.default_notification_channel_id"
        android:value="@string/default_notification_channel_id"/>
    </application>

    预定通知(可选)

    如果您想安排本地通知,那么您还需要将以下内容添加到以下应用程序组件中android/app/src/main/AndroidManifest.xml

    <application ...>
      <receiver android:name="io.invertase.firebase.notifications.RNFirebaseNotificationReceiver"/>
      <receiver android:enabled="true" android:exported="true"  android:name="io.invertase.firebase.notifications.RNFirebaseNotificationsRebootReceiver">
        <intent-filter>
          <action android:name="android.intent.action.BOOT_COMPLETED"/>
          <action android:name="android.intent.action.QUICKBOOT_POWERON"/>
          <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
          <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
      </receiver>
    </application>

    接收通知

    1)检查权限

    在您能够发送和接收通知之前,您需要确保用户已授予正确的权限:

    const enabled = await firebase.messaging().hasPermission();
    if (enabled) {
        // user has permissions
    } else {
        // user doesn't have permission
    }

    2)请求权限

    如果用户尚未授予权限,则可以提示他们执行此操作,如下所示:

    try {
        await firebase.messaging().requestPermission();
        // User has authorised
    } catch (error) {
        // User has rejected permissions
    }

    3)听取通知

    通知包含三种不同类型:

    • 来自FCM的仅通知消息
    • 来自FCM的通知+数据消息
    • 本地通知

    有关纯数据FCM消息,请参阅消息模块

    根据应用程序的状态,通知将触发两个侦听器中的一个:

    • onNotificationDisplayed - 在显示特定通知时触发
    • onNotification - 在收到特定通知时触发
    // Optional: Flow type
    import type { Notification } from 'react-native-firebase';
    
    componentDidMount() {
        this.notificationDisplayedListener = firebase.notifications().onNotificationDisplayed((notification: Notification) => {
            // Process your notification as required
            // ANDROID: Remote notifications do not contain the channel ID. You will have to specify this manually if you'd like to re-display the notification.
        });
        this.notificationListener = firebase.notifications().onNotification((notification: Notification) => {
            // Process your notification as required
        });
    }
    
    componentWillUnmount() {
        this.notificationDisplayedListener();
        this.notificationListener();
    }

    4)听取正在打开的通知

    在Android上,很遗憾,无法访问已打开的远程通知的标题和正文。如果需要,您可以使用data远程通知部分提供此信息。

    应用程序在前景和背景中

    如果您的应用位于前台或后台,则可以按以下方式监听点击/点击/打开通知的时间:

    // Optional: Flow type
    import type { Notification, NotificationOpen } from 'react-native-firebase';
    
    componentDidMount() {
        this.notificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen: NotificationOpen) => {
            // Get the action triggered by the notification being opened
            const action = notificationOpen.action;
            // Get information about the notification that was opened
            const notification: Notification = notificationOpen.notification;
        });
    }
    
    componentWillUnmount() {
        this.notificationOpenedListener();
    }

    应用已关闭

    如果您的应用已关闭,您可以通过点击/点按/打开通知来检查它是否已打开,如下所示:

    // Optional: Flow type
    import type { Notification, NotificationOpen } from 'react-native-firebase';
    
    async componentDidMount() {
        const notificationOpen: NotificationOpen = await firebase.notifications().getInitialNotification();
        if (notificationOpen) {
            // App was opened by a notification
            // Get the action triggered by the notification being opened
            const action = notificationOpen.action;
            // Get information about the notification that was opened
            const notification: Notification = notificationOpen.notification;
        }
    }


    安排通知

    Android和iOS都允许将通知安排在将来某个时间显示。

    1)建立通知

    要建立通知,请按照显示通知指南

    2)安排通知

    (Android)设置通知频道

    之前,你可以安排在Android的通知,你必须确保你已经创建了一个通知信道,如解释在这里

    安排通知

    // Build notification
    const notification = new firebase.notifications.Notification()...;
    
    // Schedule the notification for 1 minute in the future
    const date = new Date();
    date.setMinutes(date.getMinutes() + 1);
    
    firebase.notifications().scheduleNotification(notification, {
        fireDate: date.getTime(),
    })

    有关完整的参考文档,请参阅通知#scheduleNotification


    Android通知渠道

    从Android 8.0(API级别26)开始,通知必须指定通知通道,否则它们将不会出现。

    要允许React Native Firebase在所有版本的Android中无缝工作,您需要先创建一个频道,然后才能显示通知。这段代码可以重复运行多次,因此每次应用程序启动时都可以安全地运行。

    创建通知频道

    // Build a channel
    const channel = new firebase.notifications.Android.Channel('test-channel', 'Test Channel', firebase.notifications.Android.Importance.Max)
      .setDescription('My apps test channel');
    
    // Create the channel
    firebase.notifications().android.createChannel(channel);

    有关完整的参考文档,请参阅AndroidChannelAndroidNotifications

    创建通知通道组

    React Native Firebase还支持通知通道组的概念

    // Build a channel group
    const channelGroup = new firebase.notifications.Android.ChannelGroup('test-group', 'Test Channel Group');
    
    // Create the channel group
    firebase.notifications().android.createChannelGroup(channelGroup);

    有关完整的参考文档,请参阅AndroidChannelGroupAndroidNotifications


    Tips:

    记得导包:

    import firebase from 'react-native-firebase';
    import type {Notification, NotificationOpen, RemoteMessage} from 'react-native-firebase';

    发送通知有两种方式:根据包名和设备的令牌。

    获取令牌方法

    /**
     * 获取令牌
     * @returns {Promise<void>}
     */
    async msg() {
        const fcmToken = await firebase.messaging().getToken();
        if (fcmToken) {
            console.log(`令牌为:${fcmToken}`)
        } else {
            // user doesn't have a device token yet
            alert('user doesn\'t have a device token yet')
        }
    }

    接收通知的监听:

    应用在前台

    this.notificationDisplayedListener = firebase.notifications().onNotificationDisplayed((notification: Notification) => {
        // Process your notification as required
        // ANDROID: Remote notifications do not contain the channel ID. You will have to specify this manually if you'd like to re-display the notification.
        console.log(notification);
        alert('onNotificationDisplayed')
    
    });
    
    this.notificationListener = firebase.notifications().onNotification((notification: Notification) => {
        // Process your notification as required
        console.log(notification);
        alert('onNotification')
    });
    notification._title
    notification._body
    notification._data

    notification为接收到通知时拿到的对象。_title,_body等是高级选项中填写的内容

    其实有两种方法接收到通知的监听,onNotificationDisplayed和onNotification,但一般通知好像

    后台发的是走的onNotification,app内部发的通知走的是onNotificationDisplayed


    应用在后台:

    async checkNoti() {
        const notificationOpen: NotificationOpen = await firebase.notifications().getInitialNotification();
        if (notificationOpen) {
            // App was opened by a notification
            // Get the action triggered by the notification being opened
            const action = notificationOpen.action;
            console.log(action);
            // Get information about the notification that was opened
            const notification: Notification = notificationOpen.notification;
            console.log(notification);
        }
    }








    展开全文
  • React Native发送通知

    2019-08-15 18:41:07
    推荐:https://github.com/zo0r/react-native-push-notification demo解析: AndroidManifest.xml:配置基本权限 <manifest xmlns:android="http://schemas.android.com/apk/res/android" ...

    一、使用第三方库做本地/远程消息推送

    推荐:https://github.com/zo0r/react-native-push-notification

    demo解析:

    AndroidManifest.xml:配置基本权限

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example">
    
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
    
        <application
          android:name=".MainApplication"
          android:label="@string/app_name"
          android:icon="@mipmap/ic_launcher"
          android:allowBackup="false"
          android:theme="@style/AppTheme">
          <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
          </activity>
          <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
    
           <receiver
                android:name="com.google.android.gms.gcm.GcmReceiver"
                android:exported="true"
                android:permission="com.google.android.c2dm.permission.SEND" >
                <intent-filter>
                    <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                    <category android:name="${applicationId}" />
                </intent-filter>
            </receiver>
    
            <receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationPublisher" />
            <receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationBootEventReceiver">
                <intent-filter>
                    <action android:name="android.intent.action.BOOT_COMPLETED" />
                </intent-filter>
            </receiver>
            <service android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationRegistrationService"/>
            <service
                android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationListenerService"
                android:exported="false" >
                <intent-filter>
                    <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                </intent-filter>
            </service>
    
    
            <meta-data  android:name="com.dieam.reactnativepushnotification.notification_channel_name"
                        android:value="Example-Channel"/>
            <meta-data  android:name="com.dieam.reactnativepushnotification.notification_channel_description"
                        android:value="Super channel description"/>
            <meta-data  android:name="com.dieam.reactnativepushnotification.notification_color"
                        android:resource="@android:color/white"/>
        </application>
    
    
        <uses-permission android:name="android.permission.WAKE_LOCK" />
        <permission
            android:name="${applicationId}.permission.C2D_MESSAGE"
            android:protectionLevel="signature" />
        <uses-permission android:name="${applicationId}.permission.C2D_MESSAGE" />
    
    
        <uses-permission android:name="android.permission.VIBRATE" />
        <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    </manifest>

    NotifService.js:配置各类推送的消息显示

    import PushNotification from 'react-native-push-notification';
    
    export default class NotifService {
    
      constructor(onRegister, onNotification) {
        this.configure(onRegister, onNotification);
    
        this.lastId = 0;
      }
    
      configure(onRegister, onNotification, gcm = "") {
        PushNotification.configure({
          // (optional) Called when Token is generated (iOS and Android)
          onRegister: onRegister, //this._onRegister.bind(this),
    
          // (required) Called when a remote or local notification is opened or received
          onNotification: onNotification, //this._onNotification,
    
          // ANDROID ONLY: GCM Sender ID (optional - not required for local notifications, but is need to receive remote push notifications)
          senderID: gcm,
    
          // IOS ONLY (optional): default: all - Permissions to register.
          permissions: {
            alert: true,
            badge: true,
            sound: true
          },
    
          // Should the initial notification be popped automatically
          // default: true
          popInitialNotification: true,
    
          /**
            * (optional) default: true
            * - Specified if permissions (ios) and token (android and ios) will requested or not,
            * - if not, you must call PushNotificationsHandler.requestPermissions() later
            */
          requestPermissions: true,
        });
      }
    
      localNotif() {
        this.lastId++;
        PushNotification.localNotification({
          /* Android Only Properties */
          id: ''+this.lastId, // (optional) Valid unique 32 bit integer specified as string. default: Autogenerated Unique ID
          ticker: "My Notification Ticker", // (optional)
          autoCancel: true, // (optional) default: true
          largeIcon: "ic_launcher", // (optional) default: "ic_launcher"
          smallIcon: "ic_notification", // (optional) default: "ic_notification" with fallback for "ic_launcher"
          bigText: "My big text that will be shown when notification is expanded", // (optional) default: "message" prop
          subText: "This is a subText", // (optional) default: none
          color: "red", // (optional) default: system default
          vibrate: true, // (optional) default: true
          vibration: 300, // vibration length in milliseconds, ignored if vibrate=false, default: 1000
          tag: 'some_tag', // (optional) add tag to message
          group: "group", // (optional) add group to message
          ongoing: false, // (optional) set whether this is an "ongoing" notification
    
          /* iOS only properties */
          alertAction: 'view', // (optional) default: view
          category: null, // (optional) default: null
          userInfo: null, // (optional) default: null (object containing additional notification data)
    
          /* iOS and Android properties */
          title: "Local Notification", // (optional)
          message: "My Notification Message", // (required)
          playSound: false, // (optional) default: true
          soundName: 'default', // (optional) Sound to play when the notification is shown. Value of 'default' plays the default sound. It can be set to a custom sound such as 'android.resource://com.xyz/raw/my_sound'. It will look for the 'my_sound' audio file in 'res/raw' directory and play it. default: 'default' (default sound is played)
          number: '10', // (optional) Valid 32 bit integer specified as string. default: none (Cannot be zero)
          actions: '["Yes", "No"]',  // (Android only) See the doc for notification actions to know more
        });
      }
    
      scheduleNotif() {
        this.lastId++;
        PushNotification.localNotificationSchedule({
          date: new Date(Date.now() + (30 * 1000)), // in 30 secs
    
          /* Android Only Properties */
          id: ''+this.lastId, // (optional) Valid unique 32 bit integer specified as string. default: Autogenerated Unique ID
          ticker: "My Notification Ticker", // (optional)
          autoCancel: true, // (optional) default: true
          largeIcon: "ic_launcher", // (optional) default: "ic_launcher"
          smallIcon: "ic_notification", // (optional) default: "ic_notification" with fallback for "ic_launcher"
          bigText: "My big text that will be shown when notification is expanded", // (optional) default: "message" prop
          subText: "This is a subText", // (optional) default: none
          color: "blue", // (optional) default: system default
          vibrate: true, // (optional) default: true
          vibration: 300, // vibration length in milliseconds, ignored if vibrate=false, default: 1000
          tag: 'some_tag', // (optional) add tag to message
          group: "group", // (optional) add group to message
          ongoing: false, // (optional) set whether this is an "ongoing" notification
    
          /* iOS only properties */
          alertAction: 'view', // (optional) default: view
          category: null, // (optional) default: null
          userInfo: null, // (optional) default: null (object containing additional notification data)
    
          /* iOS and Android properties */
          title: "Scheduled Notification", // (optional)
          message: "My Notification Message", // (required)
          playSound: true, // (optional) default: true
          soundName: 'default', // (optional) Sound to play when the notification is shown. Value of 'default' plays the default sound. It can be set to a custom sound such as 'android.resource://com.xyz/raw/my_sound'. It will look for the 'my_sound' audio file in 'res/raw' directory and play it. default: 'default' (default sound is played)
        });
      }
    
      checkPermission(cbk) {
        return PushNotification.checkPermissions(cbk);
      }
    
      cancelNotif() {
        PushNotification.cancelLocalNotifications({id: ''+this.lastId});
      }
    
      cancelAll() {
        PushNotification.cancelAllLocalNotifications();
      }
    }

    App.js:消息显示

    /**
     * Sample React Native App
     * https://github.com/facebook/react-native
     *
     * @format
     * @flow
     */
    
    import React, { Component } from 'react';
    import { TextInput, StyleSheet, Text, View, TouchableOpacity, Alert } from 'react-native';
    import NotifService from './NotifService';
    import appConfig from './app.json';
    
    type Props = {};
    export default class App extends Component<Props> {
    
      constructor(props) {
        super(props);
        this.state = {
          senderId: appConfig.senderID
        };
    
        this.notif = new NotifService(this.onRegister.bind(this), this.onNotif.bind(this));
      }
    
      render() {
        return (
          <View style={styles.container}>
            <Text style={styles.title}>Example app react-native-push-notification</Text>
            <View style={styles.spacer}></View>
            <TextInput style={styles.textField} value={this.state.registerToken} placeholder="Register token" />
            <View style={styles.spacer}></View>
    
            <TouchableOpacity style={styles.button} onPress={() => { this.notif.localNotif() }}><Text>Local Notification (now)</Text></TouchableOpacity>
            <TouchableOpacity style={styles.button} onPress={() => { this.notif.scheduleNotif() }}><Text>Schedule Notification in 30s</Text></TouchableOpacity>
            <TouchableOpacity style={styles.button} onPress={() => { this.notif.cancelNotif() }}><Text>Cancel last notification (if any)</Text></TouchableOpacity>
            <TouchableOpacity style={styles.button} onPress={() => { this.notif.cancelAll() }}><Text>Cancel all notifications</Text></TouchableOpacity>
            <TouchableOpacity style={styles.button} onPress={() => { this.notif.checkPermission(this.handlePerm.bind(this)) }}><Text>Check Permission</Text></TouchableOpacity>
    
            <View style={styles.spacer}></View>
            <TextInput style={styles.textField} value={this.state.senderId} onChangeText={(e) => {this.setState({ senderId: e })}} placeholder="GCM ID" />
            <TouchableOpacity style={styles.button} onPress={() => { this.notif.configure(this.onRegister.bind(this), this.onNotif.bind(this), this.state.senderId) }}><Text>Configure Sender ID</Text></TouchableOpacity>
            {this.state.gcmRegistered && <Text>GCM Configured !</Text>}
    
            <View style={styles.spacer}></View>
          </View>
        );
      }
    
      onRegister(token) {
        Alert.alert("Registered !", JSON.stringify(token));
        console.log(token);
        this.setState({ registerToken: token.token, gcmRegistered: true });
      }
    
      onNotif(notif) {
        console.log(notif);
        Alert.alert(notif.title, notif.message);
      }
    
      handlePerm(perms) {
        Alert.alert("Permissions", JSON.stringify(perms));
      }
    }
    
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
      },
      welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
      },
      button: {
        borderWidth: 1,
        borderColor: "#000000",
        margin: 5,
        padding: 5,
        width: "70%",
        backgroundColor: "#DDDDDD",
        borderRadius: 5,
      },
      textField: {
        borderWidth: 1,
        borderColor: "#AAAAAA",
        margin: 5,
        padding: 5,
        width: "70%"
      },
      spacer: {
        height: 10,
      },
      title: {
        fontWeight: "bold",
        fontSize: 20,
        textAlign: "center",
      }
    });

    最终效果:

     

    二、使用极光开发者服务做远程消息推送

    1.官网注册极光开发者账号,并创建应用

    2.安装

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

    3.关联

    react-native link jpush-react-native
    react-native link jcore-react-native

    4.打开 project/android/app/src/main/java/com/项目名/下的 MainApplication.java 文件,然后加入 JPushPackage

    import cn.jpush.reactnativejpush.JPushPackage; 
    
    public class MainApplication extends Application implements ReactApplication {
    // 设置为 true 将不会弹出 toast
        private boolean SHUTDOWN_TOAST = false;
        // 设置为 true 将不会打印 log
        private boolean SHUTDOWN_LOG = false;
      private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
        @Override
        public boolean getUseDeveloperSupport() {
          return BuildConfig.DEBUG;
        }
    
        @Override
        protected List<ReactPackage> getPackages() {
          return Arrays.<ReactPackage>asList(
                new MainReactPackage(),
                   new JPushPackage(SHUTDOWN_TOAST, SHUTDOWN_LOG) 
          );
        }

    5.打开 project/android/app/src/main/java/com/项目名/下的MainActivity.java 文件,然后加入 如下代码:

    import android.os.Bundle;
    import com.facebook.react.ReactActivity;
    import cn.jpush.android.api.JPushInterface;
    
    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);
        }
     
        @Override
        protected void onDestroy() {
            super.onDestroy();
        }
    }

     6.使用

    (1)RN工程代码:

    import React, { Component } from "react";
    import { Dimensions, Text, Platform, Linking, Alert } from "react-native";
    import JPushModule from 'jpush-react-native'
    
    const deviceHeight = Dimensions.get('window').height;  
    
    export default class Login extends Component {
        constructor(props){
            super(props);
            this.state = {
                
            }
        }
    
        componentDidMount() { 
        /****************************通知 start **************************************************/
            if (Platform.OS === 'android') {
              JPushModule.initPush()
           // 新版本必需写回调函数
              JPushModule.notifyJSDidLoad(resultCode => {
                if (resultCode === 0) {
                }
              })
            } else {
              JPushModule.setupPush()
            }
            // 接收自定义消息
            this.receiveCustomMsgListener = map => {
              this.setState({
                pushMsg: map.content
              })
              console.log('extras: ' + map.extras)
            }
    
            // 接收自定义消息JPushModule.addReceiveCustomMsgListener(this.receiveCustomMsgListener)
            this.receiveNotificationListener = map => {
              console.log('alertContent: ' + map.alertContent)
              console.log('extras: ' + map.extras)
            }
            
            // 接收推送通知
            JPushModule.addReceiveNotificationListener(this.receiveNotificationListener)
            // 打开通知
            this.openNotificationListener = map => {
              // console.log('Opening notification!')
            //  console.log('map.extra: ' + map.extras)
              let webUrl= JSON.parse(map.extras).webUrl
              let url = webUrl.replace(new RegExp("\/", 'g'), "/")
              Linking.canOpenURL(url).then(supported => {
                if (!supported) {
                  Alert.alert('您的系统不支持打开浏览器!')
                } else {
                  return Linking.openURL(url);
                }
              }).catch(err => { });
    
            }
    
            JPushModule.addReceiveOpenNotificationListener(this.openNotificationListener)
    
            // this.getRegistrationIdListener = registrationId => {
            //   console.log('Device register succeed, registrationId ' + registrationId)
            // }
            // JPushModule.addGetRegistrationIdListener(this.getRegistrationIdListener)
            /****************************通知 end **************************************************/
          }
    
        componentWillUnmount() {
            JPushModule.removeReceiveCustomMsgListener(this.receiveCustomMsgListener)
            JPushModule.removeReceiveNotificationListener(this.receiveNotificationListener)
            JPushModule.removeReceiveOpenNotificationListener(this.openNotificationListener)
            // JPushModule.removeGetRegistrationIdListener(this.getRegistrationIdListener)
            // console.log('Will clear all notifications')
            // JPushModule.clearAllNotifications()
        }
          
        
    
        render() {
            return (
              <Text>push notification test</Text>
            );
        }
    }

    (2)极光官网推送

     

    7.最终效果

     

    三、APP内消息通知

    使用antd组件NoticeBar通告栏:https://rn.mobile.ant.design/components/notice-bar-cn/ 即可

    最终效果:

     

    参考:React Native之通知栏消息提示(android)  作者:jackson影琪

    转载于:https://www.cnblogs.com/bbcfive/p/11123274.html

    展开全文
  • React Native通知栏消息提示(android) 一,需求分析与概述 1.1,推送作为手机应用的基本功能,是手机应用的重要部分,如果自己实现一套推送系统费时费力,所以大部分的应用都会选择使用第三方的推送服务,如极光...

    React Native之通知栏消息提示(android)

     

    一,需求分析与概述

    1.1,推送作为手机应用的基本功能,是手机应用的重要部分,如果自己实现一套推送系统费时费力,所以大部分的应用都会选择使用第三方的推送服务,如极光推送。

    1.2,jpush-react-native 是极光推送官方开发的 React Native 版本插件,可以快速集成推送功能。现在最新版本的 JPush SDK 分离了 JPush 及 JCore,让开发者可以分开集成 JMessage 及 JPush(以前 JMessage 包含了 JPush)。

    API:

     1 #初始化JPush 必须先初始化才能执行其他操作(only android)
     2 initPush
     3 
     4 getInfo
     5 
     6 #执行该方法后,无法接收到通知
     7 stopPush
     8 
     9 #stopPush后,执行该方法,可接收通知(only android)
    10 resumePush
    11 
    12 #参数是func,func的参数是registrationId
    13 getRegistrationID
    14 
    15 #设置标签
    16 setTags
    17 
    18 #添加标签
    19 addTags
    20 
    21 #删除标签
    22 deleteTags
    23 
    24 #检查标签的状态
    25 checkTagBindState
    26 
    27 #清除所有标签
    28 cleanTags
    29 
    30 #设置别名
    31 setAlias
    32 
    33 #删除别名
    34 deleteAlias
    35 
    36 #获取别名
    37 getAlias
    38 
    39 #通知栏样式:Basic
    40 setStyleBasic
    41 
    42 #通知栏样式:Custom
    43 setStyleCustom

    1.3,推送通知可以及时地提醒用户.

    二,极光推送注册与集成

    2.1,注册

    首先,登录极光官网系统,如果还没有账号可以注册一个,登录成功我们就可以创建和管理我们的应用了。  

    2.2,集成(android)

    第一步:安装

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

    1  npm install jpush-react-native --save
    2  jpush-react-native 1.4.2 版本以后需要同时安装 jcore-react-native
    3  npm install jcore-react-native --save 

    第二步:配置

    自动关联配置

    1 # 针对性的link,避免之前手动配置的其它插件重复配置造成报错
    2  react-native link jpush-react-native
    3  react-native link jcore-react-native

    执行完 link 项目后可能会出现报错,这没关系,需要手动配置一下 build.gradle 文件。如自动配置没有成功或没有完善,可根据手动配置检查

    手动配置

    (1),检查 android 项目下的 settings.gradle 配置有没有包含以下内容(project/android/settings.gradle):

    1 include ':jcore-react-native'
    2 project(':jcore-react-native').projectDir = new File(rootProject.projectDir, '../node_modules/jcore-react-native/android')
    3 
    4 include ':jpush-react-native'
    5 project(':jpush-react-native').projectDir = new File(rootProject.projectDir, '../node_modules/jpush-react-native/android')

     (2),project/android/app/build.gradle:

     1 android {
     2     ...
     3     defaultConfig {
     4         applicationId "yourApplicationId" // 此处改成你在极光官网上申请应用时填写的包名
     5         ...
     6         manifestPlaceholders = [
     7                 JPUSH_APPKEY: "yourAppKey", //在此替换你极光官网上申请的 APPKey
     8                 APP_CHANNEL: "developer-default"    //应用渠道号, 默认即可
     9         ]
    10     }
    11 }
    12 ...
    13 dependencies {
    14     compile project(':jpush-react-native')  // 添加 jpush 依赖
    15     compile project(':jcore-react-native')  // 添加 jcore 依赖
    16     compile fileTree(dir: "libs", include: ["*.jar"])
    17     compile "com.android.support:appcompat-v7:23.0.1"
    18     compile "com.facebook.react:react-native:+"  // From node_modules
    19 }

    (3),检查一下 app 下的 AndroidManifest 配置,有没有增加 <meta-data> 部分。 project/android/app/src/main/AndroidManifest.xml:

    1 <application
    2     ...
    3     <!-- Required . Enable it you can get statistics data with channel -->
    4     <meta-data android:name="JPUSH_CHANNEL" android:value="${APP_CHANNEL}"/>
    5     <meta-data android:name="JPUSH_APPKEY" android:value="${JPUSH_APPKEY}"/>
    6  
    7 </application>

    (4),打开 project/android/app/src/main/java/com/项目名/下的 MainApplication.java 文件,然后加入 JPushPackage

     1 ...
     2 
     3 import com.rt2zz.reactnativecontacts.ReactNativeContacts;
     4 import cn.jpush.reactnativejpush.JPushPackage; 
     5 
     6 ...
     7 
     8 public class MainApplication extends Application implements ReactApplication {
     9 // 设置为 true 将不会弹出 toast
    10     private boolean SHUTDOWN_TOAST = false;
    11     // 设置为 true 将不会打印 log
    12     private boolean SHUTDOWN_LOG = false;
    13   private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    14     @Override
    15     public boolean getUseDeveloperSupport() {
    16       return BuildConfig.DEBUG;
    17     }
    18 
    19     @Override
    20     protected List<ReactPackage> getPackages() {
    21       return Arrays.<ReactPackage>asList(
    22             new MainReactPackage(),
    23                new JPushPackage(SHUTDOWN_TOAST, SHUTDOWN_LOG) 
    24       );
    25     }
    26 
    27    ...
    28 
    29 }

    (5),打开 project/android/app/src/main/java/com/项目名/下的MainActivity.java 文件,然后加入 如下代码:

     1 ...
     2 
     3 
     4 import android.os.Bundle;
     5 import com.facebook.react.ReactActivity;
     6 import cn.jpush.android.api.JPushInterface;
     7 
     8 public class MainActivity extends ReactActivity {
     9 
    10 ...
    11 
    12     @Override
    13     protected void onCreate(Bundle savedInstanceState) {
    14         super.onCreate(savedInstanceState);
    15         JPushInterface.init(this);
    16     }
    17  
    18     @Override
    19     protected void onPause() {
    20         super.onPause();
    21         JPushInterface.onPause(this);
    22     }
    23  
    24     @Override
    25     protected void onResume() {
    26         super.onResume();
    27         JPushInterface.onResume(this);
    28     }
    29  
    30     @Override
    31     protected void onDestroy() {
    32         super.onDestroy();
    33     }
    34 }

     (6),打开  project/android/app/src/main/下的AndroidManifest.xml 文件,然后添加访问通知的权限:

    1 <!--添加通知权限,${ApplicationID}替换成你的applicationID!-->
    2     <premission 
    3         android:name="${ApplicationID}.permission.JPUSH_MESSAGE"
    4         android:protectionLevel="signature"/>

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

    三,使用与实现

    3.1,使用

    (1),在js中 1 import React, { PureComponent } from 'react';

     2 import {
     3   Linking,
     4   Alert
     5 } from 'react-native';
     6 import JPushModule from 'jpush-react-native'
     7 
     8 ...
     9 
    10 
    11 componentDidMount() { 
    12 /****************************通知 start **************************************************/
    13     if (Platform.OS === 'android') {
    14       JPushModule.initPush()
    15    // 新版本必需写回调函数
    16       JPushModule.notifyJSDidLoad(resultCode => {
    17         if (resultCode === 0) {
    18         }
    19       })
    20     } else {
    21       JPushModule.setupPush()
    22     }
    23     // 接收自定义消息
    24     this.receiveCustomMsgListener = map => {
    25       this.setState({
    26         pushMsg: map.content
    27       })
    28       console.log('extras: ' + map.extras)
    29     }
    30 
    31         // 接收自定义消息JPushModule.addReceiveCustomMsgListener(this.receiveCustomMsgListener)
    32     this.receiveNotificationListener = map => {
    33       console.log('alertContent: ' + map.alertContent)
    34       console.log('extras: ' + map.extras)
    35     }
    36     // 接收推送通知
    37 JPushModule.addReceiveNotificationListener(this.receiveNotificationListener)
    38  // 打开通知
    39     this.openNotificationListener = map => {
    40       // console.log('Opening notification!')
    41     //  console.log('map.extra: ' + map.extras)
    42      let webUrl= JSON.parse(map.extras).webUrl
    43       let url = webUrl.replace(new RegExp("\/", 'g'), "/")
    44       Linking.canOpenURL(url).then(supported => {
    45         if (!supported) {
    46           Alert.alert('您的系统不支持打开浏览器!')
    47         } else {
    48           return Linking.openURL(url);
    49         }
    50       }).catch(err => { });
    51 
    52     }
    53     JPushModule.addReceiveOpenNotificationListener(this.openNotificationListener)
    54 
    55     // this.getRegistrationIdListener = registrationId => {
    56     //   console.log('Device register succeed, registrationId ' + registrationId)
    57     // }
    58     // JPushModule.addGetRegistrationIdListener(this.getRegistrationIdListener)
    59     /****************************通知 end **************************************************/
    60 
    61 
    62   }
    63   componentWillUnmount() {
    64     JPushModule.removeReceiveCustomMsgListener(this.receiveCustomMsgListener)
    65     JPushModule.removeReceiveNotificationListener(this.receiveNotificationListener)
    66     JPushModule.removeReceiveOpenNotificationListener(this.openNotificationListener)
    67     // JPushModule.removeGetRegistrationIdListener(this.getRegistrationIdListener)
    68     // console.log('Will clear all notifications')
    69     // JPushModule.clearAllNotifications()
    70   }
    71   
    72 }
    73 
    74 ...

    (2),在极光官网上推送

     

    3.2,实现的效果

     

     

    问题:

    1,真机没接收到通知

    解决:打开node_modules/jpush_react-native/android/src/AndroidManifest.xml,将所有的${applicationId}替换成你的包名。或将project/android/src/AndroidManifest.xml,的${applicationId}替换成你的包名。

    ...
    
    <application
            android:name=".MainApplication"
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme">
            <activity
                android:name=".MainActivity"
                android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
                android:label="@string/app_name">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
    
       ...
    
            <!-- Required . Enable it you can get statistics data with channel -->
            <meta-data android:name="JPUSH_CHANNEL" android:value="${APP_CHANNEL}"/>
            <meta-data android:name="JPUSH_APPKEY" android:value="${JPUSH_APPKEY}"/>
    
        </application>

    .MainApplication和.MainActivity前添加包名

     

    转载于:https://www.cnblogs.com/jackson-yqj/p/9877388.html

    展开全文
  • 1.push传值   this.props.nav.push({  id:'push',  component: Findss,  
    1.push传值   
     this.props.nav.push({
                                                id:'push',
                                                component: Findss,
                                                title:'标题',
                                                });     
                                                
    2. 接收  //设置默认值
        constructor(props){
          super(props);
          this.state ={
             title:null,
             id:null
          };
        }

     componentDidMount()
     {
       //这里获取传过来的值
       this.setState({
         title:this.props.title,
         id:this.props.id,
       });
     }                                                                                   
           显示  <Text style = {styles.text}>{this.state.title}</Text>   
    但是第二个页面显示不出来传过来的title ,不知道为什么,是这个值没传过来吗?有没有大神知道,跪求。
    展开全文
  • react native 端参考代码: importReact,{Component}from'react'; import{ AppRegistry, StyleSheet, Text, TouchableHighlight, Alert, TouchableOpacity, View }from'react-native...
  • react-native-video 是一个播放视频的开源组件, 它的用法很简单。 1.安装 依次执行下面两个命令, npm i -S react-native-video react-native link (这一步是连接本地视频库) (1) ios: 如果您想允许其他应用...
  • React Native概述什么是React NativeReact Native是Facebook在React.js Config 2015 大会上推出的一个用于开发Android和iOS App的一个框架。主要编程语言是JavaScript,UI使用JSX(一种语法类似于XML的UI描述语言)...
  • React Native通知栏消息提示(ios) 一,需求分析与概述 详情请查看:React Native通知栏消息提示(android) 二,极光推送注册与集成 2.1,注册 详情请查看:React Native通知栏消息提示(android) 2.2,集成...
  • 欢迎大家关注【跨平台开发那些事】公众号,定期推送跨平台开发技术实践。 ... 基于最新版本React Native实现JsBundle预加载,界面秒开优化 ...今年1月份,新开源的react-natvigation库...在短短不到3个月的时间,gith...
  • React Native(简称RN)开发的app大部分都可以在JS端完成,但是也有一些复杂的功能是需要原生端来完成的,或者是在原生项目中集成RN,此时RN与原生端就可避免的需要进行交互,比如页面跳转和数据传递。...
  • yarn add react-navigation 2、使用 (1)创建跳转路由 import React from 'react'; //导入 import {createStackNavigator} from 'react-navigation'; import Page1Screen from '../screen/Page1'; import Page2...
  • TextInput组件介绍输入框组件的主要属性如下: autoCapitalize : 枚举类型,可选值有none,sentences,words,characters.当用户输入时,用于提示。 placeholder:占位符,在输入前显示的文本内容。...
  • 欢迎大家关注【跨平台开发那些事】公众号,定期推送跨平台开发技术实践。 在前两篇的内容中,和大家分享了Android原生集成RN,以及RN的增量热更新。...本篇内容同样和React Native 与 原生App有关,可...
  • 首先要确认已经配置好react-native的环境。 # 创建一个native应用,SimpleApp # 然后进入项目目录 react-native init SimpleApp cd SimpleApp # 通过npm安装最新版本的react-navigation npm install --save...
  • 最近,我使用react-native-firebase在我的react本机应用程序中集成了推送通知。在整合成功实施的过程中,我遇到了很多挑战,所以我想与大家分享一些步骤 在控制台上创建应用 首先在Firebase控制台上创建一个应用...
  • 在浏览器中我们可以通过&lt;a&gt;标签与url实现不同页面之间的跳转,利用浏览器的返回按钮返回之前浏览的页面,但是在React Native中却没有集成内嵌的全局栈来...通过如下方法安装react navigation你的...
  • 本文出自《React Native学习笔记》系列文章。 React Native是基于React的,在开发React Native过程中少不了的需要用到React方面的知识。虽然官方也有相应的Document,但篇幅比较多,学起来比较枯燥。 通过《React ...
  • 请求自己后台,发现明明传了参数,后台debug模式,查看,接收不了参数。 问题点:传参格式不正确,与后台想要的格式不一致。 业务描述:角色页面,初始化页面获取角色,分页查询,参数为分页参数 (一)不能传参...
  • 解锁React Native开发新姿势,一网打尽React Native最新与最热技术,点我Get!!! 为了帮助大家快速上手在React Native与Redux开发,在这本文中将向大家介绍如何在React Native中使用Redux和react-navigation组合?,...
1 2 3 4 5 ... 20
收藏数 5,049
精华内容 2,019
关键字:

native react 通知接收不到