我有一个任务,我需要为 Android 设备的 React Native 项目添加一个 Native 功能。
我遵循了这个 [tutorial][1],它非常简单。但不幸的是,我仍然无法从 JS 层访问我的 Native 功能。
这是我的代码的样子。
SimpleTestModule.java
:
package com.reactnativesampleapp;
import android.util.Log;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
public class SimpleTestModule extends ReactContextBaseJavaModule {
SimpleTestModule(ReactApplicationContext context) {
super(context);
}
@Override
public String getName() {
return "SimpleTestModule";
}
@ReactMethod
public void simplePublicMethod() {
Log.d("SimpleTestModule", "Some cool log!");
}
}
SimpleTestPackage.java
:
package com.reactnativesampleapp;
import android.util.Log;
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 SimpleTestPackage implements ReactPackage {
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<NativeModule> createNativeModules(
ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new SimpleTestModule(reactContext));
Log.d("SimpleTestPackage", "Log just to check if this code gets executed");
return modules;
}
}
最后,这是我的MainApplication.java
:
package com.reactnativesampleapp;
import android.app.Application;
import android.content.Context;
import android.net.Uri;
import android.util.Log;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;
import com.makeupreactnativesampleapp.generated.BasePackageList;
import org.unimodules.adapters.react.ReactAdapterPackage;
import org.unimodules.adapters.react.ModuleRegistryAdapter;
import org.unimodules.adapters.react.ReactModuleRegistryProvider;
import org.unimodules.core.interfaces.Package;
import org.unimodules.core.interfaces.SingletonModule;
import expo.modules.constants.ConstantsPackage;
import expo.modules.permissions.PermissionsPackage;
import expo.modules.filesystem.FileSystemPackage;
import expo.modules.updates.UpdatesController;
import com.facebook.react.bridge.JSIModulePackage;
import com.swmansion.reanimated.ReanimatedJSIModulePackage;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Nullable;
public class MainApplication extends Application implements ReactApplication {
private final ReactModuleRegistryProvider mModuleRegistryProvider = new ReactModuleRegistryProvider(
new BasePackageList().getPackageList()
);
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
Log.d("Eugene", "getPackages!");
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(new ModuleRegistryAdapter(mModuleRegistryProvider));
packages.add(new SimpleTestPackage());
return packages;
}
@Override
protected String getJSMainModuleName() {
return "index";
}
@Override
protected JSIModulePackage getJSIModulePackage() {
return new ReanimatedJSIModulePackage();
}
@Override
protected @Nullable String getJSBundleFile() {
if (BuildConfig.DEBUG) {
return super.getJSBundleFile();
} else {
return UpdatesController.getInstance().getLaunchAssetFile();
}
}
@Override
protected @Nullable String getBundleAssetName() {
if (BuildConfig.DEBUG) {
return super.getBundleAssetName();
} else {
return UpdatesController.getInstance().getBundleAssetName();
}
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
if (!BuildConfig.DEBUG) {
UpdatesController.initialize(this);
}
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
}
/**
* Loads Flipper in React Native templates. Call this in the onCreate method with something like
* initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
*
* @param context
* @param reactInstanceManager
*/
private static void initializeFlipper(
Context context, ReactInstanceManager reactInstanceManager) {
if (BuildConfig.DEBUG) {
try {
/*
We use reflection here to pick up the class that initializes Flipper,
since Flipper library is not available in release mode
*/
Class<?> aClass = Class.forName("com.makeupreactnativesampleapp.ReactNativeFlipper");
aClass
.getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
.invoke(null, context, reactInstanceManager);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
这是我使用本机模块的 JS 文件:
import React from 'react';
import {
StyleSheet,
SafeAreaView,
NativeModules } from 'react-native';
const { SimpleTestModule } = NativeModules;
export default function App() {
SimpleTestModule.simplePublicMethod();
return (
<SafeAreaView style={styles.container}>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: "column",
backgroundColor: "#fff",
justifyContent: "space-around",
alignItems: "center",
paddingTop: Platform.OS === "android" ? StatusBar.currentHeight : 0,
});
添加所有内容后,我通过清理 Android 项目./gradlew clean
并运行npm run android
几点注意事项:
- 我已经在我的 Package 类中添加了一个日志,只是为了查看它是否被执行。不幸的是,日志从未出现,所以我猜它没有被执行
- 当我运行时
npm run android
,编译成功,但.apk
无法在设备上自动启动。这是否表明我的设置存在严重问题?
这是执行结束时的日志npm run android
:
BUILD SUCCESSFUL in 49s
508 actionable tasks: 508 executed
info Connecting to the development server...
warn Failed to connect to development server using "adb reverse": spawnSync adb ENOENT
info Starting the app...
error Failed to start the app. Run CLI with --verbose flag for more details.
Error: spawnSync adb ENOENT
at Object.spawnSync (node:internal/child_process:1086:20)
[1]: https://reactnative.dev/docs/native-modules-android
- 当我通过在设备上运行 Android 应用程序
Expo
时,当应用程序启动时我有这样的日志:
` 错误:无法从 /Users/superyevhen/Documents/Work/Resources/releases/MakeupReactNativeSampleApp/ 解析模块 ./debugger-ui/debuggerWorker.aca173c4。:
None of these files exist:
* debugger-ui/debuggerWorker.aca173c4(.native|.native.ts|.ts|.native.tsx|.tsx|.native.js|.js|.native.jsx|.jsx|.native.json|.json)
* debugger-ui/debuggerWorker.aca173c4/index(.native|.native.ts|.ts|.native.tsx|.tsx|.native.js|.js|.native.jsx|.jsx|.native.json|.json)
at ModuleResolver.resolveDependency (/Users/superyevhen/Documents/Work/Resources/releases/MakeupReactNativeSampleApp/node_modules/metro/src/node-haste/DependencyGraph/ModuleResolution.js:168:15)
at DependencyGraph.resolveDependency (/Users/superyevhen/Documents/Work/Resources/releases/MakeupReactNativeSampleApp/node_modules/metro/src/node-haste/DependencyGraph.js:353:43)
at /Users/superyevhen/Documents/Work/Resources/releases/MakeupReactNativeSampleApp/node_modules/metro/src/lib/transformHelpers.js:271:42
at /Users/superyevhen/Documents/Work/Resources/releases/MakeupReactNativeSampleApp/node_modules/metro/src/Server.js:1097:37
at Generator.next (<anonymous>)
at asyncGeneratorStep (/Users/superyevhen/Documents/Work/Resources/releases/MakeupReactNativeSampleApp/node_modules/metro/src/Server.js:99:24)
at _next (/Users/superyevhen/Documents/Work/Resources/releases/MakeupReactNativeSampleApp/node_modules/metro/src/Server.js:119:9)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
Error: Unable to resolve module ./debugger-ui/debuggerWorker.aca173c4 from /Users/superyevhen/Documents/Work/Resources/releases/MakeupReactNativeSampleApp/.:`
此消息重复多次(实际上是 7 次),但应用程序正在运行。我仍然可以成功修改 JS 层并查看更改,但我的原生模块仍然不存在。这可能是问题的根本原因吗?
任何帮助,将不胜感激。我试图尽可能准确,但如果您需要任何其他信息来分享专业知识,请告诉我。提前致谢!