此博客基于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