按照个人理解,RN和Android原生混合开发分为两种情况,第一种是以RN为主,原生为辅的混合开发,第二种则是以原生为主RN为辅的混合开发,最近几篇文章尽量以这两种情况区分,做一个大概整体的梳理

这篇文章主要讲一下以RN为主 调用Android原生函数的基本使用方法,先上图

reactnative打开android原生页面 reactnative调用原生sdk_Android


下面看具体流程:

1,新建项目,在命令行初始化一个RN项目,这一步比较简单 就不贴图了

2、 Android原生部分代码,分三步:实现ReactContextBaseJavaModule,添加到NativeModules,Application中注册,下面看详细代码

继承ReactContextBaseJavaModule类,实现getName()方法,返回暴露给RN的模块名字,并且在这个类中实现自己需要的方法(比如下面例子中的getResult()和jumpActivity())

package com.demo2.rn_module;

import android.app.Activity;
import android.content.Intent;

import com.demo2.SecondActivity;
import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

public class AndroidTest extends ReactContextBaseJavaModule implements ActivityEventListener {


    public AndroidTest(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    //用ReactNative注解,标示此方法是可以被RN调用的
    @ReactMethod
    public void getResult(int a, int b, Promise promise) {
        int c = a + b;
        promise.resolve(c);
    }

    //用ReactNative注解,标示此方法是可以被RN调用的
    @ReactMethod
    public void jumpActivity() {
        Intent intent = new Intent(getCurrentActivity(), SecondActivity.class);
        getCurrentActivity().startActivity(intent);
    }

    //返回模块名字,方便在RN中引用
    @Override
    public String getName() {
        return "AndroidTest";
    }

    //这两方法是ActivityEventListener接口中的,方便处理一些由此模块跳转后返回的回调事件
    @Override
    public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {

    }

    @Override
    public void onNewIntent(Intent intent) {

    }
}

实现ReactPackage接口,实现里面的方法,将刚才新建的AndroidTest这个Module添加到NativeModules里面

package com.demo2.rn_module;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class AndroidPackage implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> list = new ArrayList<>();
        //添加到NativeModules
        AndroidTest androidTest = new AndroidTest(reactContext);
        list.add(androidTest);
        return list;
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

继承Application并实现ReactApplication,将刚才AndroidPackage 注册到RN,如下代码:

package com.demo2;

import android.app.Application;

import com.demo2.rn_module.AndroidPackage;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;

import java.util.Arrays;
import java.util.List;

public class MainApplication extends Application implements ReactApplication {

    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 AndroidPackage()

            );
        }

        @Override
        protected String getJSMainModuleName() {
            return "index";
        }
    };

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

    @Override
    public void onCreate() {
        super.onCreate();
        SoLoader.init(this, /* native exopackage */ false);
    }
}

3、RN中的代码

新建一个AndroidConnent.js,这个JS文件就是为了导包用的,要不从引用的地方导太麻烦

import {NativeModules} from 'react-native';
export default NativeModules.AndroidTest;

RN页面实现

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow
 */

import React, {Component} from 'react';
import {Platform, StyleSheet, Text, Button, View, Dimensions, ToastAndroid} from 'react-native';
import AndroidTest from "./AndroidConnent";

const ScreenWidth = Dimensions.get("window").width;
const instructions = Platform.select({
    ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu',
    android:
    'Double tap R on your keyboard to reload,\n' +
    'Shake or press menu button for dev menu',
});

type Props = {};
export default class App extends Component<Props> {
    render() {
        return (
            <View style={styles.container}>
                <Button
                    style={{width: ScreenWidth}}
                    title="RN调用Android原生方法"
                    onPress={this.onClick}
                />
                <Button
                    style={{width: ScreenWidth}}
                    title="RN跳转Android原生界面"
                    onPress={this.jump}
                />
            </View>
        );
    }

    onClick() {
        /*AndroidTest是Android原生中getName中返回的字符串*/
        AndroidTest.getResult(1, 2).then(result => {
            ToastAndroid.show(result + "", 1000);
        })
    }



    jump() {
        AndroidTest.jumpActivity();
    }


}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
    welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    instructions: {
        textAlign: 'center',
        color: '#333333',
        marginBottom: 5,
    },
});

以上就是RN中调用Android原生模块中函数的基本流程,简单的RN跳转原生界面也是一样的流程,只需要在ReactContextBaseJavaModule的子类AndroidTest中多加一个jumpActivity()方法就可以了,携带参数的情况也是一样的,最终传递参数还是在原Android原生里面传递的

还有一个Android和RN混合开发的demo,需要的可以下载参考,demo包含了
1、Android加载RN页面
2、Android调用RN函数
3、RN调用Android函数
传送门

<完>