你不可不知的 React Native 混合用法(Android 篇)

前端之家收集整理的这篇文章主要介绍了你不可不知的 React Native 混合用法(Android 篇)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

前言

当前 React Native 虽说版本更新比较快,各种组件也提供的很全面了,但是在某些情况下,混合开发的方式才会快速缩短开发周期,原因无非就是原生平台的“底蕴”无疑更深,拥有众多且类型丰富的第三方支持库。很多情况下,运用这些库可以避免苦逼的重复劳动。接下来我们以 jpush-react-native 插件为例来看看在 React Native 中如何使用原生的第三方库。

开始

在开始之前,你必须安装以下软件:npm 命令行工具,react-native 命令行工具, Android Stu@R_502_410@。jpush-react-native 是极光推送提供的 React Native 版本插件,可以让我们快速集成推送功能。实际上这个插件就是一个混合应用,使用他们自己的原生 SDK,并且封装了一些接口,让开发者可以在 JS 和原生平台之间互相调用。接下来我们只需要三个步骤就可以完成绝大多数原生库在 React Native 中的应用。

先明确两个概念,在 Android Stu@R_502_410@ 中一个项目往往会包含很多模块(Module),项目中的 build.gradle 配置一般对所有 module 生效。而 Module 中的 build.gradle 则配置了该 Module 所需的依赖或者任务等等。

第一步——安装

在命令行中进入 React Native 项目,然后使用如下两个命令即可完成 jpush-react-native 插件的安装:

npm install jpush-react-native --save

rnpm @H_502_21@link jpush-react-native

jpush-react-native 发布到 npm 了,所以使用命令行可以轻松安装。

然而有很多第三方库可能需要原生的安装方式。比如提供 jar 包或者 aar 包的方式在 Android 中很常见,也有可能以 maven 依赖的方式安装。如果是以上方式安装需要做一些调整:

  • jar 包或者 aar 包的方式:
    i. 将依赖包复制到 module 的 libs 文件夹下(如果没有则需要手动创建)
    ii. 在 build.gradle 中添加
android {
@H_502_21@...
    sourceSets {    
        main {        
            jniLibs.srcDirs = ['libs']
        }
    }
@H_502_21@...
}
@H_502_21@...
dependencies {
    compile fileTree(dir: "libs",include: ["*.jar"])
}
  • 以 maven 依赖的方式:
    i. 在项目的 build.gradle 中增加
allprojects {    
    repositories {
        @H_502_21@...        
        mavenCentral()        
        maven {            
            url "https://oss.sonatype.org/content/repositories/snapshots/"        
        }    
    }
}

ii. 在 module 的 build.gradle 中添加

dependencies {
@H_502_21@...
compile 'xxx-SNAPSHOT'
}

其中的 xxx 指代 groupId、artifactId 以及版本号(以 : 分隔),一般都会由提供方给出。比如 ActiveAndroid:

compile 'com.michaelpardo:activeandroid:3.1.0-SNAPSHOT'

第二步——适配(配置)

这一步因第三方库而异,其实大多都是大同小异,有的库甚至不需要配置直接可以“搭建桥梁”使用。jpush-react-native 还是要配置一下的
首先在命令行中运行脚本:

// 将 AppKey 和 Module Name 替换成自己的
npm run configureJPush [AppKey] [Module Name]
  • 配置 AndroidManifest
<Meta-@H_502_21@data android:name="JPUSH_CHANNEL" android:value="${APP_CHANNEL}"/>
<Meta-@H_502_21@data android:name="JPUSH_APPKEY" android:value="${JPUSH_APPKEY}"/>

将以上代码复制到你 Module 的 AndroidManifest 下即可。

  • 配置 build.gradle
    打开与 AndroidManifest 同级的 build.gradle 文件,做以下改动:
android {
@H_502_21@...

    defaultConfig {
        // 换成自己的包名
        applicationId "com.xxx"
        @H_502_21@...
        manifestPlaceholders = [        
            JPUSH_APPKEY: "xxx",//在此替换你的AppKey,极光官网注册应用获得         
            APP_CHANNEL: "developer-default"      //应用渠道号
        ]
    }
}

到此配置完成。

第三步 搭建桥梁

这一步是最后也是最核心的一步。“搭建桥梁”主要是在 Native 侧提供一些 @ReactMethod 标签方法,或者在 Native 中处理后回调到 JS,说白了就是要使得 JS 和 Native 可以相互调用。这也是混合开发的优势所在,原生平台提供的库,我们只需要搭建一下桥梁,就可以拿来使用。只要稍微写一点原生的代码,可以省去我们绝大部分工作。许多刚接触 React Native 的人不知道如何在 Native 中打开 JS 的界面(众所周知,JS 的界面由一个个 Component 组成,有自己的路由系统)后面我会写一个简单例子,用 Native 的方式声明注册界面(在 Android 中即为 Activity),然后用 JS 渲染界面,这个问题就迎刃而解了。接下来还是先看看 jpush-react-native 的例子。

首先在你的 Module 下创建一个 ManiActivity 以及 MainApplication 类。RN 0.29 后,需要在 MainApplication 中添加原生模块。

MainActivity.java

@H_502_21@public @H_502_21@class MainActivity @H_502_21@extends ReactActivity @H_502_21@implements DefaultHardwareBackBtnHandler {

    @Override
    @H_502_21@protected String getMainComponentName() { 
        // 这里返回的名字要与 JS 侧注册的 Component 名字一致
        @H_502_21@return "PushDemoApp";
    }

    @Override
    @H_502_21@protected @H_502_21@void onPause() {    
        @H_502_21@super.onPause();    
        JPushInterface.onPause(@H_502_21@this);
    }

    @Override
    @H_502_21@protected @H_502_21@void onResume() {    
        @H_502_21@super.onResume();    
        JPushInterface.onResume(@H_502_21@this);
    }
}

接下来需要在 MainApplication 中增加原生模块

MainApplication.java

@H_502_21@public @H_502_21@class MainApplication @H_502_21@extends Application @H_502_21@implements ReactApplication {    

    @H_502_21@private @H_502_21@boolean SHUTDOWN_TOAST = @H_502_21@false;    
    @H_502_21@private @H_502_21@boolean SHUTDOWN_LOG = @H_502_21@false;    

    @H_502_21@private @H_502_21@final ReactNativeHost mReactNativeHost = @H_502_21@new ReactNativeHost(@H_502_21@this) {        
        @Override        
        @H_502_21@protected @H_502_21@boolean getUseDeveloperSupport() {            
            @H_502_21@return BuildConfig.DEBUG;        
        }        

        @Override        
        @H_502_21@protected List<ReactPackage> getPackages() {            
            @H_502_21@return Arrays.<ReactPackage>asList(                    
                @H_502_21@new MainReactPackage(),@H_502_21@new JPushPackage(SHUTDOWN_TOAST,SHUTDOWN_LOG)              
            );        
        }    
    };    

    @Override    
    @H_502_21@public ReactNativeHost getReactNativeHost() {        
        @H_502_21@return mReactNativeHost;    
    }
}

这样就完成了。在 Android Stu@R_502_410@ 中 sync 一下,可以看到 jpush-react-native 作为 Library Module 导进来了。打开 JPushModule 类,看到其中的 onReceive 方法通知的处理都在这一块。在极光推送后台发送通知(也可以使用 服务端 sdk)后,客户端 sdk 收到通知后会回调到 onReceive 方法,在 onReceive 中可以做一些定制化的操作。比如收到通知后,点击通知打开特定的界面:

@H_502_21@public @H_502_21@static @H_502_21@class JPushReceiver @H_502_21@extends BroadcastReceiver {    
    @H_502_21@public JPushReceiver() {        
        HeadlessJsTaskService.acquireWakeLockNow(mRAC);    
    }    

    @Override    
    @H_502_21@public @H_502_21@void onReceive(Context context,Intent data) {
    ...
    } @H_502_21@else @H_502_21@if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(data.getAction())) {    
        Logger.d(TAG,"用户点击打开了通知");
        Intent intent = @H_502_21@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 = @H_502_21@new Intent();
        detailIntent.setClassName(context.getPackageName(),context.getPackageName() + ".SecondActivity");
        detailIntent.putExtras(bundle);
        Intent[] intents = {intent,detailIntent};
        // 同时启动 MainActivity 以及 SecondActivity
        context.startActivities(intents);
        // 或者回调 JS 的某个方法
    }
}

...

 @ReactMethod
    @H_502_21@public @H_502_21@void finishActivity() {
        Activity activity = getCurrentActivity();
        @H_502_21@if (activity != @H_502_21@null) {
            activity.finish();
        }
    }

上面的例子中,我们在收到点击通知的事件时,打开一个特定的界面。这个界面在 Native 中创建(这样做的好处在于还可以实现一些特定的需求,比如收到通知后,如果存在 SecondActivity,则让位于 SecondActivity 之上的界面全部弹出,如果不存在,则创建等等之类的需求),但是还是用 JS 的代码来渲染界面,这对于熟悉 JS 的同学来说,再好不过。要做到这一点,首先我们创建一个 SecondActivity (与 MainActivity 同级)类:

SecondActivity.java

@H_502_21@public @H_502_21@class SecondActivity @H_502_21@extends ReactActivity {

    @Override
    @H_502_21@protected String getMainComponentName() {
        // 注意这个名字与 JS 对应的 Component 中 
        // AppRegistry.registerComponent 方法的第一个参数相同
        @H_502_21@return "SecondActivity";
    }
}

然后在 AndroidManifest 注册 SecondActivity:

AndroidManifest

<activity android:name=".SecondActivity" />

在 React Native 项目下新建一个文件夹 react-native-android,专门用来存放 js 相关的文件。新建 second.js 文件

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 @H_502_21@class second @H_502_21@extends React.Component {
  constructor(props) {
    @H_502_21@super(props);
  }

  onBackPress = () => {
    let navigator = @H_502_21@this.props.navigator;
    @H_502_21@if (navigator != undefined) {
      @H_502_21@this.props.navigator.pop();
    } @H_502_21@else {
      console.log("finishing second activity");
      JPushModule.finishActivity();
    }
  }

  onButtonPress = () => {
    console.log("will jump to setting page");
    let navigator = @H_502_21@this.props.navigator;
    @H_502_21@if (navigator != undefined) {
      @H_502_21@this.props.navigator.push({
        name: "setActivity"
      });
    } @H_502_21@else {

    }

  }

  render() {
    @H_502_21@return (
      <View>
        <TouchableHighlight
          style={styles.backBtn}
          underlayColor = '#e4083f'
          activeOpacity = {0.5}
          onPress = {@H_502_21@this.onBackPress}>
          <Text>
            Back
          </Text>
        </TouchableHighlight>
        <Text
          style={styles.welcome}> 
          Welcome ! 
        </Text> 
        <TouchableHighlight underlayColor = '#e4083f'
          activeOpacity = {0.5}
          style = {styles.btnStyle}
          onPress = {@H_502_21@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,alignSelf: 'center',justifyContent: 'center'
  },btnTextStyle: {
    textAlign: 'center',fontSize: 25,color: '#ffffff'
  },});

AppRegistry.registerComponent('SecondActivity',() => second);

就这样,大功告成!接下来可以在 index.android.js 中注册路由,使得在 JS 中也可以跳转到这个界面。源码请戳这里

总结

以上就是在 React Native 中以混合的方式开发应用的大概过程。用这种方式可以马上使用丰富的原生平台第三方库,只是在 Native 部分需要写些代码,但是花费的代价远远小于自己用 JS 的方式再实现一遍。


作者:KenChoi - 极光

原文:你不可不知的 React Native 混合用法(Android 篇)

知乎专栏:极光日报

原文链接:https://www.f2er.com/react/304062.html

猜你在找的React相关文章