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

此博客基于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中添加一个求和函数

/**
 * 带返回结果的函数
 */
@ReactMethod
public 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调用然后调用发送事件函数
@ReactMethod
public 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

源码下载地址

推荐阅读:

猜你喜欢

转载自blog.csdn.net/a_zhon/article/details/78255146