跳到主要内容

使用原生模块

基本模块

在开发RN是不可避免使用到原生模块,而大多数的原生模块集成进来都比较简单,例如duxui使用到的react-native-view-shotreact-native-fast-shadow只需要在模块的package.json中添加依赖

添加依赖之后需要重新编译
android: yarn android --app=模块
ios: yarn ios --app=模块

{
"dependencies": {
"b-validate": "^1.5.3",
"react-native-view-shot": "~3.8.0",
"react-native-fast-shadow": "~0.1.1",
"array-tree-filter": "^2.1.0"
}
}
信息

内容会完整的和package.json进行合并

复杂模块

有的模块除了添加依赖项之外,还需要对原生的内容进行一些处理,比如说微信模块 react-native-wechat-lib

package.json

{
"dependencies": {
"react-native-wechat-lib": "^3.0.4",
"wechat-jssdk": "^5.1.0"
}
}

根据文档,除了添加依赖以外,还需要进行下面这些操作

安卓:

  • 添加 proguard
  • 新建 WXEntryActivity.java 用于回调处理
  • 新建 WXPayEntryActivity.java 用于支付回调处理
  • 添加 <package android:name="com.tencent.mm" /> 用于跳转到微信的白名单
  • 添加 .wxapi.WXEntryActivity
  • 添加 .wxapi.WXPayEntryActivity

ios:

  • 由于插件bug,需要添加 pod 依赖项 pod 'WechatOpenSDK'
  • 修改 AppDelegate.h 入口文件
  • 修改 AppDelegate.mm 文件进行一些处理
  • Info.plist 添加 Schemes 和 BundleURLTypes 和 applinks
  • 在项目配置中,添加 UniversalLink

其他:

  • 通过patch修复当前版本的一个bug

下面将一步一步的来实现这些修改,要实现这些修改,需要通过cli提供的模块处理功能,首先在模块新建一个文件夹 update,在文件夹下新建 index.js, 使用 module.exports 导出一个空对象

module.exports = {

}
信息

文件路径是 update/index.js,cli会识别这个路径

下面将使用insert预埋点功能将文档需要添加的内容添加到对应的文件,insert可以完成下面这些内容:

  • 添加 proguard
  • 由于插件bug,需要添加 pod 依赖项 pod 'WechatOpenSDK'
  • 修改 AppDelegate.h 入口文件
  • 修改 AppDelegate.mm 文件进行一些处理
module.exports = {
insert: {
'android/app/proguard-rules.pro': {
'content': `
##### 微信 ######
-keep class com.tencent.mm.opensdk.** { *; }
-keep class com.tencent.wxop.** { *; }
-keep class com.tencent.mm.sdk.** { *; }`
},
'ios/Podfile': {
'podEnd': ` pod 'WechatOpenSDK'`
},
'ios/duxapp/AppDelegate.h': {
import: ' #import "WXApi.h"',
'appDelegate.protocol': ' ,WXApiDelegate'
},
'ios/duxapp/AppDelegate.mm': {
import: '#import <React/RCTLinkingManager.h>',
appDelegate: `// react-native-wechat-lib start

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [WXApi handleOpenURL:url delegate:self];
}

- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void(^)(NSArray<id<UIUserActivityRestoring>> * __nullable
restorableObjects))restorationHandler {
// 触发回调方法
[RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
return [WXApi handleOpenUniversalLink:userActivity
delegate:self];
}

// Universal Links 配置文件, 没使用的话可以忽略。
// ios 9.0+
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
options:(NSDictionary<NSString*, id> *)options
{
// Triggers a callback event.
// 触发回调事件
[RCTLinkingManager application:application openURL:url options:options];
return [WXApi handleOpenURL:url delegate:self];
}
// react-native-wechat-lib end`
}
}
}

下面使用文件创建功能创建两个回调所需的文件

  • 新建 WXEntryActivity.java 用于回调处理
  • 新建 WXPayEntryActivity.java 用于支付回调处理

因为按照要求,需要用到当前app的包名,所以需要将导出的内容修改为一个函数,函数传入的参数中,能获取到当前项目 duxapp.rn.js 中的配置,config字段就是这个配置,从中获取到appid,添加到文件对应位置

module.exports = ({ config }) => {
const { android } = config
return {
// ...
create: {
'android/app/src/main/java/cn/duxapp/wxapi/WXEntryActivity.java': `package ${android.appid}.wxapi;

import android.app.Activity;
import android.os.Bundle;
import com.wechatlib.WeChatLibModule;

public class WXEntryActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WeChatLibModule.handleIntent(getIntent());
finish();
}
}
`,
'android/app/src/main/java/cn/duxapp/wxapi/WXPayEntryActivity.java': `package ${android.appid}.wxapi;

import android.app.Activity;
import android.os.Bundle;
import com.wechatlib.WeChatLibModule;

public class WXPayEntryActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WeChatLibModule.handleIntent(getIntent());
finish();
}
}
`
},
}
}
信息

所有安卓文件路径中的cn/duxapp 此文件夹路径都是固定的,可放心使用

下面通过安卓的xml处理功能完成这些任务

  • 添加 <package android:name="com.tencent.mm" /> 用于跳转到微信的白名单
  • 添加 .wxapi.WXEntryActivity
  • 添加 .wxapi.WXPayEntryActivity
module.exports = ({ config }) => {
const { android } = config
return {
// ...
android: {
xml: {
'app/src/main/AndroidManifest.xml': {
tag: {
queries: {
child: '<package android:name="com.tencent.mm" />'
}
},
attr: {
'android:name=".MainApplication"': {
child: `<activity
android:name=".wxapi.WXEntryActivity"
android:label="@string/app_name"
android:exported="true"
android:taskAffinity="${android.appid}"
android:launchMode="singleTask"
/>
<activity
android:name=".wxapi.WXPayEntryActivity"
android:label="@string/app_name"
android:exported="true"
/>`
}
}
}
}
},
}
}
信息

此处的操作是通过 xmldom 操作实现的,其功能类似于 jsdom,可以把xml视为dom进行操作

  • tag 标签查询器
  • attr 属性查询器

下面通过IOS的plist处理功能完成这些任务

  • Info.plist 添加 Schemes 和 BundleURLTypes 和 applinks
module.exports = ({ config }) => {
const { android } = config
return {
// ...
ios: {
plist: {
'duxapp/Info.plist': {
CFBundleURLTypes: [
{
CFBundleTypeRole: 'Editor',
CFBundleURLName: 'weixin',
CFBundleURLSchemes: [
option?.wechat?.appid || 'wx'
]
}
],
LSApplicationQueriesSchemes: ['weixin', 'wechat', 'weixinULAPI']
},
'duxapp/duxapp.entitlements': {
'com.apple.developer.associated-domains': [
`applinks:${option?.wechat?.applinks || 'duxapp.cn'}`
]
}
}
}
}
}

可以看到这里读取了 option.wechat 中的两个配置,那么你也需要在配置对应位置添加上这些配置

信息

需要注意的是在安卓或者ios配置下的文件路径,不需要添加android或者ios前缀

由于当前版本的插件在运行时存在一个报错,需要通过patch修复这个错误

在update文件夹下创建一个copy文件夹,此文件夹下的所有文件将会被复制到当前项目对应的位置下面

copy下创建 patches 文件夹,文件夹下创建文件 react-native-wechat-lib+3.0.4.patch

整体文件路径看起来是这样的 wechat/update/copy/patches/react-native-wechat-lib+3.0.4.patch

放入下面的内容

diff --git a/node_modules/react-native-wechat-lib/src/index.js b/node_modules/react-native-wechat-lib/src/index.js
index 3bb59a6..6ddb35e 100644
--- a/node_modules/react-native-wechat-lib/src/index.js
+++ b/node_modules/react-native-wechat-lib/src/index.js
@@ -4,11 +4,14 @@ import { DeviceEventEmitter, NativeModules, Platform } from 'react-native';
import { EventEmitter } from 'events';

let isAppRegistered = false;
-let { WeChat, WechatLib } = NativeModules;
+let { WeChat, WechatLib, RCTWeChat } = NativeModules;

if (WeChat == null) {
WeChat = WechatLib;
}
+if (WeChat == null) {
+ WeChat = RCTWeChat;
+}

// Event emitter to dispatch request and response from WeChat.
const emitter = new EventEmitter();

到此整个模块的安装过程完成,重新编译app即可使用