ReactNative基础(七)js代码与原生代码进行交互、打包APK

来源:互联网 发布:js获取当前数组下标 编辑:程序博客网 时间:2024/06/08 09:12

此博客基于react-native-0.49.3

前面两篇博文已经将react-navigation里面三个重要的导航说完了(不是很高深,毕竟对于初学者还是够了的)、那么现在就可以来搞点事情了。

与原生代码进行交互、通信、调用原生api

  • 与原生代码交互

使用我们的开发神器Android Studio打开我们项目根目录下的android项目,这样就可以直接在Android Studio上愉快的写代码了。

  • 首先我们需要创建一个原生模块来继承ReactContextBaseJavaModule并实现getName()函数
  • 一个最简单的Module,getName()返回的字符串等下在js文件中会使用到
public class AndroidModule extends ReactContextBaseJavaModule {    public AndroidModule(ReactApplicationContext reactContext) {        super(reactContext);    }    @Override    public String getName() {        return "AndroidModule";    }}

模块写好了就需要将它注册到ReactNative中,需要创建一个类 实现 ReactPackage 注册新创建的AndroidModule

public class ReactPackageApp implements ReactPackage {    @Override    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {        List<NativeModule> modules = new ArrayList<>();        //注册模块        modules.add(new AndroidModule(reactContext));        //有多个模块只需要在这里继续add即可        return modules;    }    @Override    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {        return Collections.emptyList();    }}
  • 模块注册好了还差最后一步了、注册ReactPackageApp,打开项目中默认创建好的MainApplication.java文件
public class MainApplication extends Application implements ReactApplication {    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {        //...        @Override        protected List<ReactPackage> getPackages() {            return Arrays.asList(                    new MainReactPackage(),                    //注册我们的package                    new ReactPackageApp());        }        //...    };}

模块的初始化操作现在已经全部完成了那就要来实践一下了,调用一个Android里的函数。

  • 在我们的AndroidModule中添加函数供js调用,如下代码:
public class AndroidModule extends ReactContextBaseJavaModule {    private Context context;    public AndroidModule(ReactApplicationContext reactContext) {        super(reactContext);        context = reactContext;    }    @Override    public String getName() {        return "AndroidModule";    }    //函数需要的注解,才能调用    @ReactMethod    public void showToast(String msg) {        Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();    }}
  • 回到react native中在App.js文件中引入这个Module并调用showToast函数
import React, {Component} from 'react';import {    Platform,    StyleSheet,    Text,    View,    TouchableOpacity,    NativeModules,} from 'react-native';/** * 导入我们创建的Module */const Android = NativeModules.AndroidModule;//这个名字则是上面所提到的export default class App extends Component<{}> {    render() {        return (            <View style={styles.container}>                <TouchableOpacity style={styles.button} activeOpacity={0.5}                                  onPress={() => this.toast()}>                    <Text style={{color: 'white'}}>吐丝</Text>                </TouchableOpacity>            </View>        );    }    toast() {        Android.showToast('调用成功');    }    //由于篇幅原因,样式代码省略可以前往源码处查看

效果图:

react native 调用原生代码基本上就这些流程(ios的我暂时还不会,有大神的话可以对源码发起修改)

  • 那我们再来实现一个调用拨号界面实现拨打电话的功能
  • 继续在AndroidModule中添加一个拨打电话的函数
    //返回给JavaScrips使用的变量    @Override    public Map<String, Object> getConstants() {        final Map<String, Object> constants = new HashMap<>();        constants.put("TEL", "10010");        return constants;    }    @ReactMethod    public void callPhone(String tel) {        Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + tel));        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);        context.startActivity(intent);    }
  • App.js文件中只需要继续调用即可
//Android.TEL 这个则是访问上面 getConstants() 函数返回的常量值call() {    Android.callPhone(Android.TEL);}

效果图:

注意:要导出一个方法给JavaScript使用,Java方法需要使用注解@ReactMethod,方法的返回类型必须为void。那需要返回值怎么办呢?Rn提供了两种方式:使用回调函数或者发送事件。

1.使用回调函数,在AndroidModule中添加一个求和函数

/** * 带返回结果的函数 */@ReactMethodpublic void haveCallback(int a, int b, Callback callback) {    int sum = a + b;    //返回结果    callback.invoke(sum);}
  • Rn中直接调用就可以了
sum() {    Android.haveCallback(10, 45, (sum) => {        Android.showToast('结果为:'+sum);    });}

效果图:

2.Android往JavaScript中发送事件

  • AndroidModule中添加一个函数,让ReactNative调用然后调用发送事件函数
@ReactMethodpublic void sendEvent() {    sendEvent("测试事件");}private void sendEvent(String eventName) {    WritableMap params = Arguments.createMap();    params.putString("NAME", "阿钟");    context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)            .emit(eventName, params);}
  • JavaScript中调用sendEvent,这样就可以模拟一个事件发送了
//组件渲染完成 注册事件监听componentWillMount() {    DeviceEventEmitter.addListener('测试事件', function (e: Event) {        console.log(e);        console.log(e['NAME']);//从event中取出我们存储的值    });}

效果图:
这里写图片描述

东西都写好了是不是迫不及待的想分享给你的基友呢!那就需要将这个项目进行打包生成apk就可以了

这里写图片描述

Tips

//为了更好的视频不同的端,所以我们需要知道当前代码是跑在哪个平台var platform = Platform.OS//不要忘记引人包哦
  • 首先需要创建一个jks签名文件,这个就通过AndroidStudio来生成了

点击 Build > Generate Signed APK > Create New… 生成一个jks文件

这里写图片描述
* 将创建好的签名文件复制到项目的./android/app/xxx.jks目录下
* 在build.gradle中添加签名信息

android {    signingConfigs {        config {            keyAlias 'test'            keyPassword '123456'            storeFile file('./Test.jks')            storePassword '123456'        }    }    //...    buildTypes {        release {            //...            signingConfig signingConfigs.config        }    }    //...}
  • 最后只需要在Terminal中切换到项目根目录下执行如下命令,生成好的apk生成在./android/app/build/outputs/apk/app-release.apk

  • Mac 用户执行

$ cd android && ./gradlew assembleRelease
  • Windows 用户执行
$ cd android && gradlew assembleRelease

源码下载地址

推荐阅读:

  • ReactNative基础(一)编写一个登录页面
  • ReactNative基础(二)了解组件的生命周期
  • ReactNative基础(三)了解ScrollView并打造一个Banner效果
  • ReactNative基础(四)了解ListView的使用、实现GridView效果、编写一个真实网络请求案例
  • ReactNative基础(五)使用react-navigation实现页面的跳转、参数的传递
  • ReactNative基础(六)使用react-navigation实现页面导航布局效果(TabNavigator)
原创粉丝点击